Java Swing事件冒泡/捕获

时间:2016-05-02 19:49:26

标签: java swing

Java是否具有与pubsub或数据绑定类似的概念?

我正在学习Java GUI(特别是Swing)。我有几种形式,我希望通过在它们之间共享事件和单例对象来保持同步。在我所知的其他语言中,这可以通过数据绑定或事件同步/触发来处理。

我已经看到你可以做像source.getParent().doSomething()这样的活动,但是来自网络开发,跟踪父母参考的想法对我来说似乎绝对是疯了。我总是能够追溯到我想的父母,但这只是感觉不对。

这就是Java做事的方式吗?有没有办法影响项目,无论它们在应用程序中的位置?

我没有任何关于更像网络的做事方式的事情,例如冒泡和捕捉事件生命周期的各个阶段。也许我一次打开多个表单/视图的方法对于Java的工作方式来说太奇怪了......我可以关闭/打开表单,初始化会获取更新的值。

无论我的设计是否合适,我只是想学习Java,所以即使这个具体的例子不适用,我仍然想知道如何在没有组件A的情况下影响远方的项目。知道组件B在听。

在伪代码中因为我​​不知道Java的表达方式,所以我希望能够做到:

没有数据绑定

Foo组件:

private void initialize() {

   this.addEventListener(CONSTANTS.NAME_OF_EVENT, this.doSomething);  // waits for somebody to tell us to update
}


private void doSomething() {
   this.value = singleton.getInstance().value; // gets "123" from Bar's dispatch
   ...
}

栏组件中,我希望能够这样做:

private void triggerSomething() {
   this.singleton.getInstance.setValue(123);  // updates the singleton
   this.dispatchEvent(CONSTANTS.NAME_OF_EVENT); // tells anybody who cares about NAME_OF_EVENT to do something about it (ideally, the singleton would do the dispatching but for clarity I separated them)
}

使用数据绑定

Foo组件:

private void initialize() {
    this.singleton.getInstance().setValue(123);
}

Bar Component 中,我希望txtValue.setText()可以通过绑定到单例值来神奇地发生。

private void initialize() {
   txtValue.setText(this.singleton.getInstance().getValue());
}

1 个答案:

答案 0 :(得分:2)

您可能想要用Property Change Listener而不是事件监听器来思考。事件将处于比您想要的更低的水平(按下按钮,按钮释放,按键,按键释放)。属性更改是更高级别:"此属性已从此值更改为该值。"

public class PropertyChangeBean {
    protected PropertyChangeEvent pce(String name, Object from, Object to) {
        return new PropertyChangeEvent(this, name, from, to);
    }

    private PropertyChangeSupport pcs;

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        if (pcs == null)
            pcs = new PropertyChangeSupport(this);
        pcs.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        if (pcs != null)
            pcs.removePropertyChangeListener(listener);
    }

    protected void fireChange(String property, Object from, Object to) {
        if (pcs != null && !Objects.equals(from, to))
            pcs.firePropertyChange(pce(property, from, to));
    }

    protected void fireChange(String property, int from, int to) {
        if (pcs != null && from != to)
            pcs.firePropertyChange(pce(property, from, to));
    }

    protected void fireChange(String property, boolean from, boolean to) {
        if (pcs != null && from != to)
            pcs.firePropertyChange(pce(property, from, to));
    }

    protected void fireChange(PropertyChangeEvent pce) {
        if (pcs != null)
            pcs.firePropertyChange(pce);
    }
}

创建你的" Bar"豆喜欢:

public class Bar extends PropertyChangeBean {

    private int value = 0;

    public void setValue(int new_value) {
        fireChange("value", value, value = new_value);
    }

    public int getValue() {
        return value;
    }
}

" Foo"将在" Bar"

上注册为PropertyChangeListener
class Foo {
    Foo() {
        bar.addPropertyChangeListener(e -> {
             // Fetch and use new value of bar
        });
    }
}

你甚至可以使用Vetoable Change Listener让听众能够回应"不,这不是一个可以接受的价值"何时尝试改变。