我创建了一个接收Action的JButton类,JButton类包括击键和&鼠标监听器,所以我可以根据需要在多个帧中使用相同的类。
我的问题是: 按下键时JButton没有获得焦点,但它正在执行操作。 我需要创建一个新的背景或告诉用户该按钮执行操作的东西。
任何想法??
这是我的代码:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;
import swtdesigner.SwingResourceManager;
public class IButtonSave extends JButton{
private static final long serialVersionUID = 1L;
private Action action = null;
public IButtonSave() {
super();
setFocusPainted(true);
setFocusable(true);
try {
jbInit();
} catch (Throwable e) {
e.printStackTrace();
}
}
private void jbInit() throws Exception {
setMargin(new Insets(0, 0, 0, 0));
setBorder(new LineBorder(Color.black, 1, true));
setIconTextGap(0);
setHorizontalTextPosition(SwingConstants.CENTER);
setVerticalTextPosition(SwingConstants.TOP);
setPreferredSize(new Dimension(50, 43));
setMinimumSize(new Dimension(50, 43));
setMaximumSize(new Dimension(50, 43));
addMouseListener(new ThisMouseListener());
setVerifyInputWhenFocusTarget(true);
}
public void setAction(Action a){
action = a;
KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_F1,0,true);
KeyStroke ks2 = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0);
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, "Save");
getInputMap(JComponent.WHEN_FOCUSED).put(ks2, "Save");
getActionMap().put("Save", a);
setText("Save [F1]");
setIcon(SwingResourceManager.getIcon(SwingResourceManager.class, "/images/small/save.png"));
setToolTipText("[F1]");
}
private class ThisMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
this_mouseClicked(e);
}
}
protected void this_mouseClicked(MouseEvent e) {
if(e.getClickCount() >= 1){
action.actionPerformed(null);
}
}
}
答案 0 :(得分:5)
为什么只要将JButton
添加到其实例中,就可以扩展KeyBinding
类?
不确定你想要什么,但这对我来说很好:
基本上可以通过鼠标点击激活JButton
,或按 F1 (只要焦点在窗口中,如果按下则将焦点转移到JButton
)或 ENTER (仅在JButton
焦点时)。
当AbstractAction
被调用时,它将在requestFocusInWindow()
上调用JButton
(因此按 F1 会使按钮获得焦点,这是我认为你想要的) :
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JButton btn = new JButton("Button");
AbstractAction aa = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Here");
btn.requestFocusInWindow();//request that the button has focus
}
};
//so button can be pressed using F1 and ENTER
btn.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Enter");
btn.getActionMap().put("Enter", aa);
btn.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0), "F1");
btn.getActionMap().put("F1", aa);
btn.addActionListener(aa);//so button can be clicked
JTextField tf = new JTextField("added to show ENTER wont work unless button in focus");
frame.add(tf);
frame.add(btn, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
});
}
}
<强> UPADTE:强>
或者@GuillaumePolet建议(+1给他)覆盖processKeyBinding
的{{1}}并检查适当的密钥而不是调用方法:
JButton
答案 1 :(得分:3)
不确定这是做到这一点的最佳方式,但它运作得相当不错,如果不是最好的方式,你可以从这个答案中获得免费的SSCCE。
我重写了processKeyBindings(),如果它返回true,那么我抓住焦点指示已经执行了该动作。如果你想做别的事,你只需要在那里修改代码。
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class IButtonSave extends JButton {
private static final long serialVersionUID = 1L;
public IButtonSave() {
super();
setFocusPainted(true);
setFocusable(true);
}
@Override
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
boolean processKeyBinding = super.processKeyBinding(ks, e, condition, pressed);
if (processKeyBinding) {
requestFocusInWindow();
}
return processKeyBinding;
}
@Override
public void setAction(Action a) {
super.setAction(a);
KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0, true);
KeyStroke ks2 = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, "Save");
getInputMap(JComponent.WHEN_FOCUSED).put(ks2, "Save");
getActionMap().put("Save", a);
setText("Save [F1]");
setToolTipText("[F1]");
}
protected void initUI() {
JFrame frame = new JFrame(IButtonSave.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextArea textarea = new JTextArea(5, 30);
JPanel buttonPanel = new JPanel();
AbstractAction someAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.err.println("Action performed");
}
};
IButtonSave button = new IButtonSave();
button.setAction(someAction);
buttonPanel.add(button);
frame.add(new JScrollPane(textarea));
frame.add(buttonPanel, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new IButtonSave().initUI();
}
});
}
}