Подтвердить что ты не робот

Как закрыть JDialog и получить уведомление слушателей Window Event?

Есть ли способ закрыть JDialog через код, чтобы прослушиватели событий Window все равно были уведомлены? Я попытался просто установить видимость на false и утилизировать, но, похоже, это не так.

4b9b3361

Ответ 1

Закрытие окна (с помощью dispose()) и его скрытие (с помощью setVisible(false)) - это разные операции и производят разные события - и закрытие его из операционной системы - это еще одна другая операция, которая создает еще одно событие.

Все три будут выдавать windowDeactivated, чтобы сообщить вам о потерянном фокусе окна, но dispose() затем произведет windowClosed, а при закрытии из ОС сначала произведет windowClosing. Если вы хотите обрабатывать оба из них одинаково, вы можете установить, что окно будет удалено при закрытии:

window.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

В общем случае setVisible(false) подразумевает, что вы можете снова использовать окно, поэтому он не публикует никаких событий окна (кроме windowDeactivated). Если вы хотите обнаружить скрытие окна, вам нужно использовать ComponentListener;

window.addComponentListener(new ComponentAdapter() {
  @Override
  public void componentHidden(ComponentEvent e) {
    System.out.println("componentHidden()");
  }
})

Обратите внимание, что это будет в значительной степени работать только для явных вызовов setVisible(). Если вам нужно обнаружить скрытие в более общем плане, вы можете использовать HierarchyListener, но это, вероятно, больше проблем, чем это стоит.

  window.addHierarchyListener(new HierarchyListener() {
    @Override
      public void hierarchyChanged(HierarchyEvent e) {
        System.out.println("valid: " + window.isValid());
        System.out.println("showing: " + window.isShowing());
      }
  });

Обратите внимание, что когда вы располагаете окном, вы получите пару HierarchyEvent s, сначала для скрытия, а затем для недействительности, но когда вы спрячете его с помощью setVisible(), он все еще действителен, поэтому вы не получите недействительности.

Ответ 2

У меня, похоже, нет вашей проблемы. Когда я использую код ниже windowDeactivated() вызывается для setVisible (false) или dispose() и windowClosed ( ) также вызывается для dispose().

ClosingDialog.java:

public class ClosingDialog extends JDialog {
    public ClosingDialog(Frame owner, String title, boolean modal) {
        super(owner, title, modal);
        JPanel contentPanel = (JPanel) this.getContentPane();

        JButton setVisButton = new JButton("setVisible( false )");
        setVisButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ClosingDialog.this.setVisible(false);
            }
        });

        JButton disposeButton = new JButton("dispose()");
        disposeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ClosingDialog.this.dispose();
            }
        });

        contentPanel.setLayout(new FlowLayout());

        contentPanel.add(setVisButton);
        contentPanel.add(disposeButton);

        this.addWindowListener(new WindowListener() {
            public void windowActivated(WindowEvent e) {
                System.out.println("windowActivated");
            }

            public void windowClosed(WindowEvent e) {
                System.out.println("windowClosed");
            }

            public void windowClosing(WindowEvent e) {
                System.out.println("windowClosing");
            }

            public void windowDeactivated(WindowEvent e) {
                System.out.println("windowDeactivated");
            }

            public void windowDeiconified(WindowEvent e) {
                System.out.println("windowDeiconified");
            }

            public void windowIconified(WindowEvent e) {
                System.out.println("windowIconified");
            }

            public void windowOpened(WindowEvent e) {
                System.out.println("windowOpened");
            }
        });

        this.setSize(300, 300);
    }
}

Ответ 4

Непроданное предложение:

Вы пытались getWindowListeners(), а затем итерации вокруг окна fireClosed() для каждого из WindowListeners?

EDIT: указанное выше предложение неверно. Хранение его для потомства.

Я боюсь, что вызов dialog.dispose() отлично работает для меня в моем простом примере.

Ответ 5

Я хотел запустить событие windowClosing из кода (точно так же, как если бы пользователь нажал кнопку X), потому что у меня есть дополнительная кнопка закрытия JDialog и требуется тот же WindowListener (который я реализовал с помощью WindowAdapter) для запуска при нажатии кнопки X и нажатии кнопки. Выполнение dispose() только срабатывает windowClosed, а не windowClosing, и я хочу, чтобы сообщение появлялось до закрытия окна, для подтверждения. Я также не смог запустить windowClosing с помощью метода JDialog processWindowEvent, так как он защищен.

Вот как я работал, хотя:

WindowAdapter adapter = (WindowAdapter)jdialog.getWindowListeners()[0];
adapter.windowClosing(new WindowEvent((Window)jdialog, WindowEvent.WINDOW_CLOSING));

Надеюсь, что это поможет кому-то.