Java 在基于JTable面板的单元编辑器中丢失第一个字符

Java 在基于JTable面板的单元编辑器中丢失第一个字符,java,swing,tablecelleditor,Java,Swing,Tablecelleditor,我有一个单元格编辑器,其中包含一个小按钮,然后是一个文本字段,可用于内联编辑值 我使用setSurrendersFocusOnKeystroke(true)和焦点侦听器,以便用户立即从键盘开始编辑,但问题是第一次按下的键似乎被消耗掉了,而不是被添加到文本字段中,我如何防止这种情况 下面是完整的自包含示例 import javax.swing.*; import java.awt.*; import java.awt.event.FocusEvent; import java.awt.event.

我有一个单元格编辑器,其中包含一个小按钮,然后是一个文本字段,可用于内联编辑值

我使用setSurrendersFocusOnKeystroke(true)和焦点侦听器,以便用户立即从键盘开始编辑,但问题是第一次按下的键似乎被消耗掉了,而不是被添加到文本字段中,我如何防止这种情况

下面是完整的自包含示例

import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

public class PanelTableEditorTest extends JFrame {

    private JTable table;

    public PanelTableEditorTest() {
        this.setLayout(new BorderLayout());
        table = new JTable(10, 10);
        table.getSelectionModel().setSelectionMode(
            ListSelectionModel.SINGLE_SELECTION);
        table.setCellSelectionEnabled(true);
        table.setDefaultEditor(Object.class, new SimpleMultiRowCellEditor());
        table.setSurrendersFocusOnKeystroke(true);
        table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
            .put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F2, 0),
            "none");
        table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
            .put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ENTER, 0),
            "startEditing");
        this.add(table.getTableHeader(), BorderLayout.NORTH);
        this.add(table, BorderLayout.CENTER);
        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            public void run() {
                new PanelTableEditorTest();
            }
        });
    }

    public class SimpleMultiRowCellEditor extends DefaultCellEditor {

        final JPanel panel;
        private final JButton rowCount;

        public SimpleMultiRowCellEditor() {
            super(new JTextField());
            this.setClickCountToStart(1);

            rowCount = new JButton();
            rowCount.setVisible(true);
            panel = new JPanel();
            panel.setOpaque(false);
            panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
            panel.add(rowCount);
            panel.add(editorComponent);
            panel.addFocusListener(new PanelFocusListener());
        }

        public Component getTableCellEditorComponent(
            final JTable table,final Object val, final boolean isSelected,
            final int row, final int column) {
            rowCount.setText("1");
            delegate.setValue(val);
            editorComponent.requestFocusInWindow();
            return panel;
        }

        class PanelFocusListener implements FocusListener {

            public void focusGained(FocusEvent e) {
                editorComponent.requestFocusInWindow();
            }

            public void focusLost(FocusEvent e) {
            }
        }
    }
}
添加

rowCount.setFocusable(false)


在SimpleMultiRowCellEditor构造函数中,为了防止按钮检索焦点,因此JTextfield是唯一可以在cell edition上获得焦点的方法。因此,感谢本文,我找到了一个解决方案,并对这一点进行了一些有用的讨论,以及如何将其应用于其他组件

我不完全了解解决方案这整个地区似乎是个雷区

我还添加了这个解决方案,这样当您开始使用键盘编辑字段时,现有值将被替换,而不是双击字段时

我的一个困惑是,我并没有像预期的那样接收到一个关键事件,而是空的,所以我必须对此做出解释

我不再使用setUrrenderKeyStrokes(true),因为这会导致其他编辑器出现问题,例如直接的textfieldeditor

import javax.swing.*;
import javax.swing.text.Caret;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.EventObject;

public class PanelTableEditorTest extends JFrame
{

    private JTable table;

    public PanelTableEditorTest()
    {
        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch(Exception e)
        {

        }
        this.setLayout(new BorderLayout());
        table = new JTable(4, 4);
        table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.setCellSelectionEnabled(true);
        table.setSurrendersFocusOnKeystroke(false);
        table.setDefaultEditor(Object.class,new SimpleMultiRowCellEditor());
        table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(java.awt.event.
                        KeyEvent.VK_F2, 0), "none");
        table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(java.awt.event.
                        KeyEvent.VK_ENTER, 0), "startEditing");

        this.add(table.getTableHeader(), BorderLayout.NORTH);

        this.add(table, BorderLayout.CENTER);
        pack();
        setVisible(true);
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                new PanelTableEditorTest();

            }
        });
    }

    public class SimpleMultiRowCellEditor extends DefaultCellEditor
    {
        private EventObject event;
        final JPanel panel;
        private final JButton rowCount;

        public SimpleMultiRowCellEditor()
        {
            super(new JTextField());
            this.setClickCountToStart(1);

            rowCount = new JButton();
            rowCount.setVisible(true);
            panel = new TableEditorPanel();
            panel.setRequestFocusEnabled(true);
            panel.setOpaque(false);
            panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
            panel.add(rowCount);
            panel.add(editorComponent);
        }

        public boolean isCellEditable(EventObject anEvent)
        {
            event=anEvent;
            return super.isCellEditable(anEvent);
        }

        public Component getTableCellEditorComponent(final JTable table, final Object val, final boolean isSelected, final int row, final int column)
        {
            rowCount.setText("1");
            delegate.setValue(val);
            if(event instanceof KeyEvent || event==null)
            {
                final Caret caret = ((JTextField)editorComponent).getCaret();
                caret.setDot(0);
                ((JTextField)editorComponent).setText("");                
            }
            return panel;
        }

        class TableEditorPanel extends JPanel
        {

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

            protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed){
                InputMap map = editorComponent.getInputMap(condition);
                ActionMap am = editorComponent.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, editorComponent,
                                e.getModifiers());
                    }
                }
                return false;
            }
        }
    }
}

重新格式化的代码;如果不正确,请还原。为什么我的java导入在堆栈溢出中格式不正确?请重新格式化代码。你不需要html标签;只需缩进四个空格,如问题所示。还有一个“代码格式”按钮。是的,我以前用过这个按钮,但它对我不起作用,只是重试了一下,然后就停止了wrong@user294896:只需选择代码并单击二进制图标;换行由你决定。顺便说一句,如果没有@username,我不会看到对你自己答案的评论。@trashgod也许问题是我用另一种方式做的,我单击了二进制图标,然后粘贴了代码