java - 避免 JOptionPane 干扰 Action 监听器

标签 java swing jbutton actionlistener joptionpane

我注意到所有 JOptionPane 方法都会“干扰”ActionListeners。 我需要 ActionListener 在打开 JOptionPane 后保持 Activity 状态。

例如:

我有一个 JButton,我注册了按下的鼠标并将按钮绘制为红色。被释放后,我把它画成蓝色。

  • 如果我只是点击它,按钮就会变成蓝色。 好的
  • 如果我按住它并单击,该按钮将保持红色。 好的
  • 如果我单击它并将其设置为打开 JOptionPane 对话框,它会保持红色,即使我已经释放了鼠标。 不行

我无法找到有关此特定行为的任何文档,有人可以为我指出正确的方向吗?

我确实需要使用 JOptionPane

最佳答案

一个选项 -- 在 Swing 事件队列中对打开 JOptionPane 的调用进行排队。这将稍微延迟模式 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());
    }
}

关于java - 避免 JOptionPane 干扰 Action 监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39945744/

相关文章:

Java:使用图像作为按钮

java - 使用 JWindow 的 Timer 类

java - 在Java中设置边框(jbutton)的长度

java - 使用(hadoop)FileSystem时,Spark应用程序中的InvalidProtocolBufferException

java - 命名 : Why should named constants be all uppercase in C++/Java?

java - 如何重新绘制和/或重新验证 JPanel

java - 用java编码后回车键不起作用

java - jbutton事件ActionListener

java - MediaExtractor.setDataSource 抛出 IOException "failed to instantiate extractor"

java - 创建用户定义的异常类-获取 null 作为答案(JAVA)