简体   繁体   English

如何在编辑时选择JTable单元格中的所有文本,而不是在键入时选择?

[英]How to select all text in JTable cell when editing but not when typing?

The default behavior of a JTable is to append to the contents when you start typing, and to place the caret at the clicked location when clicking. JTable的默认行为是在您开始键入时附加到内容,并在单击时将插入符号放在单击的位置。 I want the behavior of both these things to change, so the contents is replaced when I edit a cell, either by typing or by clicking and then typing. 我希望这两件事的行为都能改变,因此当我编辑单元格时,通过键入或单击然后键入来替换内容。 When I click a cell and then change the caret position, however, I want the contents to stay so I can change it. 然而,当我单击一个单元格然后更改插入位置时,我希望内容保留,以便我可以更改它。

I know how to select all when the cell becomes editing, by replacing the cell editor with one that selects all inside a SwingUtilities.invokeLater (see elsewhere ), but that causes the typing behavior to break. 我知道如何在单元格编辑时选择所有内容,方法是将单元格编辑器替换为选择SwingUtilities.invokeLater内部的单元格编辑器(参见其他地方 ),但这会导致键入行为中断。 When I do this and start typing in a cell, first the typed character is appended to the string, then it is selected (but the selection is invisible!) and when typing another character the contents gets replaced by that. 当我这样做并开始键入单元格时,首先将键入的字符附加到字符串,然后选择它(但选择是不可见的!),当键入另一个字符时,内容将被替换。

Is there a way to replace the contents immediately when typing in a highlighted (but not editing) cell, but select all when clicking a cell? 有没有办法在键入高亮(但不是编辑)单元格时立即替换内容,但在单击单元格时选择全部?

Here is the code I use for the CellEditor: 这是我用于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;
    }
}

In your getTableCellEditorComponent() implementation, add the following: getTableCellEditorComponent()实现中,添加以下内容:

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

As an aside, why not extend AbstractCellEditor or DefaultCellEditor(JTextField textField) ? DefaultCellEditor(JTextField textField) ,为什么不扩展AbstractCellEditorDefaultCellEditor(JTextField textField) See also How to Use Tables: Using Other Editors . 另请参见如何使用表:使用其他编辑器

Addendum: See also Table Select All Renderer and Table Select All Editor . 附录:另请参见表格选择所有渲染器表格选择所有编辑器

The cleanest solution I could find for this case was to overwrite the JTable's editCellAt and inform the CellEditor of how the edit was triggered: 我能找到的最简洁的解决方案是覆盖JTable的editCellAt并告知CellEditor如何触发编辑:

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

And here is the relevant CellEditor code: 这是相关的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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM