8

私は JTable 用の多くのカスタム エディターを持っていますが、特にキーボードでの編集に関して、使いやすさが欠けていると言っても過言ではありません。

これの主な理由は、私のエディターは常にこれに似た (より複雑な場合が多い) 状況で作成されるためです。

@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
  JPanel container = new JPanel();
  container.setLayout(new BorderLayout());
  container.add(field, BorderLayout.CENTER);
  field.setText((String) value);
  container.add(new JButton("..."), BorderLayout.EAST);
  return container;
}

内部に複数のコンポーネントがあるパネル。実際のテキスト エディターは、エディターとして返されるコンポーネントの子孫です。したがって、レンダリングの問題は別として、JTable はgetTableCellEditorComponentメソッドによって返されるコンポーネントにフォーカスしているため、セルが強調表示された状態でキーを押すと、フォーカスとキーの押下がパネルに渡され、それがエディターであると考えられます。
「実際の」エディタが JTextfield であることを JTable に通知できる方法はありますか? キーの押下が渡されないため、正しいコンポーネントにハッキーrequestFocusInWindowを追加するだけでは不十分です。

4

4 に答える 4

2

私があなたの質問を正しく読んだ場合、最初にセルエディターをアクティブにすることなく、ユーザーがすぐにセルに入力できるようにしたい、つまり、セルをアクティブにしたキーストロークがテキストフィールドに入力された最初の文字になるようにしたい.

私の最初の試みは、KeyboardFocusManager の focusOwner プロパティに propertyChangeListener を追加することでしたが、フォーカスが JTable から離れないことに気付きました。あなたもおそらくそれに遭遇しました。プランBの時間。

インスタンス フィールドの keyPressed() メソッドの最後の KeyEvent を記録するテーブルに KeyListener を追加することで、「最初のキー押下」が機能するようになりました。そこから getTableCellEditorComponent() メソッドが文字を読み取ります。また、ユーザーが最初の文字の後に任意の文字を入力し続ける場合は、requestFocusInWindow() というハッキーな呼び出しが必要でした。

サンプル アプリでは、KeyListener を自身に追加する JTable のサブクラスを作成しました。CellEditor インスタンスに KeyListener を実装させ、代わりにそれを通常の JTable に追加することをお勧めしますが、それはあなたに任せます。

変更したコードスニペットは次のとおりです。

@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
    JPanel container = new JPanel();
    container.setLayout(new BorderLayout());
    container.add(field, BorderLayout.CENTER);

    // Will want to add an instanceof check as well as a check on Character.isLetterOrDigit(char).
    char keypressed = ((StickyKeypressTable)table).getLastKeyPressed();
    field.setText(String.valueOf(keypressed));

    container.add(new JButton("..."), BorderLayout.EAST);

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            // This needs to be in an invokeLater() to work properly
            field.requestFocusInWindow();
        }
    });
    return container;
}

厄介さに関する限り、これはVogon Poetryのどこかにありますが、差し迫った問題を解決するはずです.

于 2009-02-19T19:12:52.493 に答える
0

I had very similar problem. In my case I had complex TableCellEditor which consists of JSpinner and some other components. The problem was that when cell editor started I wanted to transfer focus to its internal component. I fixed this by calling panel.transferFocusDownCycle() but this in turn caused keyboard events to stop working - when my internal component had focus and I pressed key up, I was expecting that component will intercept this event and change its value. Instead table changed row focus to one above... I fixed this by adding KeyListener and dispatching all key events directly to the internal component.

This is wrapper class based on JPanel I wrote to make my life easier.

public class ContainerPanel extends JPanel implements KeyListener, FocusListener {

    private JComponent component = null;

    public ContainerPanel(JComponent component) {
        this.component = component;
        addKeyListener(this);
        addFocusListener(this);
        setFocusCycleRoot(true);
        setFocusTraversalPolicy(new ContainerOrderFocusTraversalPolicy());
        add(component);
    }

    @Override
    public void keyTyped(KeyEvent e) {
        component.dispatchEvent(e);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        component.dispatchEvent(e);
    }

    @Override
    public void keyReleased(KeyEvent e) {
        component.dispatchEvent(e);
    }

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

    @Override
    public void focusLost(FocusEvent e) {
    }
}
于 2012-11-15T21:09:51.333 に答える
0

似たようなものを2ステップで修正しました

まず、JTableからeditCellAtをオーバーライドし、エディターを準備した後にrequestFocusを呼び出します。

public boolean editCellAt( int row, int column, EventObject e )
{
  if ( cellEditor != null && !cellEditor.stopCellEditing() )
    {
    return false;
    }

  if ( row < 0 || row >= getRowCount() ||
      column < 0 || column >= getColumnCount() )
    {
    return false;
    }

  if ( !isCellEditable(row, column) )
    return false;

  TableCellEditor editor=getCellEditor(row, column);
  if ( editor != null && editor.isCellEditable(e) )
    {
    editorComp=prepareEditor(editor, row, column);
    if ( editorComp == null )
      {
      removeEditor();
      return false;
      }
    //aangepast
    Rectangle rect=getCellRect(row, column, false);
    if ( datamodel_.useAdaptedEditorRect() )
      rect=datamodel_.changeRectangle(rect, editorComp);
    editorComp.setBounds(rect);
    add(editorComp);
    editorComp.validate();

    setCellEditor(editor);
    setEditingRow(row);
    setEditingColumn(column);
    editor.addCellEditorListener(this);
    //NEXT LINE ADDED 
    editorComp.requestFocus();
    return true;
    }
  return false;
}

次に、JPanelからrequestFocusをオーバーロードし、テキストフィールドがeditorComponentとして配置されていることを確認します。

public class EditorPanel extends JPanel {
   JComponent editorComponent;

   public boolean isRequestFocusEnabled()
   {
     return true;
   }

   public void requestFocus()
   {
   editorComponent.requestFocus();
   }
}

いつでもkeyEventを取得して、自分で設定できます。

AWTEvent event = EventQueue.getCurrentEvent();
if ( event instanceof KeyEvent )
  {
  char newSelection = ( (KeyEvent) event).getKeyChar();
  int keyCode = ( (KeyEvent) event ).getKeyCode();
  editorComponent.requestFocus();
  if ( editorComponent instanceof JTextField )
    {
    if ( ( newSelection >= (char) FIRST_ALLOWED_CHAR ) && ( newSelection != (char) LAST_ALLOWED_CHAR ) ) //comes from DefaultKeyTypedAction
       ( (JTextField) editorComponent ).setText(Character.toString(newSelection));
    if ( keyCode == KeyEvent.VK_BACK_SPACE || keyCode == KeyEvent.VK_DELETE )
      ( (JTextField) editorComponent ).setText("");          
    }
  }
else
  editorComponent.requestFocus();
于 2009-02-20T08:07:17.917 に答える
0

解決したと思います。
実を言うと、カスタム エディター、カスタム レンダラーなどを使用しているため、何が問題を解決したのかわかりません...

セルが強調表示され、「abc」を押すと、3 文字が画面に表示されます (この場合はセル)。

grid.addKeyListener(new KeyAdapter() {
    public void keyTyped(KeyEvent ke) {
        int l = grid.getSelectedRow();
        int c = grid.getSelectedColumn();
        grid.editCellAt(l, c);
    }
});

うーん...試してみました... =)
(私のJTableはエディタとしてJTextFieldとJComboBoxを使用しているため、同じかどうかはわかりません)。

于 2009-03-04T20:16:18.660 に答える