Reputation: 51
I would like to have a jtable with 4 columns. One column must be a combobox. Other columns are strings.
When i click one time on a cell, i would like the cell become editable with blinking caret/cursor.Also, if i click on the combobox i would like the combox set popup visble.
I have read and tested tutorial "How to Use Tables", and if i make just one click on combobox in the cell, it opens. My first problem is that i don't understand why the code in the tutorial works when we implement abstract table model and not working DefaultTableModel.
My code is :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
public class JtabletestOK {
public static void main(String[] args) {
JtabletestOK test = new JtabletestOK();
test.go();
}
public void go() {
//create the frame
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//create a table and add it to a scroll pane in a new tab
JTable jTable1 = new JTable()
{
// Place cell in edit mode when it 'gains focus'
public void changeSelection(
int row, int column, boolean toggle, boolean extend)
{
super.changeSelection(row, column, toggle, extend);
if (editCellAt(row, column))
{
Component editor = getEditorComponent();
editor.requestFocusInWindow();
// System.out.println("ffin focus gagne");
if (editor instanceof JTextField) {
JTextField jf = (JTextField) editor;
jf.select(0, jf.toString().length());
}}
}
};
jTable1.setPreferredScrollableViewportSize(new Dimension(800,100));
jTable1.setFillsViewportHeight(true);
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(jTable1);
Object columnNames[] = { "DataCombo", "Data 2", "Data 3", "Data 4" };
DefaultTableModel model = new DefaultTableModel(columnNames, 0);
Object rowData[] = { "", "Row1-Column2", "Row1-Column3", "Row1-Column3" };
model.addRow(rowData);
jTable1.setModel(model);
String[] comboBoxArray = {"proem1","veitem2","atem3"};
JComboBox jcb = new JComboBox(comboBoxArray);
jcb.setEditable(true);
TableColumn colCombo = jTable1.getColumnModel().getColumn(0);
colCombo.setCellEditor(new DefaultCellEditor(jcb));
jcb.setEditable(true);
frame.getContentPane().add(scrollPane);
frame.pack();
frame.setVisible(true);
}
The source with abstract model is here : http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableRenderDemoProject/src/components/TableRenderDemo.java
Just find the problem : When commenting the statement jcb.setEditable(true); , if i do a single click on the comboxcell it opens the cell. But i don't know why it works better. Also, i would like the combox editable.
How i can have the same behavior for others cells.
Hello again, i have updated the code in order to have - cells become editable if i click one time on the cell by overriding the method - combobox become editable if i click one time on the cell by overriding the method
I put my new code here, it may help other :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.AbstractAction;
import javax.swing.AbstractCellEditor;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.InputMap;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.text.JTextComponent;
public class JtabletestOK {
public static void main(String[] args) {
JtabletestOK test = new JtabletestOK();
test.go();
}
public void go() {
//create the frame
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//create a table and add it to a scroll pane in a new tab
JTable jTable1 = new JTable()
{
// Place cell in edit mode when it 'gains focus'
public void changeSelection(
int row, int column, boolean toggle, boolean extend)
{
super.changeSelection(row, column, toggle, extend);
if (column > 0)
{
if (editCellAt(row, column))
{
Component editor = getEditorComponent();
editor.requestFocusInWindow();
// System.out.println("ffin focus gagne");
if (editor instanceof JTextField) {
JTextField jf = (JTextField) editor;
jf.select(0, jf.toString().length());
}}
}
}
};
jTable1.setPreferredScrollableViewportSize(new Dimension(800,100));
jTable1.setFillsViewportHeight(true);
replaceTabByEnter(jTable1);
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(jTable1);
Object columnNames[] = { "DataCombo", "Data 2", "Data 3", "Data 4" };
DefaultTableModel model = new DefaultTableModel(columnNames, 0);
Object rowData[] = { "", "Row1-Column2", "Row1-Column3", "Row1-Column3" };
model.addRow(rowData);
jTable1.setModel(model);
String[] comboBoxArray = {"proem1","veitem2","atem3"};
JComboBox jca = new JComboBox(comboBoxArray);
jca.setSelectedItem("");
JTextComponent editor = (JTextComponent) jca.getEditor().getEditorComponent();
jca.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
JComponent ja = (JComponent) e.getSource();
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
JComponent ja = (JComponent) e.getSource();
JTable jtb = (JTable) ja.getParent();
jtb.changeSelection(0,1,false,false);
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
});
editor.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("Not mouseClicked yet.");
}
@Override
public void mousePressed(MouseEvent e) {
System.out.println("Not mousePressed yet.");
}
@Override
public void mouseReleased(MouseEvent e) {
JComponent ja = (JComponent) e.getSource();
JComponent jcbloc = (JComponent) ja.getParent();
JComboBox jcb = (JComboBox) jcbloc;
jcb.setPopupVisible(true);
System.out.println("Not mouseReleased yet.");
}
@Override
public void mouseEntered(MouseEvent e) {
System.out.println("Not mouseEntered yet.");
}
@Override
public void mouseExited(MouseEvent e) {
System.out.println("Not mouseExited yet.");
}
});
autocompletecombo jcb =new autocompletecombo(jca);
TableColumn colCombo = jTable1.getColumnModel().getColumn(0);
jca.setEditable(true);
comboboxEditor cbe = new comboboxEditor(jca);
colCombo.setCellEditor(cbe);
frame.getContentPane().add(scrollPane);
frame.pack();
frame.setVisible(true);
}
public void replaceTabByEnter(JTable jtane) {
KeyStroke tab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
InputMap im = jtane.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
im.put(enter, im.get(tab));
}
class comboboxEditor extends AbstractCellEditor implements TableCellEditor{
JComboBox comboBox;
JTextField jtf;
S11InitialSelection sjcb;
@Override
public Object getCellEditorValue() {
return comboBox.getSelectedItem();
}
public comboboxEditor(JComboBox jcb) {
comboBox = jcb;
jtf.selectAll();
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
comboBox.setSelectedItem(value);
return comboBox;
}
public boolean stopCellEditing() {
fireEditingStopped();
// jt.EditNextCell();
return true;
}
}
}
I have find a solution for that :
public void mouseReleased(MouseEvent e) {
JComponent ja = (JComponent) e.getSource();
JComponent jcbloc = (JComponent) ja.getParent();
JComboBox jcb = (JComboBox) jcbloc;
jcb.setPopupVisible(true);
JTextComponent editor = (JTextComponent) jcb.getEditor().getEditorComponent();
editor.setSelectionStart(0);
editor.setSelectionEnd(editor.getText().length());
System.out.println("Not mouseReleased yet.");
}
Thanks for your help.
Upvotes: 3
Views: 3786
Reputation: 51
I have finally find how to solve all my problems. I post all the code. I hope it will help others. If you find better way to adress the problem, i'm open.
It remains two strange thing but it work as i want, so if somenone as an idea :
If i move the code
if(e.getKeyChar() == KeyEvent.VK_ENTER){
JComponent ja = (JComponent) e.getSource();
JComboBox jcbloc = (JComboBox) ja.getParent();
JTable jtb = (JTable) jcbloc.getParent();
jtb.changeSelection(0,1,false,false);
}
in keyReleased instead of keyPressed, it doesn't work.
All the code here :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.AbstractAction;
import javax.swing.AbstractCellEditor;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.InputMap;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.plaf.basic.BasicTextUI;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.text.JTextComponent;
public class JtabletestOKStackOver {
public static void main(String[] args) {
JtabletestOKStackOver test = new JtabletestOKStackOver();
test.go();
}
public void go() {
//create the frame
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//create a table and add it to a scroll pane in a new tab
JTable jTable1 = new JTable()
{
// Place cell in edit mode when it 'gains focus'
public void changeSelection(
int row, int column, boolean toggle, boolean extend)
{
super.changeSelection(row, column, toggle, extend);
if (column > -1)
{
if (editCellAt(row, column))
{
Component editor = getEditorComponent();
editor.requestFocusInWindow();
if (editor instanceof JTextField) {
JTextField jf = (JTextField) editor;
jf.select(0, jf.toString().length());
}
if (editor instanceof JComboBox) {
JComboBox jcb = (JComboBox) editor;
jcb.setPopupVisible(true);
JTextComponent editorCombo = (JTextComponent) jcb.getEditor().getEditorComponent();
editorCombo.setSelectionStart(0);
editorCombo.setSelectionEnd(editorCombo.getText().length());
}
}
}
}
};
jTable1.setPreferredScrollableViewportSize(new Dimension(800,100));
jTable1.setFillsViewportHeight(true);
jTable1.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(jTable1);
Object columnNames[] = { "DataCombo", "Data 2", "Data 3", "Data 4" };
DefaultTableModel model = new DefaultTableModel(columnNames, 0);
Object rowData[] = { "", "Row1-Column2", "Row1-Column3", "Row1-Column3" };
model.addRow(rowData);
jTable1.setModel(model);
String[] comboBoxArray = {"proem1","veitem2","atem3"};
JComboBox jca = new JComboBox(comboBoxArray);
jca.setSelectedItem("");
JTextComponent editor = (JTextComponent) jca.getEditor().getEditorComponent();
editor.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyChar() == KeyEvent.VK_ENTER){
JComponent ja = (JComponent) e.getSource();
JComboBox jcbloc = (JComboBox) ja.getParent();
JTable jtb = (JTable) jcbloc.getParent();
jtb.changeSelection(0,1,false,false);
}
}
@Override
public void keyReleased(KeyEvent e) {
}
});
editor.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
JComponent ja = (JComponent) e.getSource();
JComponent jcbloc = (JComponent) ja.getParent();
JComboBox jcb = (JComboBox) jcbloc;
jcb.setPopupVisible(true);
JTextComponent editor = (JTextComponent) jcb.getEditor().getEditorComponent();
editor.setSelectionStart(0);
editor.setSelectionEnd(editor.getText().length());
}
@Override
public void focusLost(FocusEvent e) {
}
});
TableColumn colCombo = jTable1.getColumnModel().getColumn(0);
jca.setEditable(true);
comboboxEditor cbe = new comboboxEditor(jca);
colCombo.setCellEditor(cbe);
TableColumn colAutre = jTable1.getColumnModel().getColumn(1);
TableColumn colAutre2 = jTable1.getColumnModel().getColumn(2);
TableColumn colAutre3 = jTable1.getColumnModel().getColumn(3);
textCellEditor dce = new textCellEditor(new JTextField());
colAutre.setCellEditor(dce);
colAutre2.setCellEditor(dce);
colAutre3.setCellEditor(dce);
frame.getContentPane().add(scrollPane);
frame.pack();
frame.setVisible(true);
}
class comboboxEditor extends AbstractCellEditor implements TableCellEditor{
JComboBox comboBox;
public comboboxEditor(JComboBox jcb) {
comboBox = jcb;
}
public Object getCellEditorValue() {
return comboBox.getSelectedItem();
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
comboBox.setSelectedItem(value);
return comboBox;
}
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
}
class textCellEditor extends AbstractCellEditor implements TableCellEditor{
JTextField jtextfield;
public textCellEditor(JTextField jtf) {
jtextfield = jtf;
}
public Object getCellEditorValue() {
return jtextfield.getText();
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
if (isSelected) {
// cell (and perhaps other cells) are selected
}
if (value== null)
{
value="";
}
value = value.toString();
if (value instanceof Integer) {
value = value.toString();
}
jtextfield.setText((String) value);
// Return the configured component
return jtextfield;
}
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
}
}
Thanks for your help.
Upvotes: 2
Reputation: 324118
Don't use an ActionListener on the combo box. The "popup" will be displayed by the editor when you click on the cell.
My first problem is that i don't understand why the code in the tutorial works when we implement abstract table model and not working DefaultTableModel.
Editing is controlled by the isCellEditable(...)
method of the TableModel. When you click on a cell that is editable the JTable will use the appropriate editor. If the editor is a combo box, then the popup will be displayed when the cell is clicked.
Just find the problem : When commenting the statement jcb.setEditable(true); , if i do a single click on the comboxcell it opens the cell. But i don't know why it works better
When you click on a cell I believe the MouseEvent is forwarded to the editor (ie the combo box). Since the combo box is editable the MouseEvent goes to the text field, so focus remains of the text field and the popup is not displayed. Try this with a normal combo box, not displayed in a JTable so see the same behaviour.
Upvotes: 0
Reputation: 11327
I don't know why your code with AbstractTableModel works (because I cannot see it). But I can help you to make your example working.
jcb.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
System.out.println("test");
final JComboBox j= (JComboBox)evt.getSource();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (j.isDisplayable()) j.setPopupVisible(true);
}
});
}});
Upvotes: -1