在没有最终修饰符的情况下更改按钮颜色onclick
Change button color onclick without final modifier
考虑以下代码,用于在单击按钮时更改按钮的颜色。
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
public class ChangeColor {
public static void main(String[] args) {
JButton button = new JButton();
button.setBackground(Color.BLUE);
button.addActionListener(new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
button.setBackground(Color.RED);
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(button);
frame.setSize(200, 200);
frame.setVisible(true);
}
}
它不起作用,因为这个错误:
Cannot refer to the non-final local variable defined in an enclosing scope
如何在不将按钮标记为最终按钮的情况下执行此操作?
您可以将 Button 作为构造函数参数提供给侦听器。
class ButtonColorAction extends AbstractAction {
private JButton button;
public ButtonColorAction(JButton button) {
this.button = button;
}
@Override
public void actionPerformed(ActionEvent e) {
button.setBackground(Color.RED);
}
}
并像这样使用它:
button.addActionListener(new ButtonColorAction(button));
一种解决方案是从 ActionEvent 参数中获取 JButton 的引用:
@Override
public void actionPerformed(ActionEvent e) {
// the source here refers to the object that provoked this method to occur
JButton sourceBtn = (JButton) e.getSource();
sourceBtn.setBackground(Color.RED);
}
您也可以将按钮设为字段,而不是局部变量。
您也可以将其声明为最终版本。
请注意,您永远不会使用您发布的代码,因为大多数重要的 GUI 程序不会像您正在做的那样在静态 main 方法内创建,而是在 OOP 内完成符合 GUI classes.
例如:
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class ButtonColorChange extends JPanel {
private JButton button = new JButton(new ButtonAction("Press Me"));
public ButtonColorChange() {
add(button);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("ButtonColorChange");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ButtonColorChange());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class ButtonAction extends AbstractAction {
private static final Color COLOR_1 = Color.BLUE;
private static final Color COLOR_2 = Color.RED;
public ButtonAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
AbstractButton btn = (AbstractButton) e.getSource();
Color c = btn.getBackground();
c = c == COLOR_1 ? COLOR_2 : COLOR_1;
btn.setBackground(c);
}
}
编辑关于您的其他问题:
Actually the code in my question it's only an example, the real code is something like your.
然后最好显示真实代码,或者最好是模拟真实代码的最小可编译可运行示例。
(a) It is preferred to use e.getSource() or to make button a field?
要么。如果同一个动作要用在多个按钮上,而你只对按下的按钮感兴趣,那么使用getSource()
。如果您的 Action 或 ActionListener 是一个内部 class,那么一个字段就可以正常工作。如果没有,那么您可以根据问题的另一个答案通过构造函数参数将变量传递给 Action。
(b) You say that Also you could declare it as final but I receive this error: The local variable may not have been initialized. What I'm wrong?
如果没有您的真实代码,很难判断,但很可能您没有在声明按钮的同时对其进行初始化。
(c) I my GUI program I don't launch the frame from a thread (id est I write the code of createAndShowGui() in the main(), without the thread). What is the difference?
我的代码保证我的 GUI 将在 Swing 事件线程上启动,为了线程安全应该这样做。
考虑以下代码,用于在单击按钮时更改按钮的颜色。
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
public class ChangeColor {
public static void main(String[] args) {
JButton button = new JButton();
button.setBackground(Color.BLUE);
button.addActionListener(new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
button.setBackground(Color.RED);
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(button);
frame.setSize(200, 200);
frame.setVisible(true);
}
}
它不起作用,因为这个错误:
Cannot refer to the non-final local variable defined in an enclosing scope
如何在不将按钮标记为最终按钮的情况下执行此操作?
您可以将 Button 作为构造函数参数提供给侦听器。
class ButtonColorAction extends AbstractAction {
private JButton button;
public ButtonColorAction(JButton button) {
this.button = button;
}
@Override
public void actionPerformed(ActionEvent e) {
button.setBackground(Color.RED);
}
}
并像这样使用它:
button.addActionListener(new ButtonColorAction(button));
一种解决方案是从 ActionEvent 参数中获取 JButton 的引用:
@Override
public void actionPerformed(ActionEvent e) {
// the source here refers to the object that provoked this method to occur
JButton sourceBtn = (JButton) e.getSource();
sourceBtn.setBackground(Color.RED);
}
您也可以将按钮设为字段,而不是局部变量。
您也可以将其声明为最终版本。
请注意,您永远不会使用您发布的代码,因为大多数重要的 GUI 程序不会像您正在做的那样在静态 main 方法内创建,而是在 OOP 内完成符合 GUI classes.
例如:
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class ButtonColorChange extends JPanel {
private JButton button = new JButton(new ButtonAction("Press Me"));
public ButtonColorChange() {
add(button);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("ButtonColorChange");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ButtonColorChange());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class ButtonAction extends AbstractAction {
private static final Color COLOR_1 = Color.BLUE;
private static final Color COLOR_2 = Color.RED;
public ButtonAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
AbstractButton btn = (AbstractButton) e.getSource();
Color c = btn.getBackground();
c = c == COLOR_1 ? COLOR_2 : COLOR_1;
btn.setBackground(c);
}
}
编辑关于您的其他问题:
Actually the code in my question it's only an example, the real code is something like your.
然后最好显示真实代码,或者最好是模拟真实代码的最小可编译可运行示例。
(a) It is preferred to use e.getSource() or to make button a field?
要么。如果同一个动作要用在多个按钮上,而你只对按下的按钮感兴趣,那么使用getSource()
。如果您的 Action 或 ActionListener 是一个内部 class,那么一个字段就可以正常工作。如果没有,那么您可以根据问题的另一个答案通过构造函数参数将变量传递给 Action。
(b) You say that Also you could declare it as final but I receive this error: The local variable may not have been initialized. What I'm wrong?
如果没有您的真实代码,很难判断,但很可能您没有在声明按钮的同时对其进行初始化。
(c) I my GUI program I don't launch the frame from a thread (id est I write the code of createAndShowGui() in the main(), without the thread). What is the difference?
我的代码保证我的 GUI 将在 Swing 事件线程上启动,为了线程安全应该这样做。