避免 JOptionPane 干扰动作监听器
Avoid JOptionPane interference with action listeners
我注意到所有 JOptionPane
方法 "interfere" 和 ActionListeners
。
我需要 ActionListener 在打开 JOptionPane 后保持活动状态。
例如:
我有一个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());
}
}
我注意到所有 JOptionPane
方法 "interfere" 和 ActionListeners
。
我需要 ActionListener 在打开 JOptionPane 后保持活动状态。
例如:
我有一个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());
}
}