如何指示我的Swing组件立即获取焦点 ? requestFocus()
似乎没有立即发送。
理想情况下,我希望这样(从EDT开始):
textInput.requestFocusInWindow();
System.out.println(textInput.hasFocus());
打印true
。
以下是SSCCE。备注/要求:
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);
};
}
答案 0 :(得分:2)
我明白了。
AncestorListener
和processKeyBinding()
中的事件是处理同一事件的一部分:“键入类型”。requestFocus()
,它会在“key typed”触发的当前事件流之后添加到事件队列中。因此,抓住焦点并执行FocusListener
将始终执行。解决方案是:在processKeyBinding()
中,不要立即将密钥传递给内部组件。将其排入事件队列,以便在焦点传输和侦听器之后执行。也就是说,换行:
if (ks.getKeyEventType() == KeyEvent.KEY_TYPED) {
textField.processKeyBinding(ks, e, condition, pressed);
}
进入SwingUtilities.invokeLater()
。
答案 1 :(得分:0)
我不认为这是可能的。 UI操作本质上是异步的(尽管通常非常快),并且无法强制它们同步运行。如果你确实需要这个,可以在文本输入的焦点处理程序中触发事件,并在另一个线程中等待该事件。
答案 2 :(得分:0)
我不知道如何控制事件的顺序,一般而言,这不是你应该尝试做的事情。
3.文本字段是第三方编辑器,具有焦点监听器干扰 用我的代码
也许您可以从编辑器中删除FocusListener。也许你可以使用
直接调用监听器savedFocusListener.focusGained(FocusEvent);
在AncestorListener代码中,将焦点设置在文本字段上。