实现 ActionListener 的 Java 匿名类?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/891380/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java anonymous class that implements ActionListener?
提问by Tim
I was recently doing a programming assignment that required us to implement in code a program specified by a UML diagram. At one point, the diagram specified that I had to create an anonymous JButton that displayed a count (starting at one) and decremented each time it was clicked. The JButton and its ActionListener both had to be anonymous.
我最近在做一个编程作业,要求我们在代码中实现一个由 UML 图指定的程序。有一次,该图指定我必须创建一个匿名 JButton,它显示一个计数(从 1 开始)并在每次单击时递减。JButton 及其 ActionListener 都必须是匿名的。
I came up with the following solution:
我想出了以下解决方案:
public static void main(String[] args) {
JFrame f = new JFrame("frame");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(400, 400);
f.getContentPane().add(new JButton() {
public int counter;
{
this.counter = 1;
this.setBackground(Color.ORANGE);
this.setText(this.counter + "");
this.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
counter --;
setText(counter + "");
}
});
}
});
f.setVisible(true);
}
This adds an anonymous JButton, then adds another (inner) anonymous ActionListener to handle events and update the button's text as necessary. Is there a better solution? I'm pretty sure I can't declare an anonymous JButton implements ActionListener ()
, but is there another more elegant way to achieve the same result?
这会添加一个匿名 JButton,然后添加另一个(内部)匿名 ActionListener 来处理事件并根据需要更新按钮的文本。有更好的解决方案吗?我很确定我不能声明 anonymous JButton implements ActionListener ()
,但是还有另一种更优雅的方法来实现相同的结果吗?
采纳答案by Cogsy
I usually go something like this:
我通常是这样的:
JPanel panel = new JPanel();
panel.add(new JButton(new AbstractAction("name of button") {
public void actionPerformed(ActionEvent e) {
//do stuff here
}
}));
AbstractAction implements ActionListener so this should satisfy the task.
AbstractAction 实现 ActionListener 所以这应该满足任务。
It can be bad practice to squish so many lines of code together, but if you're used to reading it then it can be quite elegant.
将这么多行代码压缩在一起可能是一种不好的做法,但是如果您习惯于阅读它,那么它可能会非常优雅。
回答by Erich Kitzmueller
I would not do something like that in a real-world program, but given the requirements in your assignment, you can hardly do better.
我不会在现实世界的程序中做这样的事情,但考虑到你的任务要求,你很难做得更好。
回答by Jon
Well there is a much more elegant way to do it.
那么有一种更优雅的方式来做到这一点。
Unfortunately, it's not a Core Java/Swing approach.
不幸的是,它不是核心 Java/Swing 方法。
You can use SwingBuilder in Groovy to achieve the same result, using slightly more terse syntax, e.g. psuedo code:
您可以在 Groovy 中使用 SwingBuilder 来实现相同的结果,使用稍微简洁的语法,例如伪代码:
button(text: '' + counter,
actionPerformed: {counter--; text = '' + counter + ''},
constraints:BL.SOUTH)
[http://groovy.codehaus.org/Swing+Builder][1]
[ http://groovy.codehaus.org/Swing+Builder][1]
I wouldn't use this in your assignment though, I've seen students reallydeviate from the norm and get marked down for it, but at least you can include it as a possible avenue to investigate further.
不过,我不会在您的作业中使用它,我已经看到学生确实偏离了规范并因此被打分,但至少您可以将其作为进一步调查的可能途径。
I think what you have at present is absolutely fine though.
我认为你目前拥有的绝对没问题。
回答by Tom Hawtin - tackline
Implementing multiple types is generally a bad idea.
实现多种类型通常是一个坏主意。
It is rarely necessary to extend JComponent
classes, although a lot of bad software and tutorials do it. An idiom/hack that has been gaining ground recently is Double Brace - a class is only subclasses in order to give it an instance initialiser which acts like a with
statement from other languages.
很少需要扩展JComponent
类,尽管很多糟糕的软件和教程都这样做了。最近流行的一个习惯用法/hack 是双括号——一个类只是子类,以便给它一个实例初始化器,它的作用就像with
来自其他语言的语句。
In this case, the relevant code can be written as:
这种情况下,相关代码可以写成:
JButton button = new JButton();
button.addActionListener(new ActionListener() {
int counter = 1;
{
updateText();
}
public void actionPerformed(ActionEvent arg0) {
--counter;
updateText();
}
private void updateText()
setText(Integer.toString(counter));
}
});
f.getContentPane(button);
If it gets more complex, then you'll probably want to make an outer class (that does not implement ActionListener
or extend JButton
) to handle the data.
如果它变得更复杂,那么您可能希望创建一个外部类(不实现ActionListener
或扩展JButton
)来处理数据。
Also note, you should be using the EventQueue.invokeLater
boilerplate to ensure that Swing components are only ever used on the AWT EDT.
另请注意,您应该使用EventQueue.invokeLater
样板文件来确保 Swing 组件只在 AWT EDT 上使用。
回答by Mike Houston
It's quite ugly, but you could do the following using the ActionListener method and an anonymous class:
这很丑陋,但您可以使用 ActionListener 方法和匿名类执行以下操作:
f.getContentPane().add(new JButton(new AbstractAction("name of button") {
private int counter = 0;
public void actionPerformed(ActionEvent e) {
((JButton) e.getSource()).setText(Integer.toString(counter--));
}
}) {
{
setText("1");
}
});
To make it easier to access the counter you could move it out to the top level of your class and access it from both places where setText is called.
为了更容易访问计数器,您可以将它移到类的顶层,并从调用 setText 的两个地方访问它。
回答by kleopatra
This is one of bad-practice tasks forced to do in homework only ;-) Bad things:
这是被迫仅在家庭作业中完成的不良实践任务之一;-) 不好的事情:
- usage of ActionListener instead of Action which is bad in itself
- as a consequence, scoping problems bubble up
- counter's scope wider than necessary
- need access to button inside the actionPerformed (via type-cast or accessing surrounding object's api)
- unreadable (aka: unmaintainable) code
- 使用 ActionListener 而不是 Action 本身就不好
- 结果,范围界定问题浮出水面
- 计数器的范围超出必要范围
- 需要访问 actionPerformed 中的按钮(通过类型转换或访问周围对象的 api)
- 不可读(又名:不可维护)代码
But, then .. we cannot resist, can we ;-) Here's a version using Action which is clean (or so I think) as to the first two issue, unreadable as all other examples (and I cheated, of course: first implemented the anonymous classes, then let the IDE do the inline
但是,那么 .. 我们无法抗拒,我们可以吗 ;-) 这是一个使用 Action 的版本,它对于前两个问题来说是干净的(或者我认为),与所有其他示例一样不可读(当然我作弊:首先实现匿名类,然后让 IDE 进行内联
f.add(new JButton(new AbstractAction() {
int counter = 1;
{ // constructor block of action
updateName();
}
@Override
public void actionPerformed(ActionEvent e) {
counter--;
updateName();
}
private void updateName() {
putValue(Action.NAME, "" + counter);
}
}) { // subclass button
{ // constructor block button
setBackground(Color.PINK);
}}
);