2011-10-18 25 views
8

Mam autonomiczną aplikację Java, która pobiera dane z bazy danych i wyświetla je w JTable. Po uruchomieniu aplikacji użytkownik jest proszony o podanie nazwy użytkownika/hasła w JDialogu. Po wprowadzeniu prawidłowych poświadczeń wyświetlana jest główna ramka JFrame zawierająca dane. W głównym oknie JFrame mam przycisk wylogowania, który po kliknięciu powinien zamknąć główną ramkę JFrame i ponownie wyświetlić JDialog logowania. Wszystko w większości działa, ale odkryłem, że główna ramka JFrame nie znika po kliknięciu przycisku wylogowania. Poniżej znajduje się mały przykład pracy mojego kodu:Java Swing dispose() vs. setVisible (false)

Main.java:

import javax.swing.SwingUtilities; 

public class Main { 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       new MainFrame(); 
      } 
     }); 
    } 
} 

MainFrame.java:

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 

public class MainFrame extends JFrame implements ActionListener { 
    private JButton button; 
    private MyDialog dialog; 

    public MainFrame() { 
     super("this is the JFrame"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     dialog = new MyDialog(this); 
     button = new JButton("click me to hide this JFrame and display JDialog"); 
     button.addActionListener(this); 
     add(button); 
     pack(); 
     setVisible(true); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     setVisible(false); // works when changed to dispose(); 
     dialog.setVisible(true); 
    } 
} 

MyDialog.java:

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 


public class MyDialog extends JDialog implements ActionListener { 
    private JFrame parentFrame; 
    private JButton button; 

    public MyDialog(JFrame parentFrame) { 
     super(parentFrame, "this is the JDialog", true); 
     setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 
     this.parentFrame = parentFrame; 
     button = new JButton("click me to hide JDialog and show JFrame"); 
     button.addActionListener(this); 
     add(button); 
     pack(); 
     setVisible(true); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     setVisible(false); 
     parentFrame.setVisible(true); 
    } 
} 

W MainFrame.java jeśli zmienię linię, która mówi setVisible(false) na dispose(), JFrame zniknie po kliknięciu przycisku. Moje pytanie brzmi: dlaczego to działa z dispose(), a nie z setVisible(false)? Czy istnieje lepszy sposób na uporządkowanie mojego kodu? Jestem nowy w Swing, więc przepraszam, jeśli to podstawowe pytanie. Dziękuję Ci.


EDITED 2011-10-19 10:26 PDT

Dziękuję wszystkim za pomoc. Zmieniłem JDialog, aby mieć zerowego rodzica, a teraz wszystko działa tak, jak chciałem.

+0

Dla lepszej pomocy prędzej, dodaj [SSCCE] (http: // pscode. org/sscce.html). –

Odpowiedz

6

Zobacz linię gdzie wszczęcia JDialog:

dialog = new MyDialog(this); 

ustawiasz tę samą klatkę jako ramki nadrzędnej, że siedzi na dialog. Widzisz, okno dialogowe nie może pojawić się samo, musi ono być umieszczone na ramce nadrzędnej.

Więc w kodzie, gdy piszesz:

setVisible(false); // works when changed to dispose(); 
dialog.setVisible(true); 

W pierwszym wierszu powiesz ramka zniknie, wtedy powiesz okno do stawienia się, co naprawdę mówi okno pojawiać się na jego ramki nadrzędnej . Ponieważ ramka nadrzędna jest taka sama, wygląda na to, że pozostaje widoczna dla Ciebie. Jeśli usuniesz drugą linię, jestem pewien, że ramka zniknie. Ale kiedy powiesz ramie, aby się pozbyła, znika całkowicie, ponieważ powiedziałeś jej nie tylko o utracie widoczności, ale także usunięciu się z pamięci.

Następnie, gdy powiesz, że okno dialogowe ma się pojawić, szuka JFrame (która została usunięta), ponownie je zainicjuj i otwórz.

Aby rozwiązać problem, należy utworzyć osobną nową ramkę JFrame dla JDialog. Następnie nie używaj utylizacji i po prostu użyj polecenia setVisible.

-Asaf

+1

Może to wystarczyć, aby ramka nie otworzyła ponownie ramki macierzystej. Stwórz super wywołanie w 'MyDialog()' go: 'super (null," to jest JDialog ", false);'. Jeśli główna ramka jest ukryta, to i tak nie otrzyma znaczących danych wejściowych, więc nie ma powodu, aby modalne było okno dialogowe. – millimoose

+0

@Inerdia Masz rację, to także opcja. Zapomniałem, że boolean jest dla modalności. Ponadto jestem całkiem pewien, że mod boolowskich został przestarzały, a metoda ModalityType jest teraz preferowana. – Asaf

+0

Nie bardzo przestarzałe, przynajmniej nie oficjalnie. Określono, która wartość boolowska odpowiada typowi modalności, więc prawdopodobnie jest to kwestia stylu, który preferujesz. – millimoose

0

Po prostu podam prawidłowy kod w moim własnym stylu. Z pewnością nie jest to jedyne, a nawet sprawdzone, najlepsze rozwiązanie.

setVisible (false) na głównej ramce powinno wywołać operację zamknięcia, logicznie dla głównej ramki EXIT_ON_CLOSE. Jeśli okno dialogowe jest elementem podrzędnym ramki głównej, aplikacja zostaje zamknięta.

Zrobiłem więc modalne okno dialogowe drugie górne okno, które ma null (JFrame) jako rodzic. Stąd masz aplikację z dwoma górnymi oknami. A modalne dialogi są za każdym razem usuwane. Zrobiłem modalne okno dialogowe DO_NOTHING_ON_CLOSE, ponieważ nie chcesz, aby ikona Zamknij działała. Stąd dispose() w actionPerformed. (Jeśli w dowolnym momencie mieć rodzica, można użyć getOwner() zamiast kopiowania rodzica do pola.)

public class Main { 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       MainFrame mainFrame = new MainFrame(); 
       mainFrame.actionPerformed(null); 
      } 
     }); 
    } 
} 


public class MainFrame extends JFrame implements ActionListener { 
    private JButton button; 

    public MainFrame() { 
     super("this is the JFrame"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     button = new JButton("click me to hide this JFrame and display JDialog"); 
     button.addActionListener(this); 
     add(button); 
     pack(); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     MyDialog dialog = new MyDialog(MainFrame.this); 
     dialog.setVisible(true); 
     setVisible(false); 
    } 
} 


public class MyDialog extends JDialog implements ActionListener { 
    private JButton button; 
    private JFrame parentFrame; 

    public MyDialog(JFrame parentFrame) { 
     super((JFrame)null, "this is the JDialog", false); 
     this.parentFrame = parentFrame; 
     setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); 
     button = new JButton("click me to hide JDialog and show JFrame"); 
     button.addActionListener(this); 
     add(button); 
     pack(); 
     setVisible(false); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     parentFrame.setVisible(true); 
     dispose(); 
    } 
} 
+1

Nie sądzę, że setVisible wywołuje operację zamknięcia. Po prostu ukrywa ramkę/dialog ... – Bogdan