[英]How to customize event source for ActionEvent?
I'm working on a custom component and came up with a problem. 我正在处理一个自定义组件,并提出了一个问题。 Here is the component: 这是组件:
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
}
The thing is I'm trying to hide MyComponent
's implementation details. 问题是我试图隐藏MyComponent
的实现细节。 But setting listener this way is not good since a caller may observe that source
attrubte is jButton
. 但是以这种方式设置侦听器并不好,因为调用者可能会发现source
属性为jButton
。 How can I set to the enclosing MyComponent
instance? 如何设置为封闭的MyComponent
实例?
Instead of allowing the client to pass in an ActionListener
, have the client pass in a different callback, create your own listener, then have your listener invoke the callback: 与其允许客户端传递一个ActionListener
, 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();
}
If you want to pass the client the ActionEvent
without the ability to access ActionEvent#getSource()
, create a wrapper: 如果要向客户端传递ActionEvent
而不能访问ActionEvent#getSource()
,请创建一个包装器:
class ActionEventWrapper {
private ActionEvent event;
public MyActionEvent(ActionEvent event) {
this.event = event;
}
//expose methods that aren't getSource()
public String getActionCommand() {
return event.getActionCommand();
}
}
Simply add this type to the callback's method parameter: 只需将此类型添加到回调的method参数中:
interface SomeCallback {
void execute(ActionEventWrapper event);
}
You could then create a new ActionEventWrapper
anytime an event is triggered: 然后,您可以在触发事件的任何时候创建一个新的ActionEventWrapper
:
public void addActionListener(SomeCallback callback){
jButton.addActionListener(event -> {
callback.execute(new ActionEventWrapper(event));
});
}
If you really want to adjust the source of the component's listener's events, simply create a new ActionEvent
, specifying whichever source you want via the constructor: 如果您确实要调整组件的侦听器事件的源,只需创建一个新的ActionEvent
,即可通过构造函数指定所需的源:
public void addActionListener(ActionListener listener) {
jButton.addActionListener(event -> {
listener.actionPerformed(new ActionEvent(..., event.getID(), event.getActionCommand()));
});
}
The ...
is where you specify which component you want to act as the source. ...
是您在其中指定要用作源的组件的位置。
Following should work. 以下应该工作。
@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);
}
}
With Lambda expression (singular) 带Lambda表达式(单数)
@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);
});
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.