【问题标题】:JSpinner keeps spinning while JOptionPane is shown on ChangeListenerJSpinner 保持旋转,而 JOptionPane 显示在 ChangeListener 上
【发布时间】:2012-12-20 18:12:30
【问题描述】:

所以我创建了一个 Java 应用程序,它使用 JSpinner 和 ChangeEventListener 在达到某些值时运行一些代码。当达到这些特定值时,会出现一个 JOptionPane。但随后 JSpinner 继续旋转。因此,如果 JSpinner 允许值 1-50,并且我将 JSpinner 从 20 增加到 21,则在 JOptionPane 打开时它会一直增加到 50。

奇怪的是,这是 Java 1.4.2 中的一个已知错误,但据说在 5.0 中已修复 (Bug ID: 4840869)。我正在运行 Java 6u37。事实上,错误问题中提供的源代码(如下所示)对我来说与它对错误的原始海报所做的效果完全相同。它肯定没有为我修好。

我唯一能想到的原因是我运行的是 Mac OS 10.7.5,并且错误修复可能没有以某种方式进入我的版本。我能做些什么来防止这种行为发生吗?

演示此的源代码(最初来自错误报告):

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class SpinnerFrame extends JFrame implements ChangeListener {

    private JSpinner spinner;

    private boolean changing;

    private SpinnerFrame() {
        super();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().add(getSpinner());
        setSize(80,60);
        setLocation(200, 300);
        setVisible(true);
        changing = false;
    }

    private JSpinner getSpinner() {
        if (spinner == null) {
            spinner = new JSpinner();
            spinner.setModel(new SpinnerNumberModel(10, 1, 50, 1));
            spinner.addChangeListener(this);
        }
        return spinner;
    }

    public void stateChanged(ChangeEvent e) {
        JSpinner spinner = (JSpinner) e.getSource();
        int value = ((Integer) spinner.getValue()).intValue();
        System.out.println("Changed to " + value);
        if (changing) {
            return;
        }
        changing = true;
        if (value > 20) {
            JOptionPane.showMessageDialog(this, "20 exceeded");
            //While this is up, the JSpinner continues to 50
        }
        changing = false;
    }

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

【问题讨论】:

    标签: java macos swing joptionpane jspinner


    【解决方案1】:

    我认为如果您在EventQueue#invokeLater() 中显示消息对话框,它应该不会有这个问题。如果您想在显示后取消旋转到 21,只需在之后将值重置为 20。

    【讨论】:

    • 这最终解决了我的问题。我实际上已经有一个用于对话框选项的工厂类来简化代码参数,所以我很容易实现它。非常感谢!
    • 我发现这仅适用于单击向上箭头,但如果您按住向上箭头向下,重复对话框仍然会发生。有什么想法吗?
    • 检查对话框当前是否正在显示,如果是则不要重新显示。
    • 我最终做到了,它奏效了。不幸的是,我还必须检查自上次显示以来已经过了多长时间,因为一旦我重置了阻止它出现的变量,就会再出现一个。
    【解决方案2】:

    我可以在早期版本的 Mac OS X 上使用 JDK 5 和 6 重现类似的效果。使用鼠标时会出现该效果,但不是键盘。

    1. 当鼠标按住微调器的向上箭头时,对话框会出现在21

    2. 稍后释放鼠标并关闭第一个对话框时,会出现第二个对话框。

    3. 鼠标按住的时间越长,报告的值就越高,直到最大值。

    作为检查您的版本的参考,bug report 中提到的相关代码是在BasicSpinnerUI 中找到的private static class ArrowButtonHandler 中对autoRepeatTimer.stop() 的四次调用。效果因 JDK 版本而异,并且可能是箭头在所选初始延迟内重复频率的人为因素。

    autoRepeatTimer.setInitialDelay(300);
    

    【讨论】:

    • 从您的回答中我不太了解我将如何解决此问题。有没有我应该调用 autoRepeatTimer.setInitialDelay(300) 的地方?
    • 我正在报告我对 JDK 版本 5 和 6 的发现。您看到回归了吗?我没有看到更好的解决方法。为什么使用模态对话框来报告通过阈值?我会通过PropertyChangeListener 在其他地方报告它,example
    猜你喜欢
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多