2011-10-18 103 views
8

我有一個獨立的Java應用程序,它從數據庫獲取數據並將其顯示在JTable中。當應用程序啓動時,會提示用戶在JDialog中輸入用戶名/密碼。輸入正確的憑證後,將顯示包含數據的主JFrame。在主JFrame中,我有一個註銷按鈕,單擊時應關閉主JFrame並重新顯示登錄JDialog。除了我發現在單擊註銷按鈕時,主JFrame不會消失,一切都基本上正常工作。下面是我的代碼小的工作示例:Java Swing dispose()與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); 
    } 
} 

In MainFrame.java如果我將setVisible(false)這一行改爲dispose(),那麼當我點擊按鈕時JFrame就會消失。我的問題是,爲什麼這個工作與dispose()而不是setVisible(false)?有沒有更好的方式來組織我的代碼?我是Swing的新手,所以如果這是一個基本問題,我很抱歉。謝謝。


EDITED 2011-10-19 10:26 PDT

謝謝大家的幫助。我改變了JDialog有一個空父母,現在一切正常,因爲我想。

+0

爲了更好地幫助越早,張貼[SSCCE(HTTP:// pscode。組織/ sscce.html)。 –

回答

6

看到你發起的JDialog行:

dialog = new MyDialog(this); 

你設置相同的框架對話坐在父框架。你看,一個對話框不能單獨出現,它必須位於父框架之上。

因此,在你的代碼,當你寫:

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

在你告訴框架消失的第一行,然後你告訴出現的對話框中,從而真正告訴對話框出現其父框架。由於父框架是相同的,因此它看起來像保持對您可見。如果你刪除第二行,我相信框架會消失。但是當你告訴框架處置時,它會完全消失,因爲你告訴它不僅要失去可見性,還要從內存中移除它。

然後,當您告訴對話框出現時,它會查找其已放置的JFrame,然後重新初始化並打開。

解決問題的方法是爲JDialog創建一個單獨的新JFrame。那麼不要使用dispose,而只需使用setVisible命令。

-Asaf

+1

它可能就足以讓它重新打開它的父框架。所以,在MyDialog()中進行超級調用:'super(null,「這是JDialog」,false);'。如果主框架處於隱藏狀態,則無論如何都不會收到有意義的輸入,因此沒有必要製作對話框模式。 – millimoose

+0

@Inerdia你是對的,那也是一個選擇。我忘記了模態的布爾值。另外,我相當肯定布爾模式已被棄用,而ModalityType方法現在是首選。 – Asaf

+0

不是真的棄用,至少不是正式的。它指定了哪個布爾值對應於哪種模式類型,所以它可能只是您喜歡哪種風格的問題。 – millimoose

0

我會簡單地給出正確的代碼,在我自己的風格。這當然不是單一的或甚至被證明的最佳解決方案。

在主框架上的setVisible(false)應調用關閉操作,邏輯上爲主框架EXIT_ON_CLOSE。如果該對話框是主框架的子項,則應用程序退出。

所以我做了模態對話框的第二個頂部窗口,其中有一個(JFrame)null作爲父項。因此,你有一個應用程序與兩個頂部窗口。並且模態對話每次都被處置。 我做了模態對話框DO_NOTHING_ON_CLOSE,因爲你不想關閉圖標的功能。 因此,在actionPerformed中的dispose()。 (如果你在任何時候有一個家長,你可以使用getOwner(),而不是母公司複製到現場。)

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

我不認爲setVisible調用關閉操作。它只是隱藏框架/對話框... – Bogdan