我最近做了一个编程任务,要求我们在代码中实现一个由UML图指定的程序。有一次,该图指定我必须创建一个显示计数(从1开始)的匿名JButton,并在每次单击时递减。 JButton及其ActionListener都必须是匿名的。
我提出了以下解决方案:
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);
}
这会添加一个匿名JButton,然后添加另一个(内部)匿名ActionListener来处理事件并根据需要更新按钮的文本。有更好的解决方案吗?我很确定我不能声明一个匿名的JButton implements ActionListener ()
,但还有另一种更优雅的方法来实现相同的结果吗?
答案 0 :(得分:13)
我通常会这样:
JPanel panel = new JPanel();
panel.add(new JButton(new AbstractAction("name of button") {
public void actionPerformed(ActionEvent e) {
//do stuff here
}
}));
AbstractAction实现了ActionListener,因此它应该满足任务。
将这么多行代码压缩在一起可能是不好的做法,但如果你习惯于阅读它,那么它就会非常优雅。
答案 1 :(得分:4)
这很难看,但您可以使用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");
}
});
为了更容易访问计数器,您可以将其移出到类的顶层,并从调用setText的两个位置访问它。
答案 2 :(得分:2)
实现多种类型通常是一个坏主意。
很少有必要扩展JComponent
类,尽管很多不好的软件和教程都会这样做。最近获得成功的成语/ hack是Double Brace - 一个类只是子类,以便为它提供一个实例初始化器,其作用类似于来自其他语言的with
语句。
在这种情况下,相关代码可以写成:
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);
如果它变得更复杂,那么你可能想要创建一个外部类(不实现ActionListener
或扩展JButton
)来处理数据。
另请注意,您应该使用EventQueue.invokeLater
样板来确保仅在AWT EDT上使用Swing组件。
答案 3 :(得分:1)
我不会在现实世界的计划中做同样的事情,但考虑到你的任务要求,你很难做得更好。
答案 4 :(得分:1)
有一种更优雅的方式来做到这一点。
不幸的是,它不是Core Java / Swing方法。
您可以使用Groovy中的SwingBuilder来实现相同的结果,使用稍微简洁的语法,例如伪代码:
button(text: '' + counter,
actionPerformed: {counter--; text = '' + counter + ''},
constraints:BL.SOUTH)
[http://groovy.codehaus.org/Swing+Builder][1]
我不会在你的任务中使用这个,但是我看到学生真的偏离了常规而得到了标记,但至少你可以把它作为一个可能的途径包括在内进一步调查。
我认为你现在拥有的东西绝对没问题。
答案 5 :(得分:0)
这是仅在家庭作业中被迫做的不良练习任务之一;-)坏事:
但是,那么..我们无法抗拒,我们能不能;-)这是一个使用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);
}}
);