Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Modal dialog freezes whole application when whole application loses focus right before it is opened

Once the steps below are taken, the whole application is frozen and the modal dialog cannot be closed.

(This is related to another question but this time we have a reproducible scenario)

The steps:

  • Open dropdown
  • Select "Han-Ra" (the last value in the drop down)

After this, trying to resize or close the modal dialog will not succeed. It reproduces 1 out of 3 times (might be easier to reproduce if you do the selection by arrow down but happens with mouse selection also)

This happens on jdk 1.8 (tried 1.8.0_162 and 1.8.0_144) and jdk 10 (10.0.1) but not when using 1.7 (tried 1.7.0_80)

This is just the most obvious case we could find but it randomly (rarely) happens for most modal dialogs. Anyone else had this problem and found a workaround? We'll report it to Oracle but we'd be more interested in a workaround.

import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

public class FreezePleeze {

    public static final Object[] ALL_THE_SINGLE_LADIES = {"Rahan", "Crao", "Naouna", "Han-ra"};

    public static void main(String[] args) {
        new FreezePleeze();
    }

    public FreezePleeze() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JButton push_me = new JButton("Push me");
                JFrame frame = new JFrame("Mmmmm");
                JPanel containerPanel = new JPanel();
                frame.add(containerPanel);
                final JComboBox<Object> comboBox = new JComboBox<>(ALL_THE_SINGLE_LADIES);
                containerPanel.add(comboBox);
                frame.setSize(300, 300);

                comboBox.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JDialog jDialog = new JDialog((JFrame) null, true);
                        jDialog.add(push_me);
                        if (comboBox.getSelectedIndex() == ALL_THE_SINGLE_LADIES.length - 1) {
                            jDialog.setLocationRelativeTo(frame);
                            jDialog.setSize(300, 300);
                            jDialog.setVisible(true);
                        }
                    }
                });

                comboBox.addPopupMenuListener(new PopupMenuListener() {
                    @Override
                    public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                    }

                    @Override
                    public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                        try {
                            Robot robot = new Robot();
                            robot.keyPress(KeyEvent.VK_WINDOWS);
                            robot.keyRelease(KeyEvent.VK_WINDOWS);
                        } catch (AWTException e1) {
                            e1.printStackTrace();
                        }
                        push_me.setText("Finished counting");
                    }

                    @Override
                    public void popupMenuCanceled(PopupMenuEvent e) {
                    }
                });
                frame.setVisible(true);
            }
        });
    }
}
like image 576
Vlad Topala Avatar asked Jan 23 '26 21:01

Vlad Topala


1 Answers

I can reproduce your problem. The solution is to submit the correct window to the constructor of your dialog:

Example:

JDialog jDialog = new JDialog(frame, true);

or, if you have no window instance when you create a dialog:

JDialog jDialog = new JDialog(FocusManager.getCurrentKeyboardFocusManager().getActiveWindow(),
                            ModalityType.APPLICATION_MODAL);
like image 147
Sergiy Medvynskyy Avatar answered Jan 26 '26 11:01

Sergiy Medvynskyy