Swing:有没有办法区分用户导致的ItemEvent和应用程序导致的ItemEvent?

时间:2008-10-06 20:55:35

标签: java swing events combobox listeners

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

例如,让我们说我有一个组合框'combo',我正在用我的ItemListener监听itemStateChanged事件,'listener'。当用户将选择更改为项目2或执行行(伪代码)时:

combo.setSelection(2)

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

那就是说,我不是任何手段的摇摆专家,所以我想我会问。

谢谢!

5 个答案:

答案 0 :(得分:2)

无论用户选择第2项,还是API调用setSelection(2),该事件都将显示相同的

您的问题的解决方案可能是重新思考您希望itemStateChanged代码在选择更改时执行的操作。为什么您的应用在每种情况下都会有不同的工也许你可以利用相似之处。

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

答案 1 :(得分: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对象的提取必须在不同的线程中运行;)。通常,重新考虑应用程序的设计。

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

如果您需要区分事件,那么您的设计可能需要重新考虑。 MVC的重点是将模型的变化与用户的实际鼠标点击分离。

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

答案 4 :(得分:0)

所以我猜你想让用户选择执行一些动作,而不仅仅是一个简单的旧的直接状态改变。这是由灵活性有限引起的问题(灵活性总是有限的,特别是如果你在其他方面有灵活性的话)。

我的建议:

首先,总是直接在Swing中使用模型。小部件是复杂的,你想要分开不同的问题。幸运的是,Swing已经有了它的模型。

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

User -- JComboBox -- ActionComboBoxModel -- DefaultComboBoxModel -- Application code