我正在尝试使用单个按钮获取一个简单的JFrame,以便在发生任何这些事件时触发事件:
似乎Enter和空格键是“免费”,以及使用JButton上的addActionListener默认鼠标点击;麻烦的是,我已经读过,键绑定取决于使用的外观。
我试图通过将Enter和空格键添加到JButton的动作映射来在LaF中获得通用行为,甚至添加了一个随机键(“m”)以确保ActionMap正在完成工作(它是),但是现在鼠标点击丢失了。我似乎能够获得所有键和鼠标单击的唯一方法是使用动作映射和addActionListener。
有没有办法让这些键和鼠标绑定在所有LaF中一致地工作,而不试图检测可能出现的每个可能的LaF?我可以注册一个动作侦听器,它将触发键和鼠标事件吗?
我最喜欢的解决方案是将鼠标单击添加到JButton动作贴图中,并检测动作内部发生的键或鼠标点击。
我还在这里学习绳索,所以这可能不是最好或最有效的做事方式;我确定它过度设计了。这是一种训练练习,我正在试验我能掌握的一切。欢迎任何和所有编码风格的评论!
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
public class Example extends JFrame {
// ============================
private class BtnListener extends AbstractAction {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent ae) {
System.out.println("\nclick button listener triggered");
System.out.println(ae.getSource().getClass().toString());
}
} // class BtnListener
private static final int NO_MODIFIER = 0;
private static final boolean ON_KEY_PRESS = false;
private static final KeyStroke ENTER_PRESSED = KeyStroke.getKeyStroke(
KeyEvent.VK_ENTER, NO_MODIFIER, ON_KEY_PRESS);
private static final KeyStroke M_PRESSED = KeyStroke.getKeyStroke(
KeyEvent.VK_M, NO_MODIFIER, ON_KEY_PRESS);
private static final KeyStroke SPACEBAR_PRESSED = KeyStroke.getKeyStroke(
KeyEvent.VK_SPACE, NO_MODIFIER, ON_KEY_PRESS);
private JButton btnButton;
private final AbstractAction btnListener = new BtnListener();
private JPanel buttonPanel;
private JFrame frmMain;
public static void main(String[] args) {
Example ex = new Example();
ex.displayFrame();
}
Action btnActionListener = new AbstractAction() {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
System.out.println("\nkey button action triggerred");
System.out.println(e.getSource().getClass().toString());
if (e.getSource() instanceof JButton) {
System.out.println("button");
} else {
System.out.println("Something else");
}
}
};
public Example() {
initialize();
}
public void displayFrame() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Throwable e) {
e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
frmMain.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void initialize() {
frmMain = new JFrame();
btnButton = new JButton("Abutton");
// Comment this out, you lose the mouse click
btnButton.addActionListener(btnListener);
// Comment out ActionMaps, but keep addActionListner (above), and
// only lose M_PRESSED
InputMap buttonFocusedMap = btnButton
.getInputMap(JComponent.WHEN_FOCUSED);
buttonFocusedMap.put(ENTER_PRESSED, "blah");
btnButton.getActionMap().put("blah", btnActionListener);
buttonFocusedMap.put(SPACEBAR_PRESSED, "blort");
btnButton.getActionMap().put("blort", btnActionListener);
buttonFocusedMap.put(M_PRESSED, "gaaak");
btnButton.getActionMap().put("gaaak", btnActionListener);
// Is there a way to add a mouse click to the ActionMap?
buttonPanel = new JPanel();
buttonPanel.add(btnButton);
frmMain.getContentPane().add(buttonPanel);
frmMain.setBounds(100, 100, 500, 432);
frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
答案 0 :(得分:9)
BasicButtonListener
使用的 BasicButtonUI
确保所有按钮(检查,无线电,切换)在聚焦时绑定到 Space 。这可以跨平台工作,即使个人外观和感觉可以唯一地呈现各种按钮模型状态。按 Space 会唤醒按下 UIAction
,释放 Space 会唤起已发布的 UIAction
。在按钮的界限内按下并释放鼠标时也会出现同样的情况;在按下时拖动按钮以查看布防状态变化。
在任何一种情况下,按下和释放的组合会调用按钮的actionPerformed()
方法。
通过根窗格的setDefaultButton()
方法,将 Enter 绑定到Action
的一种简便方法是无关紧要。这个example说明了点击按钮的所有三种方式。
答案 1 :(得分:0)
您可以(也可能应该)做的是创建一个AbstractAction。您可以将AbstractAction用于ActionMap以及单击(执行JButton.setAction(...))