How to create table with JComboBox in columns [duplicate] - java

I have a JTable with a column containing a JComboBox.
I have an ItemListener attached to the JComboBox which acts upon any changes.
However, ItemListener does not have a method for obtaining the Row that the changed ComboBox is within.
I need to Row number in order to act upon another column in the same row when the ComboBox has a change.
Any help would be appreciated.
This is my Short and Concise code. What I am trying to accomplish, is obtaining the Table Row of the ComboBox when a the itemlistener picks up a change.
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.IOException;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
public class Example extends JFrame {
private static final long serialVersionUID = 1L;
public static int maxX, maxY;
public static final String[] columnHeads = {"Col 1", "Col 2", "Col 3"};
public static void main(String args[]) throws IOException {
Example example = new Example();
}
public Example() {
//Create Table Model
DefaultTableModel model = new DefaultTableModel();
for (int index = 0; index < columnHeads.length; index++) {
model.addColumn(columnHeads[index]);
}
//Create Table
JTable table = new JTable(model);
JScrollPane scrollPane = new JScrollPane(table);
//List for ComboBox
String[] list = {"Item1", "Item2", "Item3"};
//Create ComboBox
JComboBox itemTypes = attachComboBoxRenderer(table, 2, list);
//Attach Item Listener
itemTypes.addItemListener(new ComboBoxListener());
((DefaultTableModel) table.getModel()).insertRow(
table.getRowCount(), new Object[]{"C1", "C2", ""});
this.setTitle("Example");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container = getContentPane();
//MAIN Panel
final JPanel main = new JPanel();
main.setLayout(new GridBagLayout());
main.add(scrollPane);
container.add(main);
this.pack();
this.setVisible(true);
}
public static JComboBox attachComboBoxRenderer(
JTable table, int column, Object[] values) {
JComboBox combo = new JComboBox(values);
TableColumn col = table.getColumnModel().getColumn(column);
col.setCellRenderer(new ComboBoxRenderer(values));
col.setCellEditor(new DefaultCellEditor(combo));
return combo;
}
}
class ComboBoxListener implements ItemListener {
private static final int SELECTED = 1;
#Override
public void itemStateChanged(ItemEvent e) {
// Get the affected item
Object item = e.getItem();
if (item.toString() != null
&& !"".equals(item.toString())
&& e.getStateChange() == SELECTED) {
System.out.println(item.toString() + " selected");
//How do I get Row in the Table of the ComboBox that was changed?
}
}
}
class ComboBoxRenderer extends JComboBox implements TableCellRenderer {
private static final long serialVersionUID = 1L;
public ComboBoxRenderer(Object[] items) {
super(items);
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
// Select the current value
setSelectedItem(value);
return this;
}
}

It sounds like you are Using a Combo Box as an Editor. If so, the TableCellEditor method, getTableCellEditorComponent(), includes the row as a parameter. There's a related example here.
Addendum: To change a value in the same row you've edited, just have the model return the correct value for the "other column" based on the related values in that row. Alternatively, update the related value in your model's setValueAt() method before firing the update, as shown in the example.
Addendum: Based on your example, the code below overrides the model's getValueAt() method to keep the dependent column synchronized with the item column.
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.IOException;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
/** #see http://stackoverflow.com/questions/7350445 */
public class DependentColumn extends JFrame {
private static final int DEPENDENT_COL = 1;
private static final int ITEM_COL = 2;
private static final String[] columnNames = {"Col 1", "Col 2", "Col 3"};
public static void main(String args[]) throws IOException {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
DependentColumn dc = new DependentColumn();
}
});
}
public DependentColumn() {
this.setTitle("Example");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create Model & Table
DefaultTableModel model = new DefaultTableModel(columnNames, 0) {
#Override
public Object getValueAt(int row, int col) {
if (col == DEPENDENT_COL) {
return "C2:" + this.getValueAt(row, ITEM_COL);
} else {
return super.getValueAt(row, col);
}
}
};
for (int i = 0; i < 16; i++) {
model.addRow(new Object[]{"C1", "C2", "Item1"});
}
JTable table = new JTable(model);
table.setPreferredScrollableViewportSize(new Dimension(320, 120));
//Create ComboBox
String[] items = {"Item1", "Item2", "Item3"};
JComboBox combo = new JComboBox(items);
TableColumn col = table.getColumnModel().getColumn(ITEM_COL);
col.setCellEditor(new DefaultCellEditor(combo));
combo.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
System.out.println(e.getItem() + " selected");
}
}
});
this.add(new JScrollPane(table));
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}

Related

How to do a selection in cascade of JCombobox choices in a JTable?

I have a JTable with numbers 1,2,3 as 1st column and the number as text in the 2nd column which can be chosen with a JCombobox. For example 1 can be represented as "1", ONE, FIRST or ONCE in the 2nd column. When I make a choice, all the comboboxes of the rows below have to be updated in cascade with the text of the same nature. So if I choose ONCE, the comboboxes of the rows below should be updated to TWICE, THRICE. If I choose FIRST, the comboboxes of the rows below should be updated to SECOND, THIRD. And so on..
At first it looks like it's working but whenever I click somewhere else on the JTable, the combobox is updated with the value of the last row. For example, if I choose ONCE in the 1st row, at first it will update the other rows to TWICE and THRICE. Then if I click on any row, the combobox selection will be updated to THRICE on the 1st row. Next time I click, the 2nd row is updated to THRICE.
What am I doing wrong here?
The combobox cell editor:
public class NumberChoiceEditor extends DefaultCellEditor {
private static final long serialVersionUID = 1L;
private String numberAsText;
private static final String[][] NUMBERS = { { "1", "ONE", "FIRST", "ONCE" }, { "2", "TWO", "SECOND", "TWICE" }, { "3", "THREE", "THIRD", "THRICE" } };
public NumberChoiceEditor() {
super(new JComboBox<>());
}
#Override
public Object getCellEditorValue() {
return numberAsText;
}
#Override
public Component getTableCellEditorComponent(final JTable table, final Object value, final boolean isSelected, final int row, final int column) {
if (value instanceof String) {
numberAsText = (String) value;
}
JComboBox<String> numberTextChoice = new JComboBox<>(NUMBERS[row]);
numberTextChoice.setSelectedItem(numberAsText);
numberTextChoice.addActionListener(e -> {
numberAsText = (String) numberTextChoice.getSelectedItem();
int nextRow = row + 1;
if (nextRow < NUMBERS.length) {
String numberText = (String) table.getValueAt(nextRow, 1);
JComboBox<String> nextRowChoices = (JComboBox<String>) getTableCellEditorComponent(table, numberText, isSelected, nextRow, column);
nextRowChoices.setSelectedIndex(numberTextChoice.getSelectedIndex());
table.setValueAt(nextRowChoices.getSelectedItem(), nextRow, 1);
}
});
return numberTextChoice;
}
}
The main class with the frame:
public class NumberTable {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JTable table = new JTable(new Object[][] { { 1, "1" }, { 2, "2" }, { 3, "3" } }, new Object[] { "Number", "Number Text" });
table.getColumn("Number Text").setCellEditor(new NumberChoiceEditor());
table.setRowHeight(25);
JFrame frame = new JFrame("Number Table");
frame.add(new JScrollPane(table));
frame.setLocationRelativeTo(null);
frame.setSize(600, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
I would use a TableModelListener. When the value is changed via the JComboBox editor, I would adjust the TableModel accordingly.
(Notes after the code.)
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class NumTable implements Runnable, TableModelListener {
private boolean adjusting;
private JFrame frame;
private JTable table;
#Override
public void run() {
createGui();
}
#Override
public void tableChanged(TableModelEvent event) {
if (!adjusting) {
adjusting = true;
int col = event.getColumn();
if (col == 1) {
NumChoiceEd editor = (NumChoiceEd) table.getColumnModel().getColumn(1).getCellEditor();
int row = event.getFirstRow();
JComboBox<String> combo = editor.getCombo(row);
if (combo != null) {
int ndx = combo.getSelectedIndex();
if (ndx >= 0) {
int rows = table.getRowCount();
for (int i = 0; i < rows; i++) {
combo = editor.getCombo(i);
String val = combo.getModel().getElementAt(ndx);
table.setValueAt(val, i, col);
}
}
}
}
adjusting = false;
}
}
private void createGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTable(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JScrollPane createTable() {
Object[][] data = new Object[][]{{1, "1"}, {2, "2"}, {3, "3"}};
Object[] columnNames = new Object[]{"Number", "Number Text"};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
model.addTableModelListener(this);
table = new JTable(model);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
TableColumnModel tcm = table.getColumnModel();
TableColumn column = tcm.getColumn(1);
column.setCellEditor(new NumChoiceEd());
JScrollPane scrollPane = new JScrollPane(table);
return scrollPane;
}
public static void main(String[] args) {
EventQueue.invokeLater(new NumTable());
}
}
class NumChoiceEd extends DefaultCellEditor {
private static final long serialVersionUID = 1L;
private JComboBox<String> oneCombo;
private JComboBox<String> twoCombo;
private JComboBox<String> threeCombo;
public NumChoiceEd() {
super(new JComboBox<>());
oneCombo = new JComboBox<>(new String[]{"1", "ONE", "FIRST", "ONCE"});
twoCombo = new JComboBox<>(new String[]{"2", "TWO", "SECOND", "TWICE"});
threeCombo = new JComboBox<>(new String[]{"3", "THREE", "THIRD", "THRICE"});
}
public JComboBox<String> getCombo(int row) {
switch (row) {
case 0:
return oneCombo;
case 1:
return twoCombo;
case 2:
return threeCombo;
default:
return null;
}
}
#Override
public Component getTableCellEditorComponent(final JTable table,
final Object value,
final boolean isSelected,
final int row,
final int column) {
if (column == 1) {
switch (row) {
case 0:
return oneCombo;
case 1:
return twoCombo;
case 2:
return threeCombo;
default:
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
}
else {
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
}
}
Rather than create a new JComboBox each time method getTableCellEditorComponent is called, I initially create all three JComboBoxes and return the relevant one.
You don't need to override method getCellEditorValue because the superclass method (in class DefaultCellEditor) will return the correct value.
Once the user changes the value (and closes the table cell editor), method tableChanged is invoked. In that method, I get the index of the value that was selected from the JComboBox and then I go through all the rows in the JTable and get the value at that index in the JComboBox for each row and set the JTable value to that value.
Because I change the TableModel in method tableChanged, that will cause the method to be called again. In order to prevent the recursive call, I use the adjusting flag.
In the below screen capture, I have selected a value from the JComboBox but I have not yet closed the editor. If I navigate to a different cell in the JTable that will close the editor and then all the displayed data will change. Note that if you navigate to column Number Text in a different row, you may not see the change since that will immediately open the JComboBox editor for the cell that you navigated to.
After I close the editor, the table looks as in the below screen capture.
Note that there is a lot of blank space in the above screen captures since the default dimensions of JTable are quite large but the space required to display the data (in this case) is small. One way to make the JTable smaller (in this case) would be to change the preferred size of the JScrollPane.
EDIT
In response to the question you asked in your comment, namely
is it possible to update on the combobox value change
Yes, it is possible. You add an ActionListener to each JComboBox that simply calls method stopCellEditing. Here is the above code, modified to include the ActionListener. The only changes are in class NumChoiceEd.
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionListener;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class NumTable implements Runnable, TableModelListener {
private boolean adjusting;
private JFrame frame;
private JTable table;
#Override
public void run() {
createGui();
}
#Override
public void tableChanged(TableModelEvent event) {
if (!adjusting) {
adjusting = true;
int col = event.getColumn();
if (col == 1) {
NumChoiceEd editor = (NumChoiceEd) table.getColumnModel().getColumn(1).getCellEditor();
int row = event.getFirstRow();
JComboBox<String> combo = editor.getCombo(row);
if (combo != null) {
int ndx = combo.getSelectedIndex();
if (ndx >= 0) {
int rows = table.getRowCount();
for (int i = 0; i < rows; i++) {
combo = editor.getCombo(i);
String val = combo.getModel().getElementAt(ndx);
table.setValueAt(val, i, col);
}
}
}
}
adjusting = false;
}
}
private void createGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTable(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JScrollPane createTable() {
Object[][] data = new Object[][]{{1, "1"}, {2, "2"}, {3, "3"}};
Object[] columnNames = new Object[]{"Number", "Number Text"};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
model.addTableModelListener(this);
table = new JTable(model);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
TableColumnModel tcm = table.getColumnModel();
TableColumn column = tcm.getColumn(1);
column.setCellEditor(new NumChoiceEd());
JScrollPane scrollPane = new JScrollPane(table);
return scrollPane;
}
public static void main(String[] args) {
EventQueue.invokeLater(new NumTable());
}
}
class NumChoiceEd extends DefaultCellEditor {
private static final long serialVersionUID = 1L;
private JComboBox<String> oneCombo;
private JComboBox<String> twoCombo;
private JComboBox<String> threeCombo;
public NumChoiceEd() {
super(new JComboBox<>());
ActionListener al = event -> NumChoiceEd.this.stopCellEditing(); // ADDED THIS LINE
oneCombo = new JComboBox<>(new String[]{"1", "ONE", "FIRST", "ONCE"});
oneCombo.addActionListener(al); // ADDED THIS LINE
twoCombo = new JComboBox<>(new String[]{"2", "TWO", "SECOND", "TWICE"});
twoCombo.addActionListener(al); // ADDED THIS LINE
threeCombo = new JComboBox<>(new String[]{"3", "THREE", "THIRD", "THRICE"});
threeCombo.addActionListener(al); // ADDED THIS LINE
}
public JComboBox<String> getCombo(int row) {
switch (row) {
case 0:
return oneCombo;
case 1:
return twoCombo;
case 2:
return threeCombo;
default:
return null;
}
}
#Override
public Component getTableCellEditorComponent(final JTable table,
final Object value,
final boolean isSelected,
final int row,
final int column) {
if (column == 1) {
switch (row) {
case 0:
return oneCombo;
case 1:
return twoCombo;
case 2:
return threeCombo;
default:
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
}
else {
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
}
}

How to clear a selected cell in JTable?

I can select and set focus to cells in a JTable by clicking it, now I want to change the value on the focused cell. In order to change the value of it, I have to double click! Is there any way to clear/change the value of that focused cell (by single-clicking)?
I have tried jTable1.setValueAt("", row, column);, this clears the value in the background(It's not updated in the GUI/Same old value appears in the cell).
Table structure:
jTable1.addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(final MouseEvent e) {
if (e.getClickCount()==1){
final JTable jTable=(JTable)e.getSource();
final int row = jTable.getSelectedRow();
final int column = jTable.getSelectedColumn();
jTable1.editCellAt(row,column);
jTable1.getEditorComponent().requestFocus();
final Double valueInCell = (Double)jTable.getValueAt(row, column);
System.out.println(valueInCell);
}
}
});
If all you desire is to clear or change a JTable cell that holds Strings, why not simply call JTable's setValueAt(Object o, int row, int column) method? To clear, pass in "", to set to something different, then pass in a different String.
For example, my minimal reproducible example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*;
import java.util.Arrays;
import java.util.Vector;
import java.util.Random;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
#SuppressWarnings("serial")
public class TableFoo extends JPanel {
private static final Vector<String> COLUMN_NAME_VECTOR = new Vector<String>(
Arrays.asList(new String[] { "A", "B", "C" }));
private static final int COLUMN_COUNT = COLUMN_NAME_VECTOR.size();
private JTable table = new JTable();
public TableFoo() {
table.setFillsViewportHeight(true);
fillTableData();
MyMouse myMouse = new MyMouse();
table.addMouseListener(myMouse);
setLayout(new BorderLayout());
add(new JScrollPane(table), BorderLayout.CENTER);
}
class MyMouse extends MouseAdapter {
#Override
public void mousePressed(final MouseEvent e) {
final int row = table.getSelectedRow();
final int column = table.getSelectedColumn();
table.setValueAt("", row, column);
}
}
public void fillTableData() {
Vector<Vector<String>> matrix = new Vector<Vector<String>>();
int rowCount = 8;
for (int i = 0; i < rowCount ; i++) {
Vector<String> row = new Vector<String>();
for (int j = 0; j < COLUMN_COUNT; j++) {
String rowText = String.format("row %d col %d", i, j);
row.add(rowText );
}
matrix.add(row);
}
DefaultTableModel model = new DefaultTableModel(matrix,
COLUMN_NAME_VECTOR);
table.setModel(model);
}
private static void createAndShowGui() {
TableFoo mainPanel = new TableFoo();
JFrame frame = new JFrame("TableFoo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

JComboBox in Custom table model

I have got question about adding JComboBox, to Column in Custom table model which extends ObjectTableModel (Table is OmniJTable). I work on it 2 days and cannot solve this problem.
One thing I solved is displaying JComboBox in Column, but right now I have got problem with selecting anything from it (seems it's not editable, and anything like "setEditable()" not working).
Here is code which one I add jComboBox to my OmniJTable with ObjectTableModel.
class CheckBoxCellRenderer extends JComboBox implements TableCellRenderer {
JComboBox combo;
public CheckBoxCellRenderer(JComboBox comboBox) {
this.combo = new JComboBox();
for (int i=0; i<comboBox.getItemCount(); i++){
combo.addItem(comboBox.getItemAt(i));
}
}
#Override
public Component getTableCellRendererComponent(JTable jtable, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
combo.setSelectedItem(value);
return combo;
}
}
private void addComboBoxToStatusColumn(JTable table)
{
final int statusColumnIndex = bazaTelefonowOmniJTable.getColumnModel().getColumnIndex("Status");
TableColumn tmpColum = bazaTelefonowOmniJTable.getColumnModel().getColumn(statusColumnIndex);
final JComboBox comboBox = new JComboBox();
comboBox.setEditable(true);
comboBox.setEnabled(true);
loadRecordStatusFromDictionary(comboBox);
DefaultCellEditor defaultCellEditor=new DefaultCellEditor(comboBox);
tmpColum.setCellEditor(defaultCellEditor);
tmpColum.setCellRenderer(new CheckBoxCellRenderer(comboBox));
bazaTelefonowOmniJTable.setEditable(true);
//table.repaint();
}
As i said, this one adding jComboBox to Column, but i don't know how to make this one to allow me to choose items in jComboBox.
PS: Sry for my english, it's not my primary language.
The simplest thing is not to add a CellRenderer. In that case, the Table renders it as a Label and when clicked the combo box is shown. Here is an example:
package snippet;
import java.awt.Component;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
public class JTableTest extends JFrame {
public JTableTest() {
super(JTableTest.class.getName());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents();
}
private void initComponents() {
JTable table = new JTable(new Object[][] { { "1", "One" }, { "2", "Two" } }, new Object[] { "Column One", "Status" });
addComboBoxToStatusColumn(table);
add(new JScrollPane(table));
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
new JTableTest().setVisible(true);
}
});
}
private void addComboBoxToStatusColumn(JTable table) {
final int statusColumnIndex = table.getColumnModel().getColumnIndex("Status");
TableColumn tmpColum = table.getColumnModel().getColumn(statusColumnIndex);
final JComboBox comboBox = new JComboBox();
loadRecordStatusFromDictionary(comboBox);
DefaultCellEditor defaultCellEditor = new DefaultCellEditor(comboBox);
tmpColum.setCellEditor(defaultCellEditor);
}
private void loadRecordStatusFromDictionary(JComboBox comboBox) {
comboBox.addItem("Two");
comboBox.addItem("Four");
comboBox.addItem("Six");
}
}
You also need to override the isCellEditable method from your model.
model = DaneTableModel(some arg) {
public boolean isCellEditable(int row, int col) {
if(col == STATUS_COLUMN) return true ;
return false;
}
}

Deletion of JTable row

I'm working on jTable and I intend on deleting specific rows as part of the data manipulation to be conducted on the table. Essentially I've been able to successfully delete a row which the user would specify but I what I really want to do is to delete several rows based on boolean states or check boxes that are selected as part one of the four columns of the table.
I've attached a screenshot as to the current result of running the code and would like to be able to delete the rows based on the selected boolean states or check boxes.
Below is my code including my table model code which extends the AbstractTableModel:
package com.TableRowSelectProgramatically;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
#SuppressWarnings("serial")
public class JTableRowSelectProgramatically extends JPanel {
public MyTableModel MyTableModel;
public String Cell1 = "ABCD";
public JTableRowSelectProgramatically() {
initializePanel();
}
private void initializePanel() {
setLayout(null);
setPreferredSize(new Dimension(1250, 700));
// Table model
MyTableModel = new MyTableModel();
// Table
final JTable table = new JTable(MyTableModel);
table.setFillsViewportHeight(true);
// Row data
Object[] values = {Cell1, "EFGH", "IJKL", new Boolean(false)};
Object[] values2 = {"UVWX","QRST","MNOP", new Boolean(false)};
Object[] values3 = {"ABCD","YZAB","CDEF", new Boolean(false)};
final Object[] values4 = {"QWERTY","YTREWQ","QWERTY", new Boolean(false)};
// Insert row data
MyTableModel CustomTableModel = (MyTableModel) table.getModel();
CustomTableModel.insertData(values);
CustomTableModel.insertData(values2);
CustomTableModel.insertData(values3);
CustomTableModel.insertData(values);
CustomTableModel.insertData(values2);
CustomTableModel.insertData(values3);
CustomTableModel.insertData(values);
CustomTableModel.insertData(values2);
CustomTableModel.insertData(values3);
// Create edit menu label
JLabel labelEditMenu = new JLabel("EDIT MENU:\n");
// Create add row btn
JButton addRow = new JButton("Add Row");
// Attach listener for add row btn
addRow.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
MyTableModel.insertData(values4);
}
});
// Create delete row btn
JButton deleteRow = new JButton("Delete Row");
// Attach listener for delete btn
deleteRow.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
MyTableModel.removeRow(1);
}
});
// Create scroll pane
JScrollPane pane = new JScrollPane(table);
pane.setBounds(30, 30, 500, 500);
//
JTextField AgentIDTextField = new JTextField();
// Populate the JPanel
JPanel dataEntryPanel = new JPanel(new FlowLayout());
//dataEntryPanel.setBackground(Color.orange);
dataEntryPanel.setBounds(540, 30, 500, 50);
//dataEntryPanel.add(AgentIDTextField);
dataEntryPanel.add(labelEditMenu);
dataEntryPanel.add(addRow);
dataEntryPanel.add(deleteRow);
// Join up GUI
add(pane);
add(dataEntryPanel);
}
// Enable visibity of frame
public static void showFrame() {
JPanel panel = new JTableRowSelectProgramatically();
JFrame frame = new JFrame("Test table");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}
// Launch prog
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JTableRowSelectProgramatically.showFrame();
}
});
}
// Create custom table model for data entry
class MyTableModel extends AbstractTableModel {
private String[] columnNames = {"COLUMN 0", "COLUMN 1", "COLUMN 2", "COLUMN 3"};
private Vector data = new Vector();
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#SuppressWarnings("rawtypes")
#Override
public Object getValueAt(int row, int col) {
return ((Vector) data.get(row)).get(col);
}
public String getColumnName(int col){
return columnNames[col];
}
public Class getColumnClass(int c){
return getValueAt(0,c).getClass();
}
public void setValueAt(Object value, int row, int col){
((Vector) data.get(row)).setElementAt(value, col);
fireTableCellUpdated(row,col);
}
public boolean isCellEditable(int row, int col){
if (3 == col){
return true;
}
else {
return false;
}
}
public void insertData(Object[] values){
data.add(new Vector());
for(int i =0; i<values.length; i++){
System.out.println("data.size is: " + data.size());
((Vector) data.get(data.size()-1)).add(values[i]);
}
fireTableDataChanged();
}
public void removeRow(int row){
data.removeElementAt(row);
fireTableDataChanged();
}
}
}
New attempt at deleting rows of a JTable:
public void deleteRow() {
for (int i = 0; i < getRowCount(); i++) {
Object columnState = getValueAt(i, 3);
System.out.println("STEP 6 - In row " + i + " boolean value is: " + columnState);
boolean columnStateAsBoolean = (Boolean) columnState;
System.out.println("STEP 6 - In row " + i + " Column State As Boolean is: " + columnStateAsBoolean);
if(columnStateAsBoolean == true) {
removeRow(i);
}
System.out.println("-------------------------------------");
}
}
I really want to do is to delete several rows based on boolean states or check boxes
create a loop that starts on the last row and counts down to 0.
Then for every row you use the table.getValueAt(...) method to get the Boolean value of the column.
If the value is true then delete the row.
//Try something like this
int rowCount=table.getSelectedRowCount();//get selected row's count
int row;
if(rowCount>0)
{
while((row=table.getSelectedRow())!=-1)
(DefaultTableModel)table.getModel().removeRow(table.convertRowIndexToModel(row));
}

Dynamic jcombobox items inside jtable

I am trying to create a Jtable with two combobox in each row. I have checked for tutorials on that and found that I can add static data inside combobox. But how come I can have dynamic data loaded into a combobox.
Even, whenever the user selects the combobox 1 from the row, then based on that, the combobox 2 will be updated.
Can anybody help me on this?
If I do removeAllItems() from the combobox, then the combobox 2 will updated, but I am unable to add new entries.
Thanks in advance.
Table has two columns both are rendered as JComboBox. Now, selection of Column-2 items are dependent on the Column-1 selection.
import java.awt.Component;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class ComboBoxExample {
private void createUI() {
JFrame frame = new JFrame();
Object[] columNames = {"Combo-1", "Combo-2"};
Object[][] data = {{"", ""}, {"", ""}, {"", ""}, {"", ""}};
JTable table = new JTable(data, columNames);
table.getColumnModel().getColumn(0).setCellEditor(new CustomComboBoxEditor());
table.getColumnModel().getColumn(1).setCellEditor(new CustomComboBoxEditor());
frame.add(new JScrollPane(table));
frame.setTitle("Column -2 based on Column - 1 ComboBox Selection.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new ComboBoxExample().createUI();
}
};
EventQueue.invokeLater(r);
}
}
class CustomComboBoxEditor extends DefaultCellEditor {
// Declare a model that is used for adding the elements to the `ComboBox`
private DefaultComboBoxModel model;
private List<String> obtainedList;
public CustomComboBoxEditor() {
super(new JComboBox());
this.model = (DefaultComboBoxModel)((JComboBox)getComponent()).getModel();
obtainedList = new ArrayList<String>();
obtainedList.add("One");
obtainedList.add("Two");
obtainedList.add("Three");
obtainedList.add("Four");
obtainedList.add("Five");
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
if(column == 0) {
model.removeAllElements();
for(int i = 0; i < obtainedList.size(); i++) {
model.addElement(obtainedList.get(i));
}
} else {
model.removeAllElements();
String selectedItem = (String) table.getValueAt(row, 0);
for(int i = 0; i < obtainedList.size(); i++) {
if(!selectedItem.equals(obtainedList.get(i)))
model.addElement(obtainedList.get(i));
}
} // Close else
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
}
Try something like this, you can change DATA in this example, and repaint and do the Renderer of the cell:
public void example(){
TableColumn tmpColum =table.getColumnModel().getColumn(1);
String[] DATA = { "Data 1", "Data 2", "Data 3", "Data 4" };
JComboBox comboBox = new JComboBox(DATA);
DefaultCellEditor defaultCellEditor=new DefaultCellEditor(comboBox);
tmpColum.setCellEditor(defaultCellEditor);
tmpColum.setCellRenderer(new CheckBoxCellRenderer(comboBox));
table.repaint();
}
/**
Custom class for adding elements in the JComboBox.
*/
class CheckBoxCellRenderer implements TableCellRenderer {
JComboBox combo;
public CheckBoxCellRenderer(JComboBox comboBox) {
this.combo = new JComboBox();
for (int i=0; i<comboBox.getItemCount(); i++){
combo.addItem(comboBox.getItemAt(i));
}
}
public Component getTableCellRendererComponent(JTable jtable, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
combo.setSelectedItem(value);
return combo;
}
}
After removeAllItems() call, add items in combobox as
combobox.addItem("one");
combobox.addItem("two");

Categories