Java Swing dispose () против setVisible (false) - PullRequest
8 голосов
/ 19 октября 2011

У меня есть отдельное приложение 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, чтобы иметь нулевого родителя, и теперь все работает, как я хотел.

Ответы [ 2 ]

7 голосов
/ 19 октября 2011

См. Строку, где вы запускаете JDialog:

dialog = new MyDialog(this);

Вы устанавливаете тот же кадр, что и родительский кадр, на котором находится диалоговое окно.Видите ли, диалог не может появляться сам по себе, он должен располагаться поверх родительского фрейма.

Так в вашем коде, когда вы пишете:

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

В первомВ строке вы указываете, что рамка исчезла, затем вы говорите, чтобы появилось диалоговое окно, которое действительно указывает диалоговому окну появиться в родительской рамке.Поскольку родительский фрейм одинаков, он выглядит так, будто он остается видимым для вас.Если вы удалите вторую строку, я уверен, что рамка исчезнет.Но когда вы указываете, что фрейм должен быть удален, он полностью исчезает, потому что вы сказали ему не только потерять видимость, но и удалить себя из памяти.

Затем, когда вы говорите диалоговому окну, оно ищет JFrame (которыйбыл утилизирован), повторно инициализирует его и открывает.

Способ решения вашей проблемы - создать отдельный новый JFrame для JDialog.Тогда не используйте dispose и просто используйте команду setVisible.

-Asaf

0 голосов
/ 19 октября 2011

Я просто дам правильный код в своем собственном стиле. Это, конечно, не единственное или даже проверенное лучшее решение.

setVisible (false) на главном кадре должен вызывать операцию закрытия, логически для основного кадра EXIT_ON_CLOSE. Если диалоговое окно является дочерним по отношению к основному кадру, приложение закрывается.

Поэтому я сделал модальное диалоговое окно вторым верхним окном, в котором родительский элемент имеет значение JFrame. Следовательно, у вас есть приложение с двумя верхними окнами. И модальные диалоги располагаются каждый раз. Я сделал модальное диалоговое окно DO_NOTHING_ON_CLOSE, так как вы не хотите, чтобы работал значок Close. Следовательно dispose () в actionPerformed. (Если у вас в любое время есть родитель, вы можете использовать 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();
    }
}
...