6

Action同じサブクラスに関連付けられたいくつかのコントロールを備えたSwingGUIを作成しました。サブクラスの実装は、次のAction擬似コードに従います。

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_;
};

アクションは、次の擬似コードと同様の方法で、ボタンとメニュー項目の両方に関連付けられます。

act_ = new Action_StartPlayback(/*...*/);
// ...
JButton btn = new JButton(act_);
JMenu mnu = new JMenu(act_);

ボタンまたはメニュー項目をクリックすると、アクションactionPerformedが正しく実行され、 gizmo_初期化され、非アクティブnullになり、ボタンとメニュー項目がまだ有効になっていることを除いて、すべてが期待どおりに機能します。

私はそれisEnabledが再び「自動的に」呼び出されるだろうと思っていましたが、これは明らかに起こっていません。 isEnabled()二度と呼び出されることはありません。

これは2つの質問を呼び起こします:

  1. @Overrideここで行ったような方法で大丈夫ですisEnabled()か?
  2. isEnabled()#1の答えが「はい」であるとすると、GUIの更新をトリガーして再度呼び出され、ボタンとメニュー項目が無効になるようにするにはどうすればよいですか?
4

4 に答える 4

3

オーバーライドする代わりに、メソッドでギズモを初期化した後にsetEnabled呼び出すことができます。setEnabled(false)actionPerformed

@Override public void actionPerformed(ActionEvent e) 
{
  gizmo_ = new Gizmo();
  setEnabled(false);
}

からのsetEnabled実装は次のAbstractActionとおりです。

public void setEnabled(boolean newValue) {
  boolean oldValue = this.enabled;
  if (oldValue != newValue) {
    this.enabled = newValue;
    firePropertyChange("enabled", 
            Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
  }
}

探している自動魔法は への呼び出しです。これfirePropertyChange、このアクションに基づいて状態が変更されたことをコンポーネントに通知するため、コンポーネントはそれに応じて独自の状態を更新できます。

于 2012-07-09T16:18:19.653 に答える
2

私はこれのプロではありませんが、有効の状態が変化したことをリスナーに通知する、これを自動的に行う方法がわかりません。もちろんsetEnabled(false)、actionPerformed の開始時に呼び出し、Gizmo (または Gizmo のラッパー) をコーディングしてプロパティ変更をサポートし、PropertyChangeListener を Gizmo に追加して、そのリスナーで状態が DONE に変わったら を呼び出すことができますsetEnabled(true)。少し不器用ですが、うまくいきます。

于 2012-07-09T16:19:10.807 に答える
2

これは Swing に厳密に限定されたものではなく、より一般的な Java の原則です。JDK (および他のライブラリ) の多くのクラスには、プロパティの getter と setter があります。ほとんどの場合、スーパークラスは対応するフィールドに直接アクセスし、ゲッターを経由しないため、これらのメソッドをオーバーライドして動的な値を返すことは意図されていません。

動的な動作を行う場合は、値が変更されるたびに対応するセッターを呼び出す必要があります。これは、スーパークラスの変更が行われたことを通知し、通常、プロパティ変更イベントも発生させて、他の関係者に通知します。

Java Bean を検索すると、この規則についてもう少し詳しく知ることができます。

あなたの場合、考えられる解決策は、PropertyChangeEventそのインスタンスが変更されたときにUI クラスgizmoを起動させ、アクションにそのイベントをリッスンさせることです。このようなイベントを受信すると、自身の有効状態を更新します。

于 2012-07-09T16:28:43.980 に答える