gpt4 book ai didi

java - Swing - 如何*现在*捕获焦点?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:40:44 30 4
gpt4 key购买 nike

如何指示我的 Swing 组件立即获取焦点? requestFocus() 似乎没有被立即调度。

理想情况下,我希望这样(从 EDT 运行):

textInput.requestFocusInWindow();
System.out.println(textInput.hasFocus());

打印true

下面是 SSCCE。备注/要求:

  1. 表格是用键盘导航的。 C2 列有一个复合编辑器。
  2. 当我在 C2 列中键入一个字母时,编辑开始。复合编辑器中的文本组件获得焦点。它需要键入启动编辑器的字母。这一点的实现被标记为“技巧”的注释。
  3. 文本字段是第 3 方编辑器,它有一个干扰我的代码的焦点监听器。这里模拟为 selectAll()

目前调度顺序是:在文本组件中输入字母,然后调度焦点监听器。然后下一个字母会被正确发送,因为文本字段才是焦点。

我需要它来将焦点设置在文本组件上,调度焦点监听器,然后将键事件传递给它。


public class JTableIssue extends JFrame {
public JTableIssue() {
JTable table = new JTable(new Object[][] {
{ "Apple", "Orange", "Strawberry" },
{ "Pineapple", "Orange", "Zergz" } }, new Object[] { "C1",
"C2", "C3" });
table.getColumn("C2").setCellEditor(new MyEditor());
add(new JScrollPane(table));
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public static void main(String[] args) {
new JTableIssue().setVisible(true);
}
}

class MyEditor extends AbstractCellEditor implements TableCellEditor {
MyTextField textField = new MyTextField();
JPanel panel;

MyEditor() {
panel = new JPanel(new BorderLayout()){
// Trick: Pass all key typed to text field
@Override
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
int condition, boolean pressed) {
if (ks.getKeyEventType() == KeyEvent.KEY_TYPED) {
textField.processKeyBinding(ks, e, condition, pressed);
}
return super.processKeyBinding(ks, e, condition, pressed);
}
};
textField.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
textField.selectAll();
}
});
panel.add(textField, BorderLayout.CENTER);
// Trick: Pass focus to text field when editor is added to table
panel.addAncestorListener(new AncestorListener() {
public void ancestorRemoved(AncestorEvent event) {
}

public void ancestorMoved(AncestorEvent event) {
}

public void ancestorAdded(AncestorEvent event) {
textField.requestFocus();
}
});
}

public Object getCellEditorValue() {
return textField.getText();
}

public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
textField.setText(value.toString());
return panel;
}
}

class MyTextField extends JTextField {
// Trick: "public"
@Override
public boolean processKeyBinding(javax.swing.KeyStroke ks,
java.awt.event.KeyEvent e, int condition, boolean pressed) {
return super.processKeyBinding(ks, e, condition, pressed);
};
}

最佳答案

我想通了。

  1. AncestorListenerprocessKeyBinding() 中的事件是处理同一事件的一部分:“输入键”。
  2. 显然,获取焦点的唯一方法是 requestFocus(),它会在“键入的键”触发的当前事件流之后添加到事件队列中。因此,获取焦点并执行 FocusListener 将始终在稍后执行。

解决方法是:在processKeyBinding()中,不要立即将key传给内部组件。将其放入事件队列中,以便在焦点转移和监听器之后执行。即,换行:

if (ks.getKeyEventType() == KeyEvent.KEY_TYPED) {
textField.processKeyBinding(ks, e, condition, pressed);
}

进入 SwingUtilities.invokeLater()

关于java - Swing - 如何*现在*捕获焦点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3389335/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com