我编写了一个Swing GUI,其中有几个控件与同一个Action
子类相关联。 Action
子类的实现遵循此psudocode:
public class MyGUI
{
Gizmo gizmo_; // Defined elsewhere
public class Action_StartPlayback extends AbstractAction
{
/* ctor */
public Action_StartPlayback(String text, ImageIcon icon, String desc, Integer mnem)
{
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnem);
}
@Override public boolean isEnabled()
{
return gizmo_ == null;
}
@Override public void actionPerformed(ActionEvent e)
{
gizmo_ = new Gizmo();
}
Action_StartPlayback act_;
};
该操作与按钮和菜单项相关联,方式与此psudocode类似:
act_ = new Action_StartPlayback(/*...*/);
// ...
JButton btn = new JButton(act_);
JMenu mnu = new JMenu(act_);
当我点击按钮或菜单项时,操作actionPerformed
被正确触发,gizmo_
被初始化并且不是null
,一切都按预期工作 - 除了按钮和菜单项仍然启用。
我预计isEnabled
会被“自动”再次调用,但这显然不会发生。永远不会再调用isEnabled()
。
这引出了两个问题:
@Override
isEnabled()
方法那样使用isEnabled()
方法吗?答案 0 :(得分:2)
您可以在setEnabled
方法中对Gizmo进行初始化后,轻松调用setEnabled(false)
,而不是覆盖actionPerformed
:
@Override public void actionPerformed(ActionEvent e)
{
gizmo_ = new Gizmo();
setEnabled(false);
}
以下是setEnabled
的{{1}}实施:
AbstractAction
您要查找的自动是对public void setEnabled(boolean newValue) {
boolean oldValue = this.enabled;
if (oldValue != newValue) {
this.enabled = newValue;
firePropertyChange("enabled",
Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
}
}
的调用,它会根据此操作通知组件状态已更改,因此组件可以更新其自己的状态相应
答案 1 :(得分:2)
我不是这方面的专业人士,但我没有看到自动执行此操作的方法,通知听众已启用状态已更改。当然你可以在actionPerformed开始时调用setEnabled(false)
,然后编译Gizmo(或Gizmo上的包装器)以获得属性更改支持,然后将PropertyChangeListener添加到Gizmo,并在该侦听器中,当状态发生更改时要完成,请致电setEnabled(true)
。有点kludgy但它会工作。
答案 2 :(得分:2)
这并不仅限于Swing,而是更普遍的Java原则。 JDK(以及其他库)中的许多类都有一个getter和一个属性的setter。这些方法并不意味着被覆盖以返回动态值,因为大多数时候超类直接访问相应的字段而不会通过getter。
如果您有动态行为,则每次值更改时都应调用相应的setter。这将通知超级类已经做出的更改,通常这也会触发属性更改事件以通知其他感兴趣的各方。
如果您搜索Java bean,可以在此约定上找到更多信息。
在您的情况下,可能的解决方案是让您的UI类在PropertyChangeEvent
实例更改时触发gizmo
,并让您的操作侦听该事件。当他们收到这样的事件时,他们会更新自己的启用状态。
答案 3 :(得分:0)
启用状态存储在对象的 ,AbstractAction和JButton中。
这很重要,因为您只需要一个Action_StartPlayback
个实例用于多个组件,例如:
所有这些都可以拥有Action_startPlayback
的相同实例。 Action_startPlayback
是唯一的真相来源。组件负责尊重真实来源,因此每个组件都会要求AbstractAction在事情发生变化时通知他们。 AbstractAction将记住所有组件,并将使用方法firePropertyChange()
通知它们。
但是如何重新绘制所有待处理的组件?您必须强制所有待处理的组件向Action_startPlayback
询问执行启用状态!看看这个:
@Override public void actionPerformed(ActionEvent e)
{
gizmo_ = new Gizmo();
// now, force the components to get notified.
setEnabled(true);
}