Java Swing dispose()与setVisible(false)

时间:2011-10-18 22:55:24

标签: java swing visibility dispose

我有一个独立的Java应用程序,它从数据库中获取数据并将其显示在JTable中。应用程序启动时,将提示用户输入JDialog中的用户名/密码。输入正确的凭据后,将显示包含数据的主JFrame。在主JFrame上,我有一个注销按钮,当单击时,应该关闭主JFrame并重新显示登录JDialog。一切都在工作,除了我发现点击注销按钮时主JFrame不会消失。下面是我的代码的一个小工作示例:

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);
    }
}

MainFrame.java 中,如果我将setVisible(false)的行更改为dispose(),那么单击按钮时JFrame就会消失。我的问题是,为什么这适用于dispose()而不适用于setVisible(false)?我有更好的方法来组织我的代码吗?我是Swing的新手,所以如果这是一个基本问题,我道歉。谢谢。


已编辑2011-10-19 10:26 PDT

谢谢大家的帮助。我将JDialog更改为null父级,现在一切正常。

2 个答案:

答案 0 :(得分:7)

请参阅启动JDialog的行:

dialog = new MyDialog(this);

您正在设置与对话框所在的父框架相同的框架。你看,一个对话框不能独立出现,它必须位于父框架的顶部。

所以在你的代码中,当你写:

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

在第一行中,您告诉框架消失,然后您告诉对话框出现,这实际上告诉对话框出现在其父框架上。由于父框架是相同的,因此看起来它对您来说是可见的。如果删除第二行,我确定框架会消失。但是当你告诉框架处理它时,它会完全消失,因为你告诉它不仅会失去可见性,还会从内存中移除它。

然后,当您告诉对话框出现时,它会查找其JFrame(已经处理掉),重新初始化并打开。

解决问题的方法是为JDialog创建一个单独的新JFrame。然后不要使用dispose,只需使用setVisible命令。

-Asaf

答案 1 :(得分: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();
    }
}