【问题标题】:Swing: Is there a way to differentiate between a user-caused ItemEvent and an application-caused one?Swing:有没有办法区分用户引起的 ItemEvent 和应用程序引起的 ItemEvent?
【发布时间】:2010-09-15 14:59:33
【问题描述】:

我正在使用基于 Swing 的应用程序中的组合框,我很难弄清楚如何区分由用户事件生成的 ItemEvent 与由应用程序引起的 ItemEvent。

例如,假设我有一个组合框“combo”,并且我正在使用我的 ItemListener“listener”监听 itemStateChanged 事件。当用户将选择更改为第 2 项或我执行该行(伪代码)时:

combo.setSelection(2)

.. 似乎我无法区分这些事件。

也就是说,无论如何我都不是 Swing 专家,所以我想我会问。

谢谢!

【问题讨论】:

  • 我没有关注这个。为什么要以编程方式生成事件,然后希望它们与正常事件不同?
  • 我没有生成事件,确切地说。我有听众“做事”附加到组合框。当用户执行操作时,应用程序正常工作。但是,当我需要更新组合时,它仍然会导致事件,但我需要以不同的方式处理。
  • @awied:您还需要担心用户可访问性应用程序正在驱动您的程序的情况。

标签: java swing events combobox listeners


【解决方案1】:

无论是用户选择了Item 2,还是API调用了setSelection(2),事件都会出现相同的

您的问题的解决方案可能是重新考虑您希望 itemStateChanged 代码在选择更改时执行的操作。为什么您的应用程序在每种情况下的工作方式都不同?也许您可以利用相似之处来发挥自己的优势。

使用标志时要小心。 itemStateChanged 事件将在事件调度线程上发生,该线程与您设置标志状态的线程不同。这意味着使用标志可能不是 100% 可靠的。

【讨论】:

    【解决方案2】:

    作用和反应定律很清楚:)。如果您尝试对更改做出反应,则无需区分用户和应用程序。我可以想象只有一个用例需要“区分”。应用程序显示某些数据的情况。在这种情况下,您可能拥有应用程序的数据模型。此模型中还有一些更改侦听器,应用程序 GUI 将通过为组件设置值来做出反应。并且。如果用户在 GUI 组件中选择任何内容。数据模型将通过改变值做出反应。在这种情况下,很容易在数据模型上设置某种只读状态,这将通知模型忽略来自观察对象的任何事件。此通知集应在 EDT 中运行,并且标记没有问题。小例子:

    class ApplicationDataModel {
    
        private Flag current = Flag.RW;
    
        public void setData(ApplicationData data) {
            current = Flag.RO;
            setDataImpl(data);
            notifyObservers();
            current = Flag.RW;
        }
    
        public void reaction(Event e) {
            if (flag = Flag.RO) return;
            ...
        }
    
    }
    

    小心标记,不要忘记线程。如果你从另一个线程调用 setData ,那么 EDT 你就会遇到麻烦。当然。 ApplicationData 对象的提取必须在不同的线程中运行;)。一般来说,重新考虑您的应用程序的设计。

    【讨论】:

      【解决方案3】:

      您可以在设置选择之前在代码中设置一个标志,然后在侦听器中检查该标志(如果已设置则取消设置该标志)...

      自 Java 6 以来可能有更好的方法,但这是我一直使用的方法...

      [编辑]:正如 David 指出的那样,您需要使用 SwingUtilities.invokeLater 或类似工具在 EDT 中设置标志(并更新组合)(无论如何您都应该这样做,因为您正在更改 UI 控件)

      【讨论】:

        【解决方案4】:

        如果您需要将事件区分开来,那么您的设计可能需要重新思考。 MVC 的重点是将模型的更改与用户的实际鼠标点击解耦。

        也许您应该根据您想要区分这两种情况的为什么来重申这个问题。然后,我们可以就实现目标的不同方式提供一些指导。

        【讨论】:

          【解决方案5】:

          所以我猜您希望用户选择执行一些操作,而不仅仅是简单的旧的直接状态更改。这是由有限的灵活性引起的问题(灵活性总是会受到限制,特别是如果您在其他方向上具有灵活性)。

          我的建议:

          首先,始终直接在 Swing 中使用模型。小部件非常复杂,您希望拆分不同的关注点。幸运的是,Swing 已经有了它的模型。

          一种常见的模式是在模型之间进行委托。因此,在这种情况下,您拥有保存数据的“真实”默认模型。在 JComboBox 和真正的 ComboBoxModel 之间插入,并委托 ComboBoxModel 对状态更改指令执行操作。您的应用程序代码应该忽略 JComboBox 并绕过委托模型直接使用真正的 ComboBoxModel。所以在图表中:

          用户 -- JComboBox -- ActionComboBoxModel -- DefaultComboBoxModel -- 应用程序代码

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-06-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-11-17
            相关资源
            最近更新 更多