Как выделить весь текст в ячейке JTable при редактировании, но не при вводе?

Поведение JTable по умолчанию заключается в добавлении к содержимому, когда вы начинаете печатать, и при щелчке помещает курсор в то место, где щелкнули. Я хочу, чтобы поведение обеих этих вещей изменилось, поэтому содержимое заменяется, когда я редактирую ячейку, либо вводя текст, либо щелкая, а затем вводя текст. Однако, когда я щелкаю ячейку, а затем меняю положение каретки, я хочу, чтобы содержимое оставалось, чтобы я мог его изменить.

Я знаю, как выбрать все, когда ячейка становится редактируемой, заменив редактор ячеек тем, который выбирает все внутри SwingUtilities.invokeLater (см. в другом месте), но это приводит к нарушению режима ввода. Когда я делаю это и начинаю печатать в ячейке, сначала введенный символ добавляется к строке, затем он выбирается (но выделение невидимо!) и при вводе другого символа содержимое заменяется этим.

Есть ли способ заменить содержимое сразу при вводе в выделенную (но не редактирование) ячейку, но выбрать все при нажатии на ячейку?

Вот код, который я использую для CellEditor:

public class TextFieldCellEditor extends JTextField implements TableCellEditor
{
    private CellEditorListener  cellEditorListener  = null;

    private boolean             isInteger           = false;
    private Object              oldValue;

    // Start editing
    @Override
    public Component getTableCellEditorComponent(JTable table, Object obj, boolean isSelected, int row, int column)
    {
        Color color2 = DefaultLookup.getColor(this, ui, "Table.alternateRowColor");
        super.setBackground(color2 != null && (row & 1) == 1? color2 : table.getBackground());
        super.setForeground(table.getForeground());
        super.setBorder(DefaultLookup.getBorder(this, ui, "Table.focusCellHighlightBorder"));

        super.setText(obj.toString());

        isInteger = obj instanceof Integer;
        if (isInteger)
        {
            super.setHorizontalAlignment(SwingConstants.RIGHT);
            oldValue = obj;
        }

        // SwingUtilities.invokeLater(new Runnable()
        // {
        // public void run()
        // {
        // TextFieldCellEditor.this.selectAll();
        // }
        // });

        return this;
    }

    // Retrieve e dited value
    @Override
    public Object getCellEditorValue()
    {
        if (isInteger)
        {
            // Try to convert to integer. If input is invalid, revert.
            try
            {
                return new Integer(super.getText());
            }
            catch (NumberFormatException e)
            {
                return oldValue;
            }
        }
        return super.getText();
    }

    @Override
    public boolean isCellEditable(EventObject e)
    {
        return true;
    }

    @Override
    public boolean shouldSelectCell(EventObject e)
    {
        return true;
    }

    @Override
    public boolean stopCellEditing()
    {
        cellEditorListener.editingStopped(new ChangeEvent(this));
        return true;
    }

    @Override
    public void cancelCellEditing()
    {
        cellEditorListener.editingCanceled(new ChangeEvent(this));
    }

    @Override
    public void addCellEditorListener(CellEditorListener celleditorlistener)
    {
        cellEditorListener = celleditorlistener;
    }

    @Override
    public void removeCellEditorListener(CellEditorListener celleditorlistener)
    {
        if (cellEditorListener == cellEditorListener) cellEditorListener = null;
    }
}

person Mark Jeronimus    schedule 17.11.2011    source источник
comment
эта реализация недействительна: а) не поддерживает добавление более одного слушателя б) не уведомляет своего слушателя, когда он остановлен/отменен по внутренним причинам (например, при нажатии клавиши ввода). См. источник DefaultCellEditor, чтобы получить представление о том, что нужно   -  person kleopatra    schedule 18.11.2011


Ответы (2)


В вашей реализации getTableCellEditorComponent() добавьте следующее:

if (isSelected) {
    this.selectAll();
}

Кстати, почему бы не расширить AbstractCellEditor или DefaultCellEditor(JTextField textField)? См. также Как использовать таблицы: использование других редакторов.

Приложение: См. также Таблица выбора всех визуализаторов и Редактор таблицы "Выбрать все"< /эм>.

person trashgod    schedule 17.11.2011

Самое чистое решение, которое я смог найти для этого случая, состояло в том, чтобы перезаписать editCellAt JTable и сообщить CellEditor о том, как было запущено редактирование:

@Override
public boolean editCellAt(int row, int column, EventObject e) {
    cellEditor.setKeyTriggered(e instanceof KeyEvent);
    return super.editCellAt(row, column, e);
}

И вот соответствующий код CellEditor:

public class MyCellEditor extends DefaultCellEditor {

    private boolean keyTriggered;

    public MyCellEditor() {
        super(new JTextField());
        final JTextField textField = (JTextField) getComponent();
        textField.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        if (!keyTriggered) {
                            textField.selectAll();
                        }
                    }
                });
            }
        });
    }

    public void setKeyTriggered(boolean keyTriggered) {
        this.keyTriggered = keyTriggered;
    }

    @Override
    public Component getTableCellEditorComponent(
            JTable table, Object value, boolean isSelected, int row, int column) {
        final JTextField textField = (JTextField)
                super.getTableCellEditorComponent(table, value, isSelected, row, column);
        textField.selectAll();
        return textField;
    }
}
person bdumitriu    schedule 23.11.2011