我这里有一个非常简单的问题。
当用户在我的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。
2)没有过滤器:点击JButton - >预期正确的行为。
现在有问题的行为:
1)过滤:选择行,但尚未单击编辑JButton。
2)过滤:编辑JButton点击 - >没有变化,上面提出异常(不要打扰工具提示)
以下是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
有人建议吗?
对于问题的第二部分,我解决了如下问题:
首先我使用了
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();