避免JOptionPane与动作监听器的干扰

4
我注意到所有的JOptionPane方法都会“干扰”ActionListeners。我需要在打开JOptionPane后保持ActionListener活跃。
例如:
我有一个JButton,我注册鼠标按下并将按钮绘制为红色。释放后,我将其绘制为蓝色。
如果我只是单击它,按钮会变成蓝色。好的。
如果我按住它,按钮会保持红色。好的。
如果我点击它并设置它打开一个JOptionPane对话框,即使我释放了鼠标,它仍然保持为红色。不好。
我没有找到任何关于这种特定行为的文档,有人能指点我一下吗?
我确实需要使用JOptionPane。
1个回答

4

有一种选择是将打开JOptionPane的调用排队到Swing事件队列。这样会稍微延迟模态JOptionPane的打开,从而允许执行其他按钮操作。

另一种选择是从JOptionPane中提取JDialog,并以非模态方式调用它。

例如:

import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class TestOptionPane extends JPanel {
    private static final Color FOREGROUND = Color.RED;
    private static final Color PRESSED_FG = Color.BLUE;
    private JButton button1 = new JButton(new Button1Action());
    private JButton button2 = new JButton(new Button1Action());

    public TestOptionPane() {
        setPreferredSize(new Dimension(600, 450));
        button1.getModel().addChangeListener(new ButtonModelListener(button1));
        button1.setForeground(FOREGROUND);
        add(button1);
        button2.getModel().addChangeListener(new ButtonModelListener(button2));
        button2.setForeground(FOREGROUND);
        add(button2);
    }

    private class Button1Action extends AbstractAction {
        public Button1Action() {
            super("Queue JOptionPane on Swing event thread");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            SwingUtilities.invokeLater(() -> {
                JOptionPane.showMessageDialog(TestOptionPane.this, "hello");
            });
        }
    }

    private class Button2Action extends AbstractAction {
        public Button2Action() {
            super("Show non-modal JOptionPane");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            SwingUtilities.invokeLater(() -> {
                Component parentComponent = TestOptionPane.this;
                JOptionPane optionPane = new JOptionPane("Hello", JOptionPane.PLAIN_MESSAGE);
                JDialog dialog = optionPane.createDialog(parentComponent, "Fubars Rule!");
                dialog.setModalityType(ModalityType.MODELESS);
                dialog.setLocationRelativeTo(parentComponent);
                dialog.setVisible(true);
            });
        }
    }

    private class ButtonModelListener implements ChangeListener {
        private JButton button;

        public ButtonModelListener(JButton button) {
            this.button = button;
        }

        @Override
        public void stateChanged(ChangeEvent e) {
            ButtonModel model = (ButtonModel) e.getSource();
            if (model.isPressed()) {
                button.setForeground(PRESSED_FG);
            } else {
                button.setForeground(FOREGROUND);
            }
        }

    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("TestOptionPane");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new TestOptionPane());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Lory A
@LoryA:回答已经更新,展示了两种方法,包括第一种在事件线程中排队joption pane的方法和第二种将optionpane作为非模态对话框显示的方法。 - Hovercraft Full Of Eels
2
@LoryA:我努力在Swing事件线程上创建GUI,以防止奇怪而不可预测的线程错误。它们有时会发生,我也见过。 - Hovercraft Full Of Eels

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接