I've created a custom combo box that displays possible changes in state for orders. I did it with the help of this post, using MadProgrammer's code as base line:
Changing Dropdown content in a JTable Column in Swing
It worked, partially.
Even though after clicking the combo box is activated and it shows the proper state options for the user, it has the following problem.
After the user selects the option, the combo box doesn't set the selected value in the table. However if the user changes the combo box of another order, the change does take place. It also works if you click other part of the selected row that isn't the combo box cell.
I suspect that this is because the cell only changes to be a combo box when is clicked, so it doesn't behave like a combo box does. Yet I'm a bit lost in how to fix it.
Any help is greatly appreciated.
Here are the relevant parts of my code:
EDIT: Following Andrew Thompson's advice, i replaced the code with a reproducible example. I'll be working on MadProgrammer's suggested solution and update it later.
package test;
import java.awt.Component;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
public class TestCellEditor {
public static void main(String[] args) {
new TestCellEditor();
}
public TestCellEditor() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
List<String> values = new ArrayList<>(5);
values.add("B");
values.add("A");
values.add("O");
values.add("G");
values.add("P");
ComboBoxTableCellEditor editor = new ComboBoxTableCellEditor(values);
DefaultTableModel model = new DefaultTableModel(new Object[]{"Status"}, 5);
JTable table = new JTable(model);
table.getColumnModel().getColumn(0).setCellEditor(editor);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(table));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ComboBoxTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private JComboBox editor;
private List<String> masterValues;
public ComboBoxTableCellEditor(List<String> masterValues) {
this.editor = new JComboBox();
this.masterValues = masterValues;
}
#Override
public Object getCellEditorValue() {
return editor.getSelectedItem();
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
DefaultComboBoxModel model = new DefaultComboBoxModel(masterValues.toArray(new String[masterValues.size()]));
for (int index = 0; index < table.getRowCount(); index++) {
}
editor.setModel(model);
editor.setSelectedItem(value);
return editor;
}
}
}
This approach will only override the getTableCellEditorComponent(...) method of the DefaultCellEditor to reset the model of the combo box based on a value in the current row that is being edited.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class StateCellEditor extends DefaultCellEditor
{
private int lookupColumn;
private HashMap<Object, DefaultComboBoxModel<?>> map;
public StateCellEditor(JComboBox<?> comboBox, int lookColumn, HashMap<Object, DefaultComboBoxModel<?>> map)
{
super(comboBox);
this.lookupColumn = lookupColumn;
this.map = map;
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
Component c = super.getTableCellEditorComponent(table, value, isSelected, row, column);
JComboBox<?> comboBox = (JComboBox<?>)c;
Object lookup = table.getModel().getValueAt(row, lookupColumn);
DefaultComboBoxModel model = map.get( lookup );
comboBox.setModel( model );
return comboBox;
}
private static void createAndShowUI()
{
HashMap<Object, DefaultComboBoxModel<?>> map = new HashMap<>();
map.put("Color", new DefaultComboBoxModel<Object>( new String[]{ "Red", "Blue", "Green" } ));
map.put("Shape", new DefaultComboBoxModel<Object>( new String[]{ "Circle", "Square", "Triangle" } ));
map.put("Fruit", new DefaultComboBoxModel<Object>( new String[]{ "Apple", "Orange", "Banana" } ));
JPanel panel = new JPanel( new BorderLayout() );
panel.setLayout( new BorderLayout() );
// Create the table with default data
Object[][] data =
{
{"Color", "Red"},
{"Shape", "Square"},
{"Fruit", "Banana"}
};
String[] columnNames = {"Type","Value"};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
JTable table = new JTable(model);
DefaultCellEditor dce = new StateCellEditor(new JComboBox<Object>(), 0, map);
table.getColumnModel().getColumn(1).setCellEditor(dce);
JScrollPane scrollPane = new JScrollPane( table );
panel.add( scrollPane );
JFrame frame = new JFrame("Table Combo Box by Row");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel, BorderLayout.CENTER);
frame.setSize(200, 200);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Following the suggestion of #camickr i managed to implement an easier solution.
I put this on the method that populates the table:
table.getColumnModel().getColumn(5).setCellEditor(getCellEditor(status));
public List<TableCellEditor> TableComboBoxByRow(){
// Create the editors to be used for each row
List<TableCellEditor> editors = new ArrayList<TableCellEditor>(3);
String[] items1 = { "I", "C", "F" };
JComboBox comboBox1 = new JComboBox( items1 );
DefaultCellEditor dce1 = new DefaultCellEditor( comboBox1 );
editors.add( dce1 );
String[] items2 = { "E" };
JComboBox comboBox2 = new JComboBox( items2 );
DefaultCellEditor dce2 = new DefaultCellEditor( comboBox2 );
editors.add( dce2 );
String[] items3 = { "ET" };
JComboBox comboBox3 = new JComboBox( items3 );
DefaultCellEditor dce3 = new DefaultCellEditor( comboBox3 );
editors.add( dce3 );
String[] items4 = { "F" };
JComboBox comboBox4 = new JComboBox( items4 );
DefaultCellEditor dce4 = new DefaultCellEditor( comboBox4 );
editors.add( dce4 );
return editors;
}
public TableCellEditor getCellEditor(String status)
{
if(estado.equals("I") || estado.equals("C")){
return TableComboBoxByRow().get(0);
}
else if(estado.equals("E"))
{
return TableComboBoxByRow().get(1);}
else if(estado.equals("ET"))
{
return TableComboBoxByRow().get(2);
}else{
return TableComboBoxByRow().get(3);
}
}
Thank you so much!
Related
I have made a combobox as cell editor of a column. I want when i create a new row the cell in that column should not have the combobox as the cell editor and should retain JTextField as the cell editor. Here is what i have done so far.
addRow(mainWindow.salesTable);
final TableColumn items = mainWindow.salesTable.getColumnModel().getColumn(0);
final JTextField tfield = new JTextField();
DefaultCellEditor editorqty = new DefaultCellEditor(tfield);
items.setCellEditor(editorqty);
private static void addRow(JTable table) {
DefaultTableModel model = (DefaultTableModel) table.getModel();
Vector row = new Vector();
row.add("");
row.add("");
row.add("");
row.add("");
row.add("");
row.add("");
row.add("");
row.add("");
model.addRow(row);
}
Overriding the getCellEditor(...) method of JTble is one approach:
import java.awt.*;
import java.util.List;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class TableComboBoxByRow extends JPanel
{
List<String[]> editorData = new ArrayList<String[]>(3);
public TableComboBoxByRow()
{
setLayout( new BorderLayout() );
// Create the editorData to be used for each row
editorData.add( new String[]{ "Red", "Blue", "Green" } );
editorData.add( new String[]{ "Circle", "Square", "Triangle" } );
editorData.add( new String[]{ "Apple", "Orange", "Banana" } );
// Create the table with default data
Object[][] data =
{
{"Color", "Red"},
{"Shape", "Square"},
{"Fruit", "Banana"},
{"Plain", "Text"}
};
String[] columnNames = {"Type","Value"};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
JTable table = new JTable(model)
{
// Determine editor to be used by row
public TableCellEditor getCellEditor(int row, int column)
{
int modelColumn = convertColumnIndexToModel( column );
if (modelColumn == 1 && row < 3)
{
JComboBox<String> comboBox1 = new JComboBox<String>( editorData.get(row));
return new DefaultCellEditor( comboBox1 );
}
else
return super.getCellEditor(row, column);
}
};
JScrollPane scrollPane = new JScrollPane( table );
add( scrollPane );
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("Table Combo Box by Row");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new TableComboBoxByRow() );
frame.setSize(200, 200);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
for Java Kepler Eclipse and Jtable, I am trying to make it so as when a specific table cell is selected, that cell will work as an editorPane; or have the whole column work as editorPane. When I click a cell on column COMMENTS it enlargens the row but I cant get it to work as an editorPane. My project is actualy very different but I wrote this mini one with the table so you can copy, paste and run it to see exactly what the problem is when you click on a COMMENTS cell.
I tried to make the column an editorPane to begin with like I made the column DONE with checkBox, but it doesnt work or I am doing it wrong. I also tried cellRenderer but I couldnt make that work either.
Whether the whole column works as an editorPane or just the selected cell it doesnt matter, whatever is easier and as long as it works
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
public class JavaTestOne {
JFrame frmApp;
private JTable table;
private JCheckBox checkbox;
DefaultTableModel model;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JavaTestOne window = new JavaTestOne();
window.frmApp.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public JavaTestOne() {
initialize();
}
private void initialize() {
frmApp = new JFrame();
frmApp.getContentPane().setFont(new Font("Tahoma", Font.PLAIN, 13));
frmApp.setBounds(50, 10, 1050, 650);
frmApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmApp.getContentPane().setLayout(new CardLayout(0, 0));
frmApp.setTitle("App");
{
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(0, 42, 984, 484);
frmApp.add(scrollPane);
{
table = new JTable();
table.setFillsViewportHeight(true);
Object[][] data = {
{"I01", "Tom",new Boolean(false), ""},
{"I02", "Jerry",new Boolean(false), ""},
{"I03", "Ann",new Boolean(false), ""}};
String[] cols = {"ID","NAME","DONE","COMMENTS"};
model = new DefaultTableModel(data, cols) {
private static final long serialVersionUID = -7158928637468625935L;
public Class getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
table.setModel(model);
table.setRowHeight(20);
table.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
int row = table.rowAtPoint(evt.getPoint());
int col = table.columnAtPoint(evt.getPoint());
table.setRowHeight(20);
if(col==3){
table.setRowHeight(row, 100);
//this is where I need it to work as an editorPane if it is only for the selected cell
}
}
});
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
scrollPane.setViewportView(table);
checkbox = new JCheckBox("OK");
checkbox.setHorizontalAlignment(SwingConstants.CENTER);
checkbox.setBounds(360, 63, 97, 23);
}
}
}
}
Another alternative is to display a popup window to edit the cell:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
/*
* The editor button that brings up the dialog.
*/
//public class TablePopupEditor extends AbstractCellEditor
public class TablePopupEditor extends DefaultCellEditor
implements TableCellEditor
{
private PopupDialog popup;
private String currentText = "";
private JButton editorComponent;
public TablePopupEditor()
{
super(new JTextField());
setClickCountToStart(1);
// Use a JButton as the editor component
editorComponent = new JButton();
editorComponent.setBackground(Color.white);
editorComponent.setBorderPainted(false);
editorComponent.setContentAreaFilled( false );
// Make sure focus goes back to the table when the dialog is closed
editorComponent.setFocusable( false );
// Set up the dialog where we do the actual editing
popup = new PopupDialog();
}
public Object getCellEditorValue()
{
return currentText;
}
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
popup.setText( currentText );
// popup.setLocationRelativeTo( editorComponent );
Point p = editorComponent.getLocationOnScreen();
popup.setLocation(p.x, p.y + editorComponent.getSize().height);
popup.show();
fireEditingStopped();
}
});
currentText = value.toString();
editorComponent.setText( currentText );
return editorComponent;
}
/*
* Simple dialog containing the actual editing component
*/
class PopupDialog extends JDialog implements ActionListener
{
private JTextArea textArea;
public PopupDialog()
{
super((Frame)null, "Change Description", true);
textArea = new JTextArea(5, 20);
textArea.setLineWrap( true );
textArea.setWrapStyleWord( true );
KeyStroke keyStroke = KeyStroke.getKeyStroke("ENTER");
textArea.getInputMap().put(keyStroke, "none");
JScrollPane scrollPane = new JScrollPane( textArea );
getContentPane().add( scrollPane );
JButton cancel = new JButton("Cancel");
cancel.addActionListener( this );
JButton ok = new JButton("Ok");
ok.setPreferredSize( cancel.getPreferredSize() );
ok.addActionListener( this );
JPanel buttons = new JPanel();
buttons.add( ok );
buttons.add( cancel );
getContentPane().add(buttons, BorderLayout.SOUTH);
pack();
getRootPane().setDefaultButton( ok );
}
public void setText(String text)
{
textArea.setText( text );
}
/*
* Save the changed text before hiding the popup
*/
public void actionPerformed(ActionEvent e)
{
if ("Ok".equals( e.getActionCommand() ) )
{
currentText = textArea.getText();
}
textArea.requestFocusInWindow();
setVisible( false );
}
}
private static void createAndShowUI()
{
String[] columnNames = {"Item", "Description"};
Object[][] data =
{
{"Item 1", "Description of Item 1"},
{"Item 2", "Description of Item 2"},
{"Item 3", "Description of Item 3"}
};
JTable table = new JTable(data, columnNames);
table.getColumnModel().getColumn(1).setPreferredWidth(300);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
// Use the popup editor on the second column
TablePopupEditor popupEditor = new TablePopupEditor();
table.getColumnModel().getColumn(1).setCellEditor( popupEditor );
JFrame frame = new JFrame("Popup Editor Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JTextField(), BorderLayout.NORTH);
frame.add( scrollPane );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Using this approach you don't continually manipulate the row size. You could even customize the code to make the dialog fit the width of the cell and appear below the cell.
Seems you need to implement your own TableCellEditor, read more in tutorial.
For example like that:
private class CustomEditor extends AbstractCellEditor implements TableCellEditor{
private JTextPane pane = new JTextPane();
private JScrollPane scroll = new JScrollPane(pane);
private int row = -1;
#Override
public Object getCellEditorValue() {
return pane.getText();
}
#Override
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
if(this.row != -1)
table.setRowHeight(this.row, 20);
this.row = row;
table.setRowHeight(row, 100);
pane.setText(value == null ? "" : value.toString());
return scroll;
}
}
and then set it as column editor: table.getColumn("COMMENTS").setCellEditor(new CustomEditor());
I get an error when I remove a row a sorted row in a JTable.
The error appears only when the table is sorted, and I know where the error source is:
the method updateRowHeights() in the tableChanged causes an Exception java.lang.ArrayIndexOutOfBoundsException.
I guess that the line int rowHeight = table.getRowHeight(); causes the problem,
but I don't know why.
Here is my code:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;
public class TableExample {
String [] title = new String [] {"Title A", "Title B"};
Object [][] data = new String [][] {{"aaaaaaaaaaaa aaaaaa aaaaaaa", "bbbbbbbb bbbb bbbbbb bbbbbb"},
{"cccccccccc cccccccc ccccccc", "ddddddd ddd dddddddd dddddd"},
{"eeeeeeeeee eeeeeeee eeeeeee", "fffffff ffff ffffff fffffff"}};
private JTable table;
private JFrame frame;
private DefaultTableModel model;
private JScrollPane pane1;
TableExample() {} //constructor
public JPanel createTable() {
JPanel panel = new JPanel();
//creating tables and table models
model = new DefaultTableModel(data, title);
table = new JTable(model);
table.getModel().addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent e) {
updateRowHeights();
}
});
//enable table sorting
table.setAutoCreateRowSorter(true);
pane1 = new JScrollPane(table);
pane1.setPreferredSize(new Dimension(300,300));
updateRowHeights();
panel.add(pane1);
//delete a row after del keystroke
keyBindings();
return panel;
}
void showTable() {
//create and show frame
JPanel testPanel = createTable();
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(testPanel);
frame.pack();
frame.setVisible(true);
}//showTable
void updateRowHeights() {
for (int row = 0; row < table.getRowCount(); row++) {
int rowHeight = table.getRowHeight();
Component comp = table.prepareRenderer(table.getCellRenderer(row, 1), row, 1);
rowHeight = Math.max(rowHeight, comp.getPreferredSize().height);
table.setRowHeight(row, rowHeight);
}
}
void keyBindings() {
int condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
InputMap inputMap = table.getInputMap(condition);
ActionMap actionMap = table.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete");
actionMap.put("delete", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
int row = table.getSelectedRow();
model.removeRow(row);
}
});
}
public static void main(String[] args) {
TableExample example = new TableExample();
example.showTable();
}//main
}//TableExample
How can I solve this problem?
As noted here, "When using a sorter, always remember to translate cell coordinates." In your delete action, for example,
row = table.convertRowIndexToModel(row);
A similar problem afflicts updateRowHeights(), although I did not pursue this.
Also consider overriding getPreferredScrollableViewportSize(), instead of calling setPreferredSize(); more details here.
As tested:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;
public class TableExample {
String[] title = new String[]{"Title A", "Title B"};
Object[][] data = new String[][]{
{"aaaaaaaaaaaa aaaaaa aaaaaaa", "bbbbbbbb bbbb bbbbbb bbbbbb"},
{"cccccccccc cccccccc ccccccc", "ddddddd ddd dddddddd dddddd"},
{"eeeeeeeeee eeeeeeee eeeeeee", "fffffff ffff ffffff fffffff"}};
private JTable table;
private JFrame frame;
private DefaultTableModel model;
private JScrollPane pane1;
public JPanel createTable() {
JPanel panel = new JPanel();
//creating tables and table models
model = new DefaultTableModel(data, title);
table = new JTable(model);
//enable table sorting
table.setAutoCreateRowSorter(true);
pane1 = new JScrollPane(table);
panel.add(pane1);
//delete a row after del keystroke
keyBindings();
return panel;
}
void showTable() {
//create and show frame
JPanel testPanel = createTable();
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(testPanel);
frame.pack();
frame.setVisible(true);
}//showTable
void keyBindings() {
int condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
InputMap inputMap = table.getInputMap(condition);
ActionMap actionMap = table.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete");
actionMap.put("delete", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
int row = table.getSelectedRow();
row = table.convertRowIndexToModel(row);
model.removeRow(row);
}
});
}
public static void main(String[] args) {
TableExample example = new TableExample();
example.showTable();
}//main
}//TableExample
I have written this simple program:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class JcomboboxJtableDemo extends JPanel
implements ActionListener {
private DefaultTableModel tableModel;
JTable table = new JTable (tableModel);
private JScrollPane scrollpaneTable = new JScrollPane( table );
private JPanel PaneBottoniTabella = new JPanel( );
public JcomboboxJtableDemo() {
super(new BorderLayout());
String[] petStrings = { "Bird", "Cat", "Dog", "Rabbit", "Pig" };
JComboBox comboBox = new JComboBox(petStrings);
comboBox.setSelectedIndex(4);
tableModel = CreateTableModel();
tableModel.insertRow( 0, new Object[] {"Header col1", ""} );
tableModel.insertRow( 0, new Object[] {petStrings[0], ""} );
tableModel.insertRow( 0, new Object[] {petStrings[1], ""} );
tableModel.insertRow( 0, new Object[] {petStrings[2], ""} );
tableModel.insertRow( 0, new Object[] {petStrings[3], ""} );
tableModel.setValueAt("Header col2", 0, 1);
DefaultCellEditor editor = new DefaultCellEditor(comboBox);
table.getColumnModel().getColumn(0).setCellEditor(editor);
table.getColumnModel().getColumn(1).setCellEditor(editor);
//Lay out the demo.
add(comboBox, BorderLayout.PAGE_START);
add(table, BorderLayout.PAGE_END);
setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
}
private final DefaultTableModel CreateTableModel () {
DefaultTableModel modello = new DefaultTableModel( new Object[] { "Col1","Col2" }, 0 ) {
#Override
public boolean isCellEditable(int row, int column) {
return true;
}
};
table.setModel(modello);
return modello;
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("ComboBoxDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new JcomboboxJtableDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
I you try to run it you will see that there is a problem in showing correctly the JComboBox components in the second column, in the first column the are correctly shown and you can see each selected item as set in the code, instead in the second column there are some problems: none on the relative cell.
Could you tell me why? How can I solve the problem?
Thanks
You're using the same JComboBox component for both ColumnModel columns which in turn share the same ComboBoxModel. Any change in the selected item from one column will be reflected in the other column. Create a second combobox
JComboBox comboBox2 = new JComboBox(petStrings);
...
table.getColumnModel().getColumn(1).setCellEditor(editor2);
so that any changes can occur independently in either column.
I am trying to add unique JComboBoxes to a column in a JTable. I know it is possible to add a JComboBox to an entire column using
TableColumn col = table.getColumnModel().getColumn(columnNumber);
col.setCellEditor(new MyComboBoxEditor(values));
but I need each JComboBox to be different and have different Strings inside it. Any ideas?
Override the getCellEditor(...) method. For example;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class TableComboBoxByRow extends JFrame
{
List<TableCellEditor> editors = new ArrayList<TableCellEditor>(3);
public TableComboBoxByRow()
{
// Create the editors to be used for each row
String[] items1 = { "Red", "Blue", "Green" };
JComboBox comboBox1 = new JComboBox( items1 );
DefaultCellEditor dce1 = new DefaultCellEditor( comboBox1 );
editors.add( dce1 );
String[] items2 = { "Circle", "Square", "Triangle" };
JComboBox comboBox2 = new JComboBox( items2 );
DefaultCellEditor dce2 = new DefaultCellEditor( comboBox2 );
editors.add( dce2 );
String[] items3 = { "Apple", "Orange", "Banana" };
JComboBox comboBox3 = new JComboBox( items3 );
DefaultCellEditor dce3 = new DefaultCellEditor( comboBox3 );
editors.add( dce3 );
// Create the table with default data
Object[][] data =
{
{"Color", "Red"},
{"Shape", "Square"},
{"Fruit", "Banana"},
{"Plain", "Text"}
};
String[] columnNames = {"Type","Value"};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
JTable table = new JTable(model)
{
// Determine editor to be used by row
public TableCellEditor getCellEditor(int row, int column)
{
int modelColumn = convertColumnIndexToModel( column );
if (modelColumn == 1 && row < 3)
return editors.get(row);
else
return super.getCellEditor(row, column);
}
};
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
}
public static void main(String[] args)
{
TableComboBoxByRow frame = new TableComboBoxByRow();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
}
}
Try this:
...
final Object[] obj = {"test1", "test2", "test3"};
JTable jTable = new JTable();
TableColumn column = jTable.getColumnModel().getColumn(1);
column.setCellEditor(new AutoCompletionComboBoxEditor(obj));
...
public static class AutoCompletionComboBoxEditor extends AbstractCellEditor implements TableCellEditor {
JComboBox cbx;
public AutoCompletionComboBoxEditor(Object[] items) {
cbx = new JComboBox(items);
}
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
return cbx;
}
public Object getCellEditorValue() {
return cbx.getSelectedItem();
}
}
try tell me the effect :)
-Saligh