Java 使用TextComponents的GUI中的Swing键问题(箭头键、选项卡等)
我想将箭头键绑定到整个窗口的某些特定操作(无论哪个组件被聚焦)。我特别想用箭头键移动JList中的选择栏。我的窗口包含一个JTextArea和不同的JScrollPanes 我猜会出现以下问题:当我更改列表选择时,textarea会获得焦点(这取决于我想要实现的逻辑)。当JTextArea或JScrollPane具有焦点时,所有向上箭头等关键事件“丢失”(或者更确切地说,只影响TextComponent/Pane) 下面是一个小示例,它演示了问题:Java 使用TextComponents的GUI中的Swing键问题(箭头键、选项卡等),java,swing,keyevent,Java,Swing,Keyevent,我想将箭头键绑定到整个窗口的某些特定操作(无论哪个组件被聚焦)。我特别想用箭头键移动JList中的选择栏。我的窗口包含一个JTextArea和不同的JScrollPanes 我猜会出现以下问题:当我更改列表选择时,textarea会获得焦点(这取决于我想要实现的逻辑)。当JTextArea或JScrollPane具有焦点时,所有向上箭头等关键事件“丢失”(或者更确切地说,只影响TextComponent/Pane) 下面是一个小示例,它演示了问题: import java.awt.BorderL
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class KeyProblemExample extends JFrame implements ListSelectionListener {
private JList<Integer> list;
private JTextArea textArea;
private JLabel label;
public KeyProblemExample()
{
Font font = new Font("Dialog", Font.PLAIN, 20);
Integer[] listValues = {1, 2, 3};
list = new JList<>(listValues);
list.setFixedCellWidth(50);
list.setFont(font);
textArea = new JTextArea();
textArea.setEditable(false);
textArea.setLineWrap(true);
String text = Stream.generate(()-> "xyz").limit(300).collect(Collectors.joining());
textArea.setText(text);
textArea.setFont(font);
label = new JLabel("bla bla bla");
label.setFont(font);
}
private void buildLogic()
{
//list selection listener
list.addListSelectionListener(this);
//up and down keys
AbstractAction down = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (list.getSelectedIndex() >= 0 && list.getSelectedIndex() < list.getModel().getSize() - 1)
list.setSelectedIndex(list.getSelectedIndex() + 1);
}
};
AbstractAction up = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (list.getSelectedIndex() >= 1 && list.getSelectedIndex() < list.getModel().getSize())
list.setSelectedIndex(list.getSelectedIndex() - 1);
}
};
KeyStroke keyDown = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, KeyEvent.ALT_MASK);
label.getActionMap().put("indexDown", down);
label.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyDown, "indexDown");
KeyStroke keyUp = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0);
label.getActionMap().put("indexUp", up);
label.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyUp, "indexUp");
}
private void displayGUI()
{
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
JScrollPane sp1 = new JScrollPane();
sp1.setViewportView(textArea);
sp1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
sp1.setWheelScrollingEnabled(true);
JScrollPane sp2 = new JScrollPane();
sp2.setViewportView(list);
sp2.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
sp2.setWheelScrollingEnabled(true);
panel.add(sp1, BorderLayout.CENTER);
panel.add(sp2, BorderLayout.EAST);
panel.add(label, BorderLayout.SOUTH);
this.getContentPane().add(panel);
this.pack();
this.setSize(400,400);
this.setLocationByPlatform(true);
this.setVisible(true);
}
@Override
public void valueChanged(ListSelectionEvent e) {
textArea.requestFocus();
// label.requestFocus();
}
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
KeyProblemExample x = new KeyProblemExample();
x.buildLogic();
x.displayGUI();
}
};
SwingUtilities.invokeLater(r);
}
}
导入java.awt.BorderLayout;
导入java.awt.Font;
导入java.awt.event.ActionEvent;
导入java.awt.event.KeyEvent;
导入java.util.stream.collector;
导入java.util.stream.stream;
导入javax.swing.AbstractAction;
导入javax.swing.JComponent;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JList;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
导入javax.swing.JTextArea;
导入javax.swing.KeyStroke;
导入javax.swing.ScrollPaneConstants;
导入javax.swing.SwingUtilities;
导入javax.swing.event.ListSelectionEvent;
导入javax.swing.event.ListSelectionListener;
公共类KeyProblemExample扩展JFrame实现ListSelectionListener{
私人名单;
私人JTEXTEXTAREA textArea;
私人标签;
公钥问题示例()
{
Font Font=新字体(“对话框”,Font.PLAIN,20);
整数[]listValues={1,2,3};
列表=新的JList(列表值);
列表。设置固定单元格宽度(50);
list.setFont(字体);
textArea=新的JTextArea();
textArea.setEditable(false);
textArea.setLineWrap(true);
String text=Stream.generate(()->“xyz”).limit(300.collect(Collectors.joining());
textArea.setText(text);
textArea.setFont(字体);
标签=新的JLabel(“bla bla bla”);
label.setFont(字体);
}
私有void buildLogic()
{
//列表选择侦听器
list.addListSelectionListener(此);
//上下键
AbstractAction down=新建AbstractAction(){
@凌驾
已执行的公共无效操作(操作事件e){
如果(list.getSelectedIndex()>=0&&list.getSelectedIndex()=1&&list.getSelectedIndex()
在本例中,Alt ArrowDown命令起作用,而普通ArrowUp命令不起作用。如果我更改requestFocus()
行,以便标签请求焦点,则ArrowUp也可以工作(因为现在标签而不是文本区域获得焦点)
我的问题:如何将箭头键等“窗口范围”键绑定到特定操作(特别是如果我的窗口中有文本组件)。文本组件的键绑定在有焦点时优先。因此,您需要使用以下代码从文本组件中删除绑定:
textComponent.getInputMap().put(KeyStroke.getKeyStroke("UP"), "none");
有关更多信息,请参阅Swing教程中的部分。文本组件的键绑定在具有焦点时优先。因此,您需要使用以下代码从文本组件中删除绑定:
textComponent.getInputMap().put(KeyStroke.getKeyStroke("UP"), "none");
有关更多信息,请参阅Swing教程中的部分。谢谢@camickr,问题可以通过您的提示解决 。。。以下是一些进一步的信息/解决方案:
TextArea
和ScrollPane
组件的向上和向下箭头键输入(在调用此命令之前,必须实例化每种类型的一个对象)KeyEventDispatcher
禁用整个窗口的按键:
KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
manager.addKeyEventDispatcher(new KeyEventDispatcher() {
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_PRESSED) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_DOWN) {
//doAction
return true;
}
else if (keyCode == KeyEvent.VK_UP) {
//doAction
return true;
}
}
return false;
}
});
这将分别对按下“窗口宽度”的上箭头和下箭头键执行“doAction”命令。由于该方法在这两种情况下都返回true,因此键事件将不会被分派到其他组件,因此该键将得到d