1

わかりました、これは説明するのが難しいものですが、私は最善を尽くします。

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のCELLを意味します)。

  1. JTextFieldを1回クリックすると、セルが強調表示されます。ダブルクリックするとカレットが表示され、テキストを入力できます。一方、JComboBoxでは、シングルクリックすると、テキストを入力するためのキャレットと、コンボドロップダウンボタンが表示されます。

  2. タブを押すか、矢印キーを使用してJTextFieldに移動してから入力を開始すると、入力した文字が自動的にセルに入力されます。一方、同じ方法でJComboBoxに移動してから入力を開始すると、コンボドロップダウンボタンが表示される以外は何も起こりません。最初にF2キーを押さない限り、入力した文字は入力されません。

だからここに私の質問があります:上記の2つのインスタンスでJComboBoxesをJTextFieldsとまったく同じように動作させるために何をする必要がありますか?

なぜ私がやっていることをしているのか尋ねたり、代替案を提案したりしないでください(それは現状であり、この方法で行う必要があります)。はい、問題のすべてのコンポーネントのAPIを読みました。問題は、それがスイングAPIであるということです。

4

2 に答える 2

2

箇条書き2の代替手段は、keyEventsのすべての受け渡しをカスタムJComboBox実装に移動することです。そこで、table.processKeyBindingと同様のprocessKeyBindingを実装します。何かのようなもの:

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);
    }

};
于 2012-10-06T15:56:12.120 に答える
2

さらにグーグルで調べたところ、次の記事にたどり着きました。

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

私の問題と同じ問題を説明しているわけではありませんが、いくつかの共通の特徴を共有していることは間違いありません。

その記事のいくつかの提案を使用して、私の問題 (私の質問のポイント 2 で説明したもの) のキーボードのビットを (少なくとも) 解決することができました。次processKeyBindingのようにメソッドをオーバーライドしてこれを行いました。JTable

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で説明したシナリオ(つまり、マウスを使用する場合)でJComboBoxesをJTextFieldsのように動作させる問題は、誰かが試してみたい場合はまだ未解決です。

于 2012-10-05T17:12:48.220 に答える