我有一个包含每个单元格中的按钮的大表。这些按钮非常相似,几乎相同。如果我以这种方式向每个按钮添加一个动作侦听器:
tmp.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent evt) {
proposition = proposition + action;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
updatePropositionPanel();
}
});
}
});
实际上,每个动作监听器都与action
的值不同。 proposition
和updatePropositionPanel
是该类的字段和方法。
首先我认为如果我不使用内部类,我可以缩短它。所以,我决定编写一个新的ActionListener类。但是,我意识到在这种情况下,“命题”对于这个类的实例是不可见的。
然后我决定将actionPerformed方法添加到当前类并执行:addActionListener(this)
。但是我意识到我不知道如何为actionPerformed方法提供参数。
那么,它是如何运作的。我可以用简短的方式添加一个动作监听器吗?
增加:
我喜欢用构造函数编写内部类的想法,构造函数可以使用一些参数和actioPerformed方法,它可以使用构造函数中给出的参数。我开始这样做,然后意识到它与其他内部匿名类创建冲突(像上面给出的代码一样使用)。所以,我想我会创建另一个类(不是内部类)。
答案 0 :(得分:4)
您可以创建自己的类并将数据传递给构造函数。例如
public class MyActionListener
{
private int proposition;
private MyOtherClass moc;
public MyActionListener(int proposition, MyOtherClass moc) {
this.proposition = proposition;
this.moc = moc;
}
public void actionPerformed(ActionEvent evt) {
proposition += moc.action;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
moc.updatePropositionPanel();
}
});
}
}
然后你可以正常添加它,将你喜欢的任何参数传递给构造函数:
tmp.addActionListener( new MyActionListener(proposition, this) );
答案 1 :(得分:1)
编辑:我已将类更改为使用MyOuterClass显示构造。
这是一些草拟的代码。希望这会得到你的1,这就是我实现它的方式。
public class MyOuterClass {
// member variables for MyOuterClass
public MyOuterClass() {
// ...constructor stuff here
}
// ...outer class stuff here - methods, etc.
// The code each place you want to add the listener, somewhere in MyOuterClass
tmp.addActionListener(new MyActionListener(poposition, action));
// below outer class stuff, although it can really be most places, I usually put
// it here - personal style preference. Swing's classes often put inner
// classes first
/**
* An inner class.
*/
private MyActionListener implements ActionListener {
/**
* Object used here as a filler, replace with appropriate
* class types
*/
private Object proposition;
private Object action;
private MyActionListener(Object proposition, Object action) {
this.proposition = proposition;
this.action = action;
}
public void actionPerformed(ActionEvent evt) {
proposition = proposition + action;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
updatePropositionPanel();
}
}
/**
* Setters provided in case you need to change proposition and action. If not,
* feel free not to have them and to have final members
*/
private void setProposition(Object proposition) {
this.proposition = proposition;
}
private void setAction(Object action) {
this.action = action;
}
}
}
编辑:要在编辑中按要求创建另一个类,请执行上述操作,但在另一个.java文件中创建非私有其他类并编写代码。
答案 2 :(得分:1)
唯一不同的是action
的值,您可以将代码放在方法中。 (此外,@ Override是不必要的,+=
在这里很有用。)
public void setup(
final AbstractButton button,
final int action
) {
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
proposition += action;
EventQueue.invokeLater(new Runnable() {
public void run() {
updatePropositionPanel();
}
});
}
});
}
invokeLater
可能毫无意义,因为无论如何你将参加AWT赛事调度线程(EDT)。
如果要添加许多通用操作,那么可以通过使用没有与之关联的无意义事件对象的接口来简化它。
如果你想成为hackish,可以在子类构造函数中添加监听器。
new ActionHandler(button) { public void action() {
proposition += action;
updatePropositionPanel();
}});
希望JDK7能够让这种东西的Java语法不那么冗长。但是,Java总是有些冗长。
答案 3 :(得分:0)
如果您proposition
可变(例如StringBuilder
而不是String
),则选项1有效。如果您声明final
,则选项2有效。这样他们就可以在内部类中访问/可见。
答案 4 :(得分:0)
您可以创建一个单独的MyActionListener类,并使用构造函数传递两个值命题和操作。它整理了源代码。
答案 5 :(得分:0)
您可以创建自己的侦听器类来实现ActionListener。该类可以包含与您正在讨论的参数对应的成员变量;你可以使用构造函数设置它们。
添加侦听器的调用看起来像这样:
tmp.addActionListener(new MyActionListenerSubClass(proposition, action));
答案 6 :(得分:0)
为了这个例子,我假设你的命题和动作变量是字符串。 定义接口PropositionUpdater,接口PropositionPanelUpdater和协作者提议持有者:
public interface PropositionUpdater() {
public void updateProposition(PropositionHolder holder, String action);
}
public interface PropositionHolder() {
public String getProposition();
public void setProposition(String proposition);
}
public interface PropositionPanelUpdater() {
public void updatePropositionPanel();
}
命题更新程序的默认实现就是:
public class DefaultPropositionUpdater implements PropositionUpdater {
public void updateProposition(final PropositionHolder holder, final String action) {
holder.setProposition(holder.getProposition() + action);
}
}
我将保留一个PropositionHolder和PropositionPanelUpdater的默认值给你的想象力;)
现在,这是你的行动听众:
public class PropositionUpdaterActionListener implements ActionListener {
private PropositionHolder holder;
private PropositionUpdater updater;
private PropositionPanelUpdater panelUpdater;
public PropositionUpdaterActionListener(final PropositionHolder holder, final PropositionUpdater updater, final PropositionPanelUpdater panelUpdater) {
super();
this.holder = holder;
this.updater = updater;
this.panelUpdater = panelUpdater;
}
public void actionPerformed(final ActionEvent evt) {
//Not sure how you *got* the action, but whatever...
updater.updateProposition(holder, action);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
panelUpdater.updatePropositionPanel();
}
});
}
}
答案 7 :(得分:0)
你没有说出你在谈论多少个按钮。
如果它是一个像国际象棋棋盘或更少的棋子,@ juskt的方法很好。
但是,如果你看一些更大的东西,我会用这种方法:
public class MyActionListener {
public void actionPerformed(ActionEvent evt) {
JComponent c = (JComponent)evt.getSoource();
int prop = (Integer)c.getclientProperty("PROPOSITION");
int act = (Integer)c.getclientProperty("ACTION");
SomeClass obj = c.getclientProperty("UPDATE");
prop += act;
// If necessary, clientPut("PROPOSITION", prop);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
obj.updatePropositionPanel();
}
});
}
}
此动作侦听器不持有任何状态。 因此,它的单个实例可用于所有按钮。 对于像Go板(19x19)这样的东西,这可以解决1个对象而不是361。