Swing处理按钮点击及按键事件(适配器类、Action、KeyStroke等)
效果
通过按钮点击和按键(如Ctrl
+B
)更换背景颜色。
代码
Main
类
package test;
import javax.swing.*;
import java.awt.*;
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
// `EventQueue.invokeLater()` 确保在正确线程中更新 GUI,避免线程安全问题。
var f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.addWindowListener(new MyWindowListener());
f.setSize(300, 300);
var p = new JPanel();
var b1 = new JButton(new ColorAction("black", p, Color.BLACK));
var b2 = new JButton(new ColorAction("green", p, Color.GREEN));
var b3 = new JButton(new ColorAction("yellow", p, Color.YELLOW));
p.add(b1);
p.add(b2);
p.add(b3);
f.add(p);
f.setVisible(true);
});
}
}
Action类
继承了AbstractAction
,间接实现了Action
接口,而Action
接口扩展了ActionListener
:
package test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
public class ColorAction extends AbstractAction {
private final JComponent target;
private final Color color;
public ColorAction(String name, JComponent target, Color color) {
super(name);
this.target = target;
this.color = color;
putValue(Action.SHORT_DESCRIPTION, "将 颜色 变成 " + color + "色");
}
@Override
public void actionPerformed(ActionEvent e) {
target.setBackground(color);
}
}
事件处理中有几个重要的角色:事件源对象(例如按钮)、事件对象、监听器对象、事件处理逻辑。
事件处理的逻辑几乎总是和事件源对象(背景、各种组件)耦合。
适配器类
package test;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class MyWindowListener extends WindowAdapter {
@Override
public void windowClosing(WindowEvent e) {
System.out.println("窗口关闭");
}
}
通过按键改变颜色
package test;
import javax.swing.*;
import java.awt.*;
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
// `EventQueue.invokeLater()` 确保在正确线程中更新 GUI,避免线程安全问题。
var f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.addWindowListener(new MyWindowListener());
f.setSize(300, 300);
var p = new JPanel();
var blackAction = new ColorAction("black", p, Color.BLACK);
var b1 = new JButton(blackAction);
var b2 = new JButton(new ColorAction("green", p, Color.GREEN));
var b3 = new JButton(new ColorAction("yellow", p, Color.YELLOW));
p.add(b1);
p.add(b2);
p.add(b3);
InputMap inputMap = p.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);// 输入 -> 动作名
inputMap.put(KeyStroke.getKeyStroke("ctrl B"), "black"); // B要大写
ActionMap actionMap = p.getActionMap(); // 动作名 -> 具体动作
actionMap.put("black", blackAction);
f.add(p);
f.setVisible(true);
});
}
}
关键代码:
var blackAction = new ColorAction("black", p, Color.BLACK);
var b1 = new JButton(blackAction);
InputMap inputMap = p.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);// 输入 -> 动作名
inputMap.put(KeyStroke.getKeyStroke("ctrl B"), "black"); // B要大写
ActionMap actionMap = p.getActionMap(); // 动作名 -> 具体动作
actionMap.put("black", blackAction);
需理解键盘焦点(keyboard focus)的概念。