在特定JTable单元上设置焦点和闪烁光标

时间:2014-07-09 01:04:27

标签: java swing jtable focus tablecelleditor

我这里有一个非常简单的问题。

当用户在JTable中选择一行后点击“编辑”按钮时,软件会检查是否允许编辑此行。

如果是,我想将焦点放在该行的第一个单元格中,并使用闪烁的光标,以便用户可以直接在单元格中键入内容。

由于isEditable()方法,我可以成功设置行是否可编辑,并使用table.editCellAt(selectedRow, 0)开始编辑。

然而

1)该单元格中没有闪烁的光标

2)用户无法立即输入单元格 (他仍然需要双击单元格)

有关如何实现这一目标的任何建议吗?

//////////////////// UPDATE //////////////////////

尽管MadProgrammer的评论解决了这个问题,但它只解决了部分问题,但那是因为我还不够精确。

的确,当我执行他用“经典JTable”描述的步骤时,即:

table.editCellAt(selectedRow, 0);
table.setSurrendersFocusOnKeystroke(true);
table.getEditorComponent().requestFocus();

我得到闪烁的光标和立即输入的能力。

然而,缺少的部分是我给用户2个选项。

1)他可以直接手动选择表格中的一行,为此解决方案没问题。

2)但我也为用户提供了使用JTextField更容易找到他正在搜索的行的能力。为此,我使用带有regexFilter的TableRowSorter来过滤显示的行。当我在那里尝试MadProgrammer的解决方案(带过滤)时,我得到了一个java.lang.NullPointerException,并且没有进行进一步的编辑。

以下是例外:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at dialogs.DialogEditCouleurs.actionPerformed(DialogEditCouleurs.java:229)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.WaitDispatchSupport$2.run(Unknown Source)
at java.awt.WaitDispatchSupport$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.WaitDispatchSupport.enter(Unknown Source)
at java.awt.Dialog.show(Unknown Source)
at java.awt.Component.show(Unknown Source)
at java.awt.Component.setVisible(Unknown Source)
at java.awt.Window.setVisible(Unknown Source)
at java.awt.Dialog.setVisible(Unknown Source)
at dialogs.DialogEditCouleurs.<init>(DialogEditCouleurs.java:123)
at panels.PanelPropertiesEdit.actionPerformed(PanelPropertiesEdit.java:940)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

以下是导致异常的行:

table.getEditorComponent().requestFocus();

以下是该软件的实际行为:

1)没有过滤器:行已被选中,但尚未点击编辑JButton。

enter image description here

2)没有过滤器:点击了JButton - &gt;预期的正确行为。

enter image description here

现在有问题的行为:

1)过滤:行被选中,但尚未点击编辑JButton。 enter image description here

2)过滤:编辑单击JButton - &gt;没有变化,上面提出异常(不要打扰工具提示)

enter image description here

以下是JDIalog的相关部分:

public class DialogEditColors extends JDialog implements ActionListener, KeyListener
{
final WebNotificationPopup          notificationPopup   = new WebNotificationPopup();
final TableRowSorter<TableModel>    sorter;
private JTable                      tableau  = null;
private EditTableModel              model    = null;
private JPanel                      panelBoutons = null;
private WebTextField                txtFieldSearch  = null;
private JLabel                      lblTitle    = null;
private JButton                     btnAdd  = null, btnDelete = null, btnEdit = null;
private JButton                     btnAnnuler  = null, btnSaveCouleur = null;
private JScrollPane                 scroller    = null;
private ColorDao                    colorDao = new ColorDao(Share.connection);

public DialogEditColors()
    {
        super();
        setSize(439, 313);
        setTitle("  Edition couleurs");
        getContentPane().setLayout(null);
        setModal(true);
        setResizable(false);
        setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);

        btnSaveCouleur = new JButton("Enregistrer");
        btnSaveCouleur.setBounds(317, 247, 89, 26);
        btnSaveCouleur.addActionListener(this);

        btnAnnuler = new JButton("Annuler");
        btnAnnuler.setBounds(214, 247, 89, 26);
        btnAnnuler.addActionListener(this);

        btnAdd = new JButton("");
        btnAdd.setBounds(new Rectangle(10, 8, 33, 26));
        btnAdd.addActionListener(this);

        btnDelete = new JButton("");
        btnDelete.setBounds(new Rectangle(53, 8, 33, 26));
        btnDelete.addActionListener(this);

        btnEdit = new JButton("");
        btnEdit.setBounds(new Rectangle(96, 8, 33, 26));
        btnEdit.addActionListener(this);

        panelBoutons = new JPanel();
        panelBoutons.setBorder(new LineBorder(Color.GRAY));
        panelBoutons.setBounds(27, 11, 378, 43);
        panelBoutons.setLayout(null);

        txtFieldSearch = new WebTextField("", 10);
        txtFieldSearch.setBounds(193, 9, 175, 24);
        panelBoutons.add(txtFieldSearch);
        txtFieldSearch.setTrailingComponent(new WebImage(IconUtil.createIcon("/images/search.png").getImage()));
        txtFieldSearch.addKeyListener(this);

        Object[][] data = new Object[colorDao.findAll().size()][2];
        String[] title = { "Couleur", "Description" };

        int i = 0;
        for (Couleur coul : colorsDao.findAll())
            {
                data[i][0] = coul.getNom();
                data[i][1] = coul.getDescription();
                i++;
            }

        model = new EditTableModel(data, title);
        tableau = new JTable(model)
        {//COLORING THE BACKGROUND IN ALTERNATE COLORS
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
                {
                    Component returnComp = super.prepareRenderer(renderer, row, column);
                    Color alternateColor = new Color(242, 242, 242);
                    Color whiteColor = Color.WHITE;
                    if ( !returnComp.getBackground().equals(getSelectionBackground()) )
                        {
                            Color bg = (row % 2 == 0 ? alternateColor : whiteColor);
                            returnComp.setBackground(bg);
                            bg = null;
                        }
                    return returnComp;
                };
        };

        tableau.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        tableau.setCellSelectionEnabled(true);
        sorter = new TableRowSorter<TableModel>(model);
        tableau.setRowSorter(sorter);
        sorter.addRowSorterListener(tableau);

        scroller = new JScrollPane(tableau);
        scroller.setBounds(27, 65, 378, 171);
        addComponents();
        setVisible(true);
    }//END OF CONSTRUCTOR

private void addComponents()
    {
        getContentPane().add(scroller);
        getContentPane().add(btnSaveCouleur);
        getContentPane().add(btnAnnuler);
        panelBoutons.add(btnAdd);
        panelBoutons.add(btnDelete);
        panelBoutons.add(btnEdit);
        getContentPane().add(panelBoutons);
    }//END OF METHOD

public void actionPerformed(ActionEvent e)
    {
     if ( e.getSource() == btnEdit )
            {
                int selectedRow = 0;
                if ( tableau.getSelectedRowCount() != 0 ) //THERE IS A CHOSEN COLOR IN JTABLE 
                    {
                        String selectedColor = (tableau.getValueAt(tableau.getSelectedRow(), tableau.getSelectedColumn()))
                                .toString();
                        //WE'RE TESTING IF THE COLOR IS READONLY
                        if ( colorDao.findByName(selectedColor).get(0).getReadOnly() == true )
                            {//IF THE COLOR IS READONLY
                                notificationPopup.setIcon(NotificationIcon.error);
                                notificationPopup.setContent("This item is readonly : impossible to edit it !");
                                NotificationManager.showNotification(notificationPopup);
                            }

                        else
                            {////THE COLOR IS NOT READONLY --> EDITING IS ALLOWED
                                //1) NOTIFY THE MODEL THAT EDITING IS ALLOWED
                                model.setEditingValidated(true);
                                //2) TEST WETHER FILTER IS ACTIVE OR NOT TO SEE IF INDEX CONVERSION IS NEEDED 
                                if ( txtFieldSearch.getText() == "" )
                                    {//NO FILTER
                                        selectedRow = tableau.getSelectedRow();
                                    }
                                else
                                    {//FILTER IS ACTIVE
                                        int modelIndex = tableau.convertRowIndexToModel(tableau.getSelectedRow());
                                        selectedRow = modelIndex;
                                    }

                                model.setEditingValidatedRowNb(selectedRow);
                                tableau.editCellAt(selectedRow, 0);
                                tableau.setSurrendersFocusOnKeystroke(true);
                                tableau.getEditorComponent().requestFocus();
                            }
                    }
                else
                    {   //NO CHOSEN COLOR
                        notificationPopup.setIcon(NotificationIcon.error);
                        notificationPopup.setContent("No chosen color !");
                        NotificationManager.showNotification(notificationPopup);
                    }
            }

        else if ( e.getSource() == btnAnnuler )
            {//WE LEAVE THE DIALOG WITHOUT DOING ANYTHING
                Share.chosenColor = null;
                this.dispose();
            }
    }//END OF METHOD

public void keyReleased(KeyEvent e)
    {
        if ( e.getSource() == txtFieldSearch )
            {
                String text = txtFieldSearch.getText();
                if ( text.length() == 0 )
                    {
                        sorter.setRowFilter(null);
                    }
                else
                    {
                        sorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
                    }
                ((AbstractTableModel) tableau.getModel()).fireTableDataChanged();
            }
    }//END OF METHOD
}//END OF CLASS

这是TableModel的相关部分:

public class EditTableModel extends AbstractTableModel implements Serializable
{
protected Vector    dataVector;
protected Vector    columnIdentifiers;
protected boolean   isEditingValidated      = false;
protected int       editingValidatedRowNb   = 0;

public boolean isCellEditable(int row, int column)
    {
        //IF EDITING IS NOT VALIDATED NOTHING IS EDITABLE / RETURN FALSE
        if ( !isEditingValidated ) 
            {
                return false;
            }
        //ELSE A FURTHER TEST IS NEEDED TO DECIDE
        else
            {
                //IF THE CURRENT ROW IS THE ROW FOR WHICH EDITING IS VALIDATED RETURN TRUE
                if ( row == editingValidatedRowNb )
                    {
                        return true;
                    }
                //ELSE THE ROW IS ANOTHER ROW SO RETURN FALSE
                else
                    {
                        return false;
                    }
            }
    }//END OF METHOD
}//END OF CLASS

建议任何人?

1 个答案:

答案 0 :(得分:1)

对于问题的第二部分,我解决了如下问题:

首先我使用了

table.setCellSelectionEnabled(true);

只是为了确保选择JTable中的特定单元格。

然后,我用了

table.changeSelection(int row, int column, false, false);

上面的两个布尔值分别是切换和扩展。 false,false此处将清除先前的选择并确保选中新单元格。

上面的代码片段用于选择表格中的特定单元格。我这样做了,所以当我使用editCellAt()方法时,它肯定会开始编辑当前被选中的单元格。

如果由于任何原因,editCellAt()没有正常工作,那么你将从getEditorComponent()获得null。由于目前没有任何组件正在编辑因为您的案例存在问题。

table.getEditorComponent()

然后开始编辑我使用的单元格

table.editCellAt(int row, int column);

这用于以编程方式开始编辑单元组件。

最后让光标闪烁/聚焦在我使用的特定单元格上

table().getEditorComponent().requestFocus();

希望这会有所帮助。它对我来说就像魅力一样。如果没有,请告诉我。

简而言之,我添加了以下代码行:

table.setCellSelectionEnabled(true);
table.changeSelection(int row, int column, false, false);
table.editCellAt(int row, int column);
table().getEditorComponent().requestFocus();