当前位置: 首页 > 知识库问答 >
问题:

JTextField与JTable中的JComboBox行为

后易安
2023-03-14

好吧,这很难解释,但我会尽力的。

我在JTable中有一个JTextField和一个JComboBox,它的getCellEditor方法被覆盖如下:

public TableCellEditor getCellEditor( int row, int column ) {
        if ( column == 3 ) {
              // m_table is the JTable

              if ( m_table.getSelectedRowCount() == 1 ) {             
                JComboBox choices = new JComboBox();
                choices.setEditable( true );
                choices.addItem( new String( "item 1" ) );

                return new DefaultCellEditor( choices );
         }

         return super.getCellEditor( row, column );
}

以下是行为差异(请注意,从现在开始,当我说JTextField或JComboBox时,我指的是JTable中包含任一组件的单元格):

>

当我使用tab键或箭头键导航到JTextField,然后开始键入时,我键入的字符会自动输入单元格。然而,当我以同样的方式导航到JComboBox,然后开始键入时,除了出现组合下拉按钮外,什么也不会发生。除非我先按F2键,否则我键入的字符都不会被输入。

所以我的问题是:在上面描述的两个实例中,我需要做什么才能让JComboBox的行为完全像JTextFields?

请不要问我为什么要做我正在做的事情,或者建议替代方案(就是这样,我需要这样做),是的,我已经阅读了所有有问题的组件的应用编程接口......问题是,这是一个摇摆应用编程接口。

共有2个答案

徐茂材
2023-03-14

bullet 2的另一种选择是将keyEvents的所有传递移动到定制的JComboBox实现中:在那里,实现其processKeyBinding,类似于table。进程键绑定。比如:

public static class JTableEditorComboBox extends JComboBox {

    @Override
    protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
            int condition, boolean pressed) {
        boolean result = super.processKeyBinding(ks, e, condition, pressed);
        if (!result) 
            result = processKeyBindingForTextField(ks, e, condition, pressed);
        return result;
    }

    private boolean processKeyBindingForTextField(KeyStroke ks, KeyEvent e,
            int condition, boolean pressed) {
        // sanity check: really used as cellEditor
        if (!Boolean.TRUE.equals(getClientProperty("JComboBox.isTableCellEditor")) 
               || !isEditable() 
               || !(getEditor().getEditorComponent() instanceof JTextField)) return false;
        JTextField field = (JTextField) getEditor().getEditorComponent();
        // basically c&p JComponent.processKeyBinding (it's protected so
        // can't call directly from here)
        InputMap map = field.getInputMap(WHEN_FOCUSED);
        ActionMap am = field.getActionMap();

        if(map != null && am != null && isEnabled()) {
            Object binding = map.get(ks);
            Action action = (binding == null) ? null : am.get(binding);
            if (action != null) {
                return SwingUtilities.notifyAction(action, ks, e, field,
                                                   e.getModifiers());
            }
        }

        return false;
    }

}

然后,在cellEditor中使用一个实例,比如:

JTable table = new JTable(new AncientSwingTeam()) {

    @Override
    public TableCellEditor getCellEditor(int row, int column) {
        if (column == 1) {
            // m_table is the JTable

            JComboBox choices = new JTableEditorComboBox();
            choices.setEditable(true);
            choices.addItem(new String("item 1"));

            DefaultCellEditor editor = new DefaultCellEditor(choices);
            editor.setClickCountToStart(2);
            return editor;
        }

        return super.getCellEditor(row, column);
    }

};
袁卓
2023-03-14

进一步的谷歌搜索让我看到了以下文章:

http://www.jroller.com/santhosh/entry/keyboard_handling_in_tablecelleditor

虽然它没有描述与我相同的问题,但它肯定有一些共同的特点。

使用这篇文章中的一些建议,我能够(至少)解决我问题中的键盘位(我问题的第2点中描述的那个)。我通过覆盖JTableProcKeyBinding方法做到了这一点,如下所示:

protected boolean processKeyBinding( KeyStroke key_stroke, KeyEvent e, int condition, boolean pressed ) {
        Object source = e.getSource();

        if ( source instanceof JTable ) {
          JTable table = (JTable) source;
          Component comp = table.getEditorComponent();

          if ( comp instanceof JComboBox ) {
            JComboBox combo_box = (JComboBox) comp;

            // this bit is quite hacky. Since I want comboboxes to behave exactly like textfields,
            // simply check to see how a textfield would handle this event.
            JTextField tmp_field = new JTextField();
            InputMap input_map = tmp_field.getInputMap( condition );
            ActionMap action_map = tmp_field.getActionMap();

            if( input_map != null && action_map != null && isEnabled() ) {
                Object binding = input_map.get( key_stroke );
                Action action = ( binding == null ) ? null : action_map.get( binding );

                if( action != null ) {
                    combo_box.requestFocus();
                    ComboBoxEditor combo_editor = combo_box.getEditor();
                    JTextField text_field = (JTextField) combo_editor.getEditorComponent();

                    if ( e.getKeyChar() == ' ' ) {    // backspace
                      String cur_val = text_field.getText();
                      if ( ! cur_val.equals( "" ) )
                        text_field.setText( cur_val.substring( 0, cur_val.length() - 1 ) );
                    }                          
                    else
                      text_field.setText( text_field.getText() + e.getKeyChar() );

                    return false;
                }
            }
          }
        }

        return super.processKeyBinding( key_stroke, e, condition, pressed );
}

这种方法对我来说似乎有点像黑客,但它又是摇摆的,所以它可能是合理的。

在我问题的第1点描述的场景中(即使用鼠标时),让JComboxes表现得像JTextFields一样的问题仍然存在,如果有人想尝试一下的话。

 类似资料:
  • 现在,在第一行第三列(“OK”)中,您可以在JComboBox中选择表示一行的不同条目。因此一行有三个引用另一行的JComboBoxes。如果您在这样的JComboBox中单击,您会注意到它总是选择第一个条目,而不是您在单击之前看到的带有数字的条目。 也许现在你明白我想做什么了?

  • 问题内容: 我不知道如何在特定行中设置一个jcombobox …现在我已经为所有行设置了这个jcombobox,但是我只希望在一行中设置它: 问题答案: 更新: 在测试我的(可能是不完整的)答案时,我遇到了一个非常好的SO问题,我认为它将比我能提供的更好:将JComboBox放入JTable 另一个更新: 我再次阅读了您的问题,并且意识到您要求输入 特定的行 。我能想到的唯一方法是创建一个自定义C

  • 我创建了一个表单,其中添加了一个,它有3列。第二列和第三列有编辑器。 我希望当我们选择第二列组合框的第一项时,第三列组合框的第一个组合框也应该被选择,反之亦然。 我该怎么做?

  • 我有一个在运行时加载行的表。加载后,用户需要在每一行的第一列中从中选择一个项目。然后他需要在每行的同一行上从另一个中选择一个项目。第二个的内容取决于第一个的选择。 我现在的编码方式是更改整个第二列的combobox内容。 有没有一种方法可以让每一行的组合框对象都不一样,这样我就可以在第一个组合框中选择一个值的时候处理它?

  • 我有一个JTable对象,我会在一个列上添加5个不同的JComboBox。 我已经尽力了: 但这会将相同的JComboBox添加到该列的所有单元格中。如何在同一列中添加不同的内容? 非常感谢。

  • 我试图在JTable的某个列中放置一个JComboBox。我有这个代码,它正在工作: 我的问题是,在选中该列中的一个单元格之前,它不会显示为JComboBox。加载JFrame时,整个表看起来都一样,好像所有单元格中只有文本。单击时,它会显示组合框的箭头和选项,但再次取消选择时,它看起来像一个常规单元格。 有办法绕过它吗?