Java не содержит диалоговое окно, когда кадр не виден

1

У меня возникла проблема со скрытыми компонентами, которые не располагаются должным образом при работе с несколькими кадрами.

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

Например:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class MultipleFrameTest {
    public static void main(String[] args) {
        TestFrame   test   = new TestFrame();
        FrameTester tester = new FrameTester(test);

        tester.setVisible(true);
    }

    private static class TestFrame extends JFrame {
        JDialog dialog;
        java.util.Timer timer;

        public TestFrame() {
            super("Test Frame");

            this.dialog = null;
            this.timer  = new java.util.Timer("Frame Timer");

            fillFrame();
            pack();
        }

        private void fillFrame() {
            JButton dialogButton = new JButton("Launch Model Dialog");
            dialogButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent event) {
                    JOptionPane pane = new JOptionPane("Wait for 2 seconds",
                        JOptionPane.QUESTION_MESSAGE,
                        JOptionPane.OK_CANCEL_OPTION);
                    dialog = pane.createDialog(TestFrame.this, "Question");

                    timer.schedule(new TimerTask() {
                        public void run() {
                            SwingUtilities.invokeLater(new Runnable() {
                                public void run() {
                                    TestFrame.this.setVisible(false);

                                    if (dialog != null) {
                                        dialog.setVisible(false);
                                        dialog.dispose();
                                        dialog = null;
                                    }
                                }
                            });
                        }
                    }, 2 * 1000);

                    dialog.setVisible(true);
                }
            });

            JPanel panel = new JPanel();
            panel.add(dialogButton);

            add(panel);
        }
    }    

    private static class FrameTester extends JFrame {
        JFrame frame;

        public FrameTester(JFrame frame) {
            super("Frame Tester");

            this.frame = frame;

            fillFrame();
            pack();
        }

        private void fillFrame() {
            JButton toggleButton = new JButton("Toggle Frame Visibility");
            toggleButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent event) {
                    frame.setVisible(!frame.isVisible());
                }
            });

            JPanel panel = new JPanel();
            panel.add(toggleButton);

            add(panel);
        }
    }
}

Чтобы запустить этот пример:

  1. Нажмите кнопку "Переключить рамку видимости". Это покажет TestFrame.
  2. Нажмите кнопку "Запустить модальный диалог". Появится JOptionPane.
  3. Подождите 2 секунды, чтобы TimerTask спрятал TestFrame и TestFrame dispose() JOptionPane.
  4. Нажмите кнопку "Переключить рамку видимости". TestFrame станет видимым, и JOptionPane будет подключен.

Я знаю, что я могу это исправить, TestFrame JOptionPane перед тем, как скрыть TestFrame:

- TestFrame.this.setVisible(false);

  if (dialog != null) {
     dialog.setVisible(false);
     dialog.dispose();
     dialog = null;
  }

+ TestFrame.this.setVisible(false);

Кто-нибудь знает, почему это происходит? Я ожидал, что модальный диалог исчезнет, даже если он будет скрыт, когда он будет удален.

Теги:
modal-dialog
swing
jframe
dispose

1 ответ

4
Лучший ответ

Хотя вы действительно должны рассмотреть комментарий trashgod о использовании нескольких JFrames, хорошей/плохой практике? , вот объяснение, почему вы видите это поведение.

Это происходит из-за того, что перед диалоговым окном скрывается окно владельца. Когда вы делаете такую вещь, принадлежащий диалогу будет помечен как showWithParent и следующий вызов setVisible(true) в кадре автоматически вызовет отображение соответствующего диалога из-за этого флага. Единственный способ избежать этого, как вы сказали в своем вопросе, - сначала скрыть принадлежащий ему диалог, а затем скрыть окно владельца.

Вот выдержка метода Window.hide():

    synchronized(ownedWindowList) {
        for (int i = 0; i < ownedWindowList.size(); i++) {
            Window child = ownedWindowList.elementAt(i).get();
            if ((child != null) && child.visible) {
                child.hide();
                child.showWithParent = true; // See here the flag set to true
            }
        }
    }

и здесь соответствующий экстракт метода Window.show():

       for (int i = 0; i < ownedWindowList.size(); i++) {
            Window child = ownedWindowList.elementAt(i).get();
            if ((child != null) && child.showWithParent) { // Here theh flag is checked
                child.show();
                child.showWithParent = false; // flag is then reset
            }       // endif
        }

Btw, вместо использования этой сложной структуры таймера /TimerTask/invokeLater вы можете просто использовать javax.swing.TimersetRepeats(false)). Таймер Swing всегда запускается в Диспетчере событий.

  • 0
    Спасибо за информацию!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню