2016-04-19 10 views
2

私はカスタムコンポーネントを開発中で、問題が発生しました。ActionEventのイベントソースをカスタマイズする方法は?

public class MyComponent extends JPanel { 

    private final JButton jButton; 
    private final JLabel jLabel; 

    public MyComponent(){ 
     jButton = new JButton(); 
     //etc.. 
    } 

    public void addActionListener(ActionListener l){ 
     //The problem with this is that ActionEvent has source attribute 
     //set to jButton which is not desirable. How can I set it to this? 
     jButton.addActionListener(l); 
    } 

    //other component-specific methods 
} 

事は、私がMyComponentの実装の詳細を隠蔽しようとしている:ここではコンポーネントです。しかし、聞き手がsourceアタッチがjButtonであることを観察する可能性があるので、このようにリスナーを設定することは良くありません。どのようにして囲むMyComponentインスタンスに設定できますか?

+0

'jButton.add(L)で

@SuppressWarnings("all") public class MyComponent extends JPanel { private final JButton jButton = new JButton(); private final JLabel jLabel = new JLabel(); public void addActionListener(final ActionListener listener) { final MyComponent self = this; ActionListener newListener = new ActionListener() { public void actionPerformed(ActionEvent e) { ActionEvent newEvent = new ActionEvent(e.getSource(), e.getID(), e.getActionCommand()) { @Override public Object getSource() { return self; } }; listener.actionPerformed(newEvent); } }; jButton.addActionListener(newListener); } } 

;'は 'jButton.addActionListener(l)を意味するものではありませんか。'? – 11thdimension

+0

@ 11thdensionはいはい、修正されました。ありがとうございました。 – user3663882

+0

問題は、MyComponentの実装の詳細を隠そうとしていることです。 == [EventHandler](http://stackoverflow.com/a/9007348/714968) – mKorbel

答えて

2

の代わりに、クライアントはActionListenerに通過させる、さまざまなコールバッククライアントのパスを持って、独自のリスナーを作成し、その後、あなたのリスナーはコールバックを呼び出しています

public class MyComponent extends JPanel { 
    private final JButton jButton; 

    public MyComponent(){ 
     jButton = new JButton(); 
    } 

    public void addActionListener(SomeCallback callback){ 
     jButton.addActionListener(event -> { //create listener 
      callback.execute(); //invoke callback 
     }); 
    } 
} 

interface SomeCallback { 
    void execute(); 
} 

あなたが渡したい場合クライアントActionEvent#getSource()にアクセスする能力のないActionEvent、ラッパーを作成:

class ActionEventWrapper { 
    private ActionEvent event; 

    public MyActionEvent(ActionEvent event) { 
     this.event = event; 
    } 

    //expose methods that aren't getSource() 
    public String getActionCommand() { 
     return event.getActionCommand(); 
    } 
} 

は単純にコールバックメソッドのパラメータには、このタイプを追加します。

interface SomeCallback { 
    void execute(ActionEventWrapper event); 
} 

あなたは、イベントがトリガされた新しいActionEventWrapperいつでも作成することができます:あなたは本当に、コンポーネントのリスナーのイベントのソースを調整したい場合は、単にあなたが欲しい方のソースを指定して、新しいActionEventを作成し、

public void addActionListener(SomeCallback callback){ 
     jButton.addActionListener(event -> { 
      callback.execute(new ActionEventWrapper(event)); 
     }); 
    } 

をコンストラクタを介して:

public void addActionListener(ActionListener listener) { 
    jButton.addActionListener(event -> { 
     listener.actionPerformed(new ActionEvent(..., event.getID(), event.getActionCommand())); 
    }); 
} 

...あなたがソースとして機能したいコンポーネントを指定場所です。

+0

これは私の場合の解決策です。しかし、どのような本来の質問が...どのように 'ActionEvent'の' source'をカスタマイズするのですか? – user3663882

+0

@ user3663882できません。 「ActionEvent」は「舞台裏で」作成され、アクションがトリガーされるとすぐにソースがイベントに渡されます。私はコールバックを渡すためのオプションに 'getSource()'を含まない 'ActionEvent'を追加しましたが。これが役に立ったら教えてください! –

+0

@ user3663882あなたが迷っていることが他にもありますか、またはこのデザインがあなたのニーズに合わない場合は教えてください(私の答えを修正することができる理由を説明してください) –

1

次は動作するはずです。ラムダ式(単数)

@SuppressWarnings("all") 
public class MyComponent2 extends JPanel { 
    private final JButton jButton = new JButton(); 
    private final JLabel jLabel = new JLabel(); 

    public void addActionListener(final ActionListener listener) { 
     MyComponent2 self = this; 

     jButton.addActionListener(e-> { 
      ActionEvent newEvent = new ActionEvent(e.getSource(), e.getID(), e.getActionCommand()) { 
       @Override 
       public Object getSource() { 
        return self; 
       } 
      }; 
      listener.actionPerformed(newEvent); 
     }); 
    } 
} 
+0

匿名のクラスを切り替えることを避けることをお勧めします'getSource()'メソッドをオーバーライドするのではなく、 'ActionEvent'のコンストラクタを使ってソースを指定することです。 –

+0

ラムダ式は匿名クラスですから、コードをlambda相当のものに変換しようとします。 – 11thdimension

+0

これらは匿名クラスではなく、コンパイル後に余分なバイナリファイルを生成することもありません。ラムダは単純に構文的な砂糖ではありません - バイトコードをチェックしてください。 –

関連する問題