【问题标题】:Java Swing: JTextField doesn't lose focus as expectedJava Swing:JTextField 没有按预期失去焦点
【发布时间】:2012-06-02 20:01:10
【问题描述】:

我有一个有 2 列的 JTable。其中一列由 JTextField 表示,另一列由单选按钮表示。

以这种方式填充模型:

   model.addRow(new Object[]{radioButton, ""});

与 JTextField 相关联的单元格编辑器是这样的:

class MyCellEditor extends DefaultCellEditor {

  MyCellEditor(JTextField textField) {
    super(textField);
    textField.addFocusListener(new FocusListener() {

        public void focusLost(FocusEvent e) {
            // do something if focus is lost
        }

        @Override
        public void focusGained(FocusEvent e) {
        }
    });
}

当我单击 JTextField 单元格时,我会按预期得到一个“闪烁”光标,因此我可以输入我的文本。无论如何,如果我单击主窗口中的其他任何位置,我希望使用“focusLost(...)”方法已被调用,但只有当我在窗口中“播放”一下时才会发生这种情况(比如几次点击进出 jtextfield)。

为什么组件在第一次点击另一个外部组件后没有失去焦点?

【问题讨论】:

    标签: java swing focus jtable jtextfield


    【解决方案1】:

    我是这样解决的:

    1) 将焦点放在新的 JTextField:

     if (editCellAt(getRowCount()-1, 1)) getEditorComponent().requestFocus();
    

    2) 表格自动检测失去焦点:

     table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
    

    3) 在 "MyCellEditor class --> @Override public boolean stopCellEditing()" 中只检查组件是否有焦点:

     getComponent().isFocusOwner()
    

    【讨论】:

      【解决方案2】:

      您可以在TableCellEditor 中覆盖stopEditing()

      或者直接写

      table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
      

      更复杂的(JFormattedTextField)例子

      import java.awt.Component;
      import java.awt.EventQueue;
      import java.text.DecimalFormat;
      import java.text.ParseException;
      import javax.swing.*;
      import javax.swing.table.TableCellEditor;
      import javax.swing.table.TableCellRenderer;
      import javax.swing.table.TableColumnModel;
      
      public class EditorAsRendererTableTest {
      
          public static void main(String[] args) {
              EventQueue.invokeLater(new Runnable() {
      
                  @Override
                  public void run() {
                      JTable table = new JTable(3, 2);
                      TableColumnModel colModel = table.getColumnModel();
                      MyCellEditor both = new MyCellEditor();
                      colModel.getColumn(0).setCellEditor(both);
                      colModel.getColumn(0).setCellRenderer(both);
                      JFrame frame = new JFrame("Test");
                      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                      frame.getContentPane().add(new JScrollPane(table));
                      frame.pack();
                      frame.setLocationRelativeTo(null);
                      frame.setVisible(true);
                  }
              });
          }
      
          private static class MyCellEditor extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
      
              private static final long serialVersionUID = 1L;
              private JFormattedTextField renderer = new JFormattedTextField(DecimalFormat.getInstance());
              private JFormattedTextField editor;
      
              @Override
              public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                  renderer.setValue(value);
                  return renderer;
              }
      
              @Override
              public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
                  editor = new JFormattedTextField(DecimalFormat.getInstance());
                  editor.setValue(value);
                  return editor;
              }
      
              @Override
              public boolean stopCellEditing() {
                  try {
                      editor.commitEdit();
                  } catch (ParseException e) {
                      return false;
                  }
                  return super.stopCellEditing();
              }
      
              @Override
              public Object getCellEditorValue() {
                  return editor.getValue();
              }
          }
      
          private EditorAsRendererTableTest() {
          }
      }
      

      【讨论】:

      • 我过去已经尝试过这两种方法,但它们都不起作用(无论如何我认为使用 stopEditing() 你指的是:public boolean stopCellEditing())。就我而言,stopCellEditing() 仅在按下“enter”键时调用。
      • @Randomize 请在此处查看我的编辑,不要忘记也覆盖 cancelCellEditing()
      • 感谢您的帮助。我运行您的演示代码,看起来在我单击文本字段后我无法单击其他任何地方。是否意味着“最佳实践”,以便文本字段在输入值之前不会失去焦点?
      • @Randomize Focus 不是 JTable 的正确监听器,不要忘记覆盖 cancelCellEditing(),这是真正 CellEditor 的后半部分
      • 当焦点移开时我看不到差异。如果我单击其他地方,则不会调用 stopCellEditing 和 cancelCellEditing。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-05
      • 1970-01-01
      • 1970-01-01
      • 2012-01-02
      • 2020-05-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多