bouncer
bouncer

Reputation: 173

Custom Modal Dialog

I am creating my own dialog which is basically a JPanel set as the glasspane on a JFrame. I want to make my dialog modal in the sense that all the code after the setVisible() is not executed while the dialog is visible and once the dialog is closed, the rest of the code after the setVisible() must continue.

To achieve this I am using a thread to display my dialog. I know that the SwingUtilities.invokeLater() method must be used to update the gui because it is executed in another thread. However my dialog does not show on the screen.

Here is my code example:

final JFrame frame = new JFrame();
frame.setBounds(0, 0, 1024, 768);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);

JButton button = new JButton("Text");
button.setBounds(200, 300, 110, 50);
button.addActionListener(new ActionListener() {

    boolean dispose;

    public void actionPerformed(ActionEvent e) {
        try {
            Thread thread = new Thread(new Runnable() {
                public void run() {
                    final JPanel panelGlass = new JPanel(null);
                    panelGlass.setBounds(frame.getBounds());
                    panelGlass.setBackground(Color.red);
                    frame.setGlassPane(panelGlass);

                    JButton btnClose = new JButton("close");
                    btnClose.setBounds(100, 100, 110, 50);
                    btnClose.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                            dispose = true;
                        }
                    });
                    panelGlass.add(btnClose);

                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            dispose = false;
                            panelGlass.setVisible(true);
                        }
                    });

                    while (!dispose) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                    panelGlass.setVisible(false);
                }
            });
            thread.start();
            thread.join();
        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
});
frame.getContentPane().add(button);

frame.setVisible(true);

Why is my dialog not shown?

Upvotes: 0

Views: 870

Answers (3)

mKorbel
mKorbel

Reputation: 109823

  • frame.getRootPane.setGlassPane

  • your idea is good, but have to consume() events came from keyboard, add there KeyListener only with e.consume() because GlassPane to consume only mouse events

  • create whole Gui with GlassPane too,

  • inside actionperformed to show prepared GlassPane, then to start a Runnable.Thread

  • I have one question here about multiply glasspane

  • use JLayer Java7, based on JXLayer Java6

  • your question is booking example for why reason is SwingWorker implemented in Java

reply from cellphone

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 691933

You can't do that like that since

  • you're accessing Swing components from a thread other than the event disptach thread
  • the event disptach thread, where all the UI painting happens, is completely blocked by the call to Thread.join().

You should be able to do something like what you want with Java 7's SecondaryLoop, but I've never used it.

Upvotes: 1

Tudor
Tudor

Reputation: 62459

The problem is here:

thread.start();
thread.join();

You start the thread but you immediately wait for it to finish. This blocks the UI thread and doesn't allow it to process your SwingUtilities.invokeLater update.

I really don't see any good reason for that join call to exist.

Upvotes: 1

Related Questions