我正在开发一个自定义组件,并提出了一个问题。这是组件:
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
attrubte是jButton
。如何设置封闭的MyComponent
实例?
答案 0 :(得分: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
无法访问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();
}
}
只需将此类型添加到回调的方法参数:
interface SomeCallback {
void execute(ActionEventWrapper event);
}
然后,您可以在触发事件时随时创建新的ActionEventWrapper
:
public void addActionListener(SomeCallback callback){
jButton.addActionListener(event -> {
callback.execute(new ActionEventWrapper(event));
});
}
如果您真的想调整组件侦听器事件的来源,只需创建一个新的ActionEvent
,通过构造函数指定您想要的任何来源:
public void addActionListener(ActionListener listener) {
jButton.addActionListener(event -> {
listener.actionPerformed(new ActionEvent(..., event.getID(), event.getActionCommand()));
});
}
您可以在...
指定要作为来源的组件。
答案 1 :(得分:1)
以下应该工作。
@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);
}
}
使用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);
});
}
}