Error in getRowCount() on DefaultTableModel - java

EDIT
I've tried changing the table model back to DefaultTableModel but I am getting an Exception when compiling my code and I can't figure out why!
Here's my table init:
jTable1.setModel(new Table1Model());
jTable1.setDefaultRenderer(Color.class,new ColorRenderer(true));
jTable1.getColumnModel().getColumn(5).setCellEditor(new ColorEditor());
My class extending the model:
class Table1Model extends DefaultTableModel {
//private String[] columnNames = {"Station #",
private Object[] columnNames = {"Station #",
"Name",
"avg Time",
"Buffer",
"Buffer Parts",
"Color"};
private Object[][] data = {
{"1", "Station 1",
new Integer(10), false, new Integer(0), Color.red},
{"2", "Station 2",
new Integer(10), false, new Integer(0), Color.blue},
{"3", "Station 3",
new Integer(10), false, new Integer(0), Color.green},
{"4", "Station 4",
new Integer(10), false, new Integer(0), Color.orange},
{"5", "Station 5",
new Integer(10), false, new Integer(0), Color.black}
};
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public int getRowCount() {
//int length = data.length;
//int datalength = Integer.parseInt(length);
return data.length;
}
#Override
public String getColumnName(int col) {
return columnNames[col].toString();
}
#Override
public Object getValueAt(int row, int col) {
return data[row][col];
}
/*
* JTable uses this method to determine the default renderer/
* editor for each cell. If we didn't implement this method,
* then the last column would contain text ("true"/"false"),
* rather than a check box.
*/
#Override
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
/*
* Don't need to implement this method unless your table's
* editable.
*/
#Override
public boolean isCellEditable(int row, int col) {
//Note that the data/cell address is constant,
//no matter where the cell appears onscreen.
if (col == 0) { return false; }
else if (col == 4) {
boolean di = (Boolean) getValueAt(row,(col-1));
if (!di) { return false; }
else { return true; }
}
else { return true; }
}
/*
* Don't need to implement this method unless your table's
* data can change.
*/
#Override
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
/*public void removeRow(int row) {
data.removeRow(row);
}*/
private void printDebugData() {
int numRows = getRowCount();
int numCols = getColumnCount();
for (int i=0; i < numRows; i++) {
System.out.print(" row " + i + ":");
for (int j=0; j < numCols; j++) {
System.out.print(" " + data[i][j]);
}
System.out.println();
}
System.out.println("--------------------------");
}
}
This generates the following error:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at SimGui$Table1Model.getRowCount(SimGui.java:863)
at javax.swing.table.DefaultTableModel.setDataVector(DefaultTableModel.java:224)
at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:124)
at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:106)
at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:86)
at SimGui$Table1Model.<init>(SimGui.java:832)
at SimGui.initComponents(SimGui.java:265)
at SimGui.<init>(SimGui.java:34)
at SimGui$16.run(SimGui.java:789)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:701)
at java.awt.EventQueue.access$000(EventQueue.java:102)
at java.awt.EventQueue$3.run(EventQueue.java:662)
at java.awt.EventQueue$3.run(EventQueue.java:660)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:671)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)
Can you help me figure out what's wrong?
Also, will I be able to use the ColorEditor with the DefaultTableModel?

You have two obvious choices here: either give your class a getVectorData() method or else give it another similarly useful method that allows you to extract the nucleus of your data from your model. You probably shouldn't use an AbstractTableModel variable though but rather use a variable of your own custom type that extends AbstractTableModel to allow you to be able to call custom methods of your model.
i.e.,
MyTableModel model = (MyTableModel)jTable1.getModel();
SomeCollection myKeyData = model.getMyKeyData();
Also, this statement:
I have recently created my own class to extend AbstractTableModel to be able to insert some logic on isCellEditable and setValueAt.
Doesn't make sense to me since you could always use a DefaultTableModel and simply override those two methods. But if you use a DefaultTableModel, don't also have it hold the 2D array of object as you're trying to do. Rather feed the data into its internal data via the appropriate constructor or via its addRow(...) method. Else you lose all the power that DefaultTableModel has to offer.
Edit
If you want to use a DefaultTableModel to leverage its methods, then you cannot use a separate data "nucleus" for your model (here your Object[][]), but instead must load your data into the model that is held inside of the DefaultTableModel super class. This can be done either via the correct super constructor or by adding rows of data using its addRow(...) method.
For example, here I load your data into a DefaultTableModel override:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.table.*;
public class TableModelTest extends JPanel {
private static final Object[][] DATA = {
{ "1", "Station 1", new Integer(10), false, new Integer(0), Color.red },
{ "2", "Station 2", new Integer(10), false, new Integer(0), Color.blue },
{ "3", "Station 3", new Integer(10), false, new Integer(0),
Color.green },
{ "4", "Station 4", new Integer(10), false, new Integer(0),
Color.orange },
{ "5", "Station 5", new Integer(10), false, new Integer(0),
Color.black } };
private MyTableModel myTableModel = new MyTableModel(DATA);
private JTable table = new JTable(myTableModel);
public TableModelTest() {
setLayout(new BorderLayout());
add(new JScrollPane(table), BorderLayout.CENTER);
table.getColumnModel().getColumn(5)
.setCellRenderer(new ColorCellRenderer());
table.getColumnModel().getColumn(5).setCellEditor(new ColorCellEditor());
}
private static void createAndShowGui() {
TableModelTest mainPanel = new TableModelTest();
JFrame frame = new JFrame("TableModelTest");
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();
}
});
}
}
class ColorCellEditor extends AbstractCellEditor implements TableCellEditor {
Color currentColor;
JButton button;
JColorChooser colorChooser;
JDialog dialog;
protected static final String EDIT = "edit";
public ColorCellEditor() {
ActionListener actionListener = new MyActionListener();
button = new JButton();
button.setActionCommand(EDIT);
button.addActionListener(actionListener);
button.setBorderPainted(false);
colorChooser = new JColorChooser();
dialog = JColorChooser.createDialog(button, "Pick a Color", true,
colorChooser, actionListener, null);
}
private class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (EDIT.equals(e.getActionCommand())) {
button.setBackground(currentColor);
colorChooser.setColor(currentColor);
dialog.setVisible(true);
fireEditingStopped();
} else {
currentColor = colorChooser.getColor();
}
}
}
public Object getCellEditorValue() {
return currentColor;
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
currentColor = (Color) value;
return button;
}
}
class ColorCellRenderer implements TableCellRenderer {
private static final int IMG_WIDTH = 70;
private static final int IMG_HEIGHT = 20;
private JLabel label = new JLabel();
#Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean arg2, boolean arg3, int arg4, int arg5) {
Color color = (Color) value;
BufferedImage img = new BufferedImage(IMG_WIDTH, IMG_HEIGHT,
BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.setColor(color);
g.fillRect(0, 0, IMG_WIDTH, IMG_HEIGHT);
g.dispose();
ImageIcon icon = new ImageIcon(img);
label.setIcon(icon);
return label;
}
}
class MyTableModel extends DefaultTableModel {
private static final String[] COLUMN_NAMES = { "Station #", "Name",
"avg Time", "Buffer", "Buffer Parts", "Color" };
public MyTableModel(Object[][] data) {
super(data, COLUMN_NAMES);
}
#Override
public boolean isCellEditable(int row, int col) {
if (col == 0) {
return false;
} else if (col == 4) {
boolean di = (Boolean) getValueAt(row, (col - 1));
if (!di) {
return false;
} else {
return true;
}
} else {
return true;
}
}
public void printDebugData() {
int numRows = getRowCount();
int numCols = getColumnCount();
for (int i = 0; i < numRows; i++) {
System.out.print(" row " + i + ":");
for (int j = 0; j < numCols; j++) {
Object datum = getValueAt(i, j);
// System.out.print(" " + data[i][j]);
System.out.print(" " + datum);
}
System.out.println();
}
System.out.println("--------------------------");
}
}

Related

JTable with different JCombobox for each line

I have a table that I'm loading with rows at run time. Once loaded the user needs to choose an item from a JComboBox in the first column for each line. Then he needs to chose an item from another JComboBoxon the same line in every rows. The content of the second JComboBox depends on the selection of the first JComboBox.
The way I coded it now is changing the combobox content for the whole second column.
columnProfile.setCellEditor(new DefaultCellEditor(comboBoxProf))
Is there a way to have a combobox object different on every row so I can work on it everytime I select a value in the first combobox?
The number of rows is not fixed until the user hits submit. He can add and delete rows.
I've used the basic Table example from Oracle and made the changes to reflect what I'm currently doing
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
public class TableRenderDemo extends JPanel {
private boolean DEBUG = false;
JComboBox comboBox2;
JComboBox comboBox1;
public TableRenderDemo() {
super(new GridLayout(1,0));
JTable table = new JTable(new MyTableModel());
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
JScrollPane scrollPane = new JScrollPane(table);
initColumnSizes(table);
setUpSportColumn(table, table.getColumnModel().getColumn(2));
setUpYearsColumn(table, table.getColumnModel().getColumn(3));
add(scrollPane);
table.getModel().addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
if (e.getColumn() == 2){
comboBox2.removeAllItems();
/*REFILL COMBOBOX WITH WHAT I NEED FOR THIS ROW ONLY*/
}
}
});
}
private void initColumnSizes(JTable table) {
MyTableModel model = (MyTableModel)table.getModel();
TableColumn column = null;
Component comp = null;
int headerWidth = 0;
int cellWidth = 0;
Object[] longValues = model.longValues;
TableCellRenderer headerRenderer =
table.getTableHeader().getDefaultRenderer();
for (int i = 0; i < 5; i++) {
column = table.getColumnModel().getColumn(i);
comp = headerRenderer.getTableCellRendererComponent(
null, column.getHeaderValue(),
false, false, 0, 0);
headerWidth = comp.getPreferredSize().width;
comp = table.getDefaultRenderer(model.getColumnClass(i)).
getTableCellRendererComponent(
table, longValues[i],
false, false, 0, i);
cellWidth = comp.getPreferredSize().width;
if (DEBUG) {
System.out.println("Initializing width of column "
+ i + ". "
+ "headerWidth = " + headerWidth
+ "; cellWidth = " + cellWidth);
}
column.setPreferredWidth(Math.max(headerWidth, cellWidth));
}
}
public void setUpSportColumn(JTable table,
TableColumn sportColumn) {
//Set up the editor for the sport cells.
comboBox1 = new JComboBox();
comboBox1.addItem("Snowboarding");
comboBox1.addItem("Rowing");
comboBox1.addItem("Knitting");
comboBox1.addItem("Speed reading");
comboBox1.addItem("Pool");
comboBox1.addItem("None of the above");
sportColumn.setCellEditor(new DefaultCellEditor(comboBox1));
DefaultTableCellRenderer renderer =
new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
sportColumn.setCellRenderer(renderer);
}
public void setUpYearsColumn(JTable table,
TableColumn yearColumn) {
comboBox2 = new JComboBox();
comboBox2.addItem("1");
comboBox2.addItem("2");
comboBox2.addItem("3");
comboBox2.addItem("4");
comboBox2.addItem("5");
comboBox2.addItem("6");
yearColumn.setCellEditor(new DefaultCellEditor(comboBox2));
//Set up tool tips for the sport cells.
DefaultTableCellRenderer renderer =
new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
yearColumn.setCellRenderer(renderer);
}
class MyTableModel extends AbstractTableModel {
private String[] columnNames = {"First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian"};
private Object[][] data = {
{"Kathy", "Smith",
"Snowboarding", "1", new Boolean(false)},
{"John", "Doe",
"Rowing", "1", new Boolean(true)},
{"Sue", "Black",
"Knitting", "1", new Boolean(false)},
{"Jane", "White",
"Speed reading", "1", new Boolean(true)},
{"Joe", "Brown",
"Pool", "1", new Boolean(false)}
};
public final Object[] longValues = {"Jane", "Kathy",
"None of the above",
new Integer(20), Boolean.TRUE};
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
public boolean isCellEditable(int row, int col) {
if (col < 2) {
return false;
} else {
return true;
}
}
public void setValueAt(Object value, int row, int col) {
if (DEBUG) {
System.out.println("Setting value at " + row + "," + col
+ " to " + value
+ " (an instance of "
+ value.getClass() + ")");
}
data[row][col] = value;
fireTableCellUpdated(row, col);
if (DEBUG) {
System.out.println("New value of data:");
printDebugData();
}
}
private void printDebugData() {
int numRows = getRowCount();
int numCols = getColumnCount();
for (int i=0; i < numRows; i++) {
System.out.print(" row " + i + ":");
for (int j=0; j < numCols; j++) {
System.out.print(" " + data[i][j]);
}
System.out.println();
}
System.out.println("--------------------------");
}
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TableRenderDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TableRenderDemo newContentPane = new TableRenderDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Say you had your data held in a Map<String, List<String>> with the Map's keys representing the values held by the first JComboBox, and the Map's values representing the changing values held by the 2nd column's JComboBox (the data does not need to be set up this way, but it's easy for MCVE/demonstration purposes), and call this map dataMap, then your column editor could look something like:
column1.setCellEditor(new DefaultCellEditor(combo1) {
#SuppressWarnings("unchecked")
#Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
// the items that will fill our JComboBox. Initially its empty
Object[] items = new Object[]{};
// get the value in the column to the left
Object column0Value = table.getValueAt(row, column - 1);
if (column0Value != null) {
// if the value is not null, then get the map's values
// and use it to fill our items array
items = dataMap.get(column0Value).toArray();
}
// get the super component, the JComboBox that is being used
// as an editor:
JComboBox<Object> superCombo = (JComboBox<Object>) super.getTableCellEditorComponent(table, value, isSelected,
row, column);
// create a model and fill with items
DefaultComboBoxModel<Object> comboModel = new DefaultComboBoxModel<>(items);
// set the cell editor's model and return
superCombo.setModel(comboModel);
return superCombo;
}
});
For example please check this MCVE as an example that uses the above cell editor and as an example of a MCVE that would work well in your future questions
import java.awt.Component;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
#SuppressWarnings("serial")
public class TableWithMultCombos extends JPanel {
private static final String[] COLUMN_NAMES = { "Day of Week", "Number" };
private Map<String, List<String>> dataMap = new LinkedHashMap<>();
private DefaultTableModel tblModel = new DefaultTableModel(COLUMN_NAMES, 5);
private JTable table = new JTable(tblModel);
private DefaultComboBoxModel<Object> combo2Model = new DefaultComboBoxModel<>();
private JComboBox<Object> combo0 = null;
private JComboBox<Object> combo1 = new JComboBox<>(combo2Model);
public TableWithMultCombos() {
dataMap.put("Monday", Arrays.asList(new String[] { "Mon - 1", "Mon - 2", "Mon - 3", "Mon - 4" }));
dataMap.put("Tuesday", Arrays.asList(new String[] { "Tues - 1", "Tues - 2", "Tues - 3", "Tues - 4" }));
dataMap.put("Wednesday", Arrays.asList(new String[] { "Wed - 1", "Wed - 2", "Wed - 3", "Wed - 4" }));
dataMap.put("Thursday", Arrays.asList(new String[] { "Thurs - 1", "Thurs - 2", "Thurs - 3", "Thurs - 4" }));
dataMap.put("Friday", Arrays.asList(new String[] { "Fri - 1", "Fri - 2", "Fri - 3", "Fri - 4" }));
combo0 = new JComboBox<>(dataMap.keySet().toArray());
TableColumn column0 = table.getColumnModel().getColumn(0);
column0.setCellEditor(new DefaultCellEditor(combo0));
TableColumn column1 = table.getColumnModel().getColumn(1);
column1.setCellEditor(new DefaultCellEditor(combo1) {
#SuppressWarnings("unchecked")
#Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
// the items that will fill our JComboBox. Initially its empty
Object[] items = new Object[]{};
// get the value in the column to the left
Object column0Value = table.getValueAt(row, column - 1);
if (column0Value != null) {
// if the value is not null, then get the map's values
// and use it to fill our items array
items = dataMap.get(column0Value).toArray();
}
// get the super component, the JComboBox that is being used
// as an editor:
JComboBox<Object> superCombo = (JComboBox<Object>) super.getTableCellEditorComponent(table, value, isSelected,
row, column);
// create a model and fill with items
DefaultComboBoxModel<Object> comboModel = new DefaultComboBoxModel<>(items);
// set the cell editor's model and return
superCombo.setModel(comboModel);
return superCombo;
}
});
table.setFillsViewportHeight(true);
add(new JScrollPane(table));
}
private static void createAndShowGui() {
TableWithMultCombos mainPanel = new TableWithMultCombos();
JFrame frame = new JFrame("TableWithMultCombos");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}

Cant get the checkbox to be a boolean using column class

I have the following code:
The issue i am having is that i want to set the last column as a checkbox boolean, tickable yes or no. However when i set the column class as boolean for the column i still get a string, why is my boolean opt for the column not working?
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import java.awt.Dimension;
import javax.swing.JButton;
/**
* TableDemo is just like SimpleTableDemo, except that it uses a custom
* TableModel.
*/
public class NewClass extends JPanel{
private boolean DEBUG = false;
public NewClass() {
JTable table = new JTable(new MyTableModel());
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this panel.
add(scrollPane);
}
class MyTableModel extends AbstractTableModel {
private String[] columnNames = { "First Name", "Last Name", "Sport",
"# of Years", "Vegetarian" };
private Object[][] data = {
{ "Mary", "Campione", "Snowboarding", new Integer(5),
new Boolean(false) },
{ "Alison", "Huml", "Rowing", new Integer(3), new Boolean(true) },
{ "Kathy", "Walrath", "Knitting", new Integer(2),
new Boolean(false) },
{ "Sharon", "Zakhour", "Speed reading", new Integer(20),
new Boolean(true) },
{ "Philip", "Milne", "Pool", new Integer(10),
new Boolean(false) } };
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public Class getColumnClass(int c) {
switch (c){
case 0:
return String.class;
case 1:
return String.class;
case 2:
return String.class;
case 3:
return String.class;
case 4:
return boolean.class;// i thought here if i define the column data type as boolean i would get checkboxes why not?
default:
return String.class;
}
}
/**
* Don't need to implement this method unless your table's editable.
*/
public boolean isCellEditable(int row, int col) {
//Note that the data/cell address is constant,
//no matter where the cell appears onscreen.
return false;
}
/**
* Don't need to implement this method unless your table's data can
* change.
*/
public void setValueAt(Object value, int row, int col) {
if (DEBUG) {
System.out.println("Setting value at " + row + "," + col
+ " to " + value + " (an instance of "
+ value.getClass() + ")");
}
data[row][col] = value;
fireTableCellUpdated(row, col);
if (DEBUG) {
System.out.println("New value of data:");
printDebugData();
}
}
private void printDebugData() {
int numRows = getRowCount();
int numCols = getColumnCount();
for (int i = 0; i < numRows; i++) {
System.out.print(" row " + i + ":");
for (int j = 0; j < numCols; j++) {
System.out.print(" " + data[i][j]);
}
System.out.println();
}
System.out.println("--------------------------");
}
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
NewClass newContentPane = new NewClass();
JButton button = new JButton("Enter");
JPanel mainPane = new JPanel();
mainPane.add(button,BorderLayout.NORTH);
mainPane.add(newContentPane,BorderLayout.CENTER);
//Create and set up the window.
JFrame frame = new JFrame("TableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(mainPane);
//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.
//System.out.println(human1.eat());
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

rows not deleted from JTable

In my JTable, all my checkboxes are in column 3. after I onclick a button, it will
remove those rows that are checked.
But however after implementing the functions in my onclick. It does not remove the the rows.
The method for the button listener
class DeleteBtnListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent arg0) {
for(int row = 0; row < table.getRowCount(); ++row) {
if((Boolean) table.getValueAt(row, 3) == true) {
myTableModel.removeRow(row);
table.revalidate();
table.repaint();
}
}
}
}
and this is what is in my AbstractTableModel class
#SuppressWarnings("serial")
class MyTableModel extends AbstractTableModel {
private final boolean DEBUG = true;
private String[] columnNames = {"Name",
"Age",
"Salary",
"Delete"};
private Object[][] data = {
{"Kathy", "20",new Integer(5), new Boolean(false)},
{"John", "35", new Integer(3), new Boolean(false)},
{"Sue", "20", new Integer(2), new Boolean(false)},
{"Jane", "12", new Integer(20), new Boolean(false)},
{"Mary", "42", new Integer(10), new Boolean(false)}
};
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
#SuppressWarnings("unchecked")
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
public boolean isCellEditable(int row, int col) {
return true;
}
public void setValueAt(Object value, int row, int col) {
if (DEBUG) {
System.out.println("Setting value at " + row + "," + col
+ " to " + value);
}
data[row][col] = value;
fireTableCellUpdated(row, col);
}
public void removeRow(int row) {
fireTableRowsDeleted(row, row);
}
}
You need to remove the row from the actual data in your model (i.e. the array data). fireTableRowsDeleted is not enough. That just updates ui stuff. Keep in mind though, you are using an array. So you will need to advance the row indices accordingly with the data. Better use a List for easier manipulation. Also keep in mind you are trying to remove rows "concurrently" in the loop. So if you remove a row, you need to decrement the row in the loop also.
Also as #AndrewThompson mentioned, just use a DefaultTableModel. I don't see anything special about your model that warrants the need for a custom model.
Here's an example with DefaultTableModel
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class TestTable {
private DefaultTableModel myTableModel = getModel();
private JTable table = new JTable(myTableModel);
public TestTable() {
JButton button = new JButton("Remove All");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
for(int row = 0; row < table.getRowCount(); ++row) {
if((Boolean) table.getValueAt(row, 3) == true) {
System.out.println("true");
myTableModel.removeRow(row);
row--;
}
}
}
});
JFrame frame = new JFrame();
frame.add(new JScrollPane(table));
frame.add(button, BorderLayout.PAGE_END);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private DefaultTableModel getModel() {
String[] columnNames = {"Name",
"Age",
"Salary",
"Delete"};
Object[][] data = {
{"Kathy", "20",new Integer(5), new Boolean(false)},
{"John", "35", new Integer(3), new Boolean(false)},
{"Sue", "20", new Integer(2), new Boolean(false)},
{"Jane", "12", new Integer(20), new Boolean(false)},
{"Mary", "42", new Integer(10), new Boolean(false)}
};
return new DefaultTableModel(data, columnNames) {
#Override
public Class<?> getColumnClass(int col) {
switch(col) {
case 0:
case 1: return String.class;
case 2: return Integer.class;
case 3: return Boolean.class;
default: return Object.class;
}
}
};
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new TestTable();
}
});
}
}
Can you try with DefaultTableModel that works perfectly. Override other methods of JTable if needed.
sample code:
DefaultTableModel model = new DefaultTableModel(data, columnNames);
final JTable table = new JTable(model) {
#Override
public Class<?> getColumnClass(int column) {
switch (column) {
case 2:
return Integer.class;
case 3:
return Boolean.class;
default:
return String.class;
}
}
#Override
public boolean isCellEditable(int row, int col) {
return true;
}
};
To remove row call
((DefaultTableModel) table.getModel()).removeRow(row);

Using JComboBox with custom renderer as JTable cell renderer/editor (architecture)

I'm new to GUI design and I'm trying to plan this out before I go too far the wrong way, any help would be nice. I'm trying to display a JTable with rows of Employee, which itself has datatypes of String and ArrayList<Cert>. Cert contains a String.
I'd like to have the table present the data for editing, but for a few of the columns I'd like to implement a JComboBox for selection of a String from a set of valid strings, as well as color each option differently (different background colors in the JComboBox).
Also, the ArrayList<Cert> currently displays in a cell as [xxx, xxx, ...] where XXX is the return from the toString() function for each item in the ArrayList. I think I'd like to display that ArrayList<Cert> as a read-only JComboBox, but I'm not as concerned with this item.
I'm questioning how many classes I need to create to make this happen. I already have a custom model for the JTable extending AbstractTableModel. Do I need to write an extension of JComboBox or do I just need to extend the appropriate renderer for a JComboBox as a cell and do the magic there, then assign that custom renderer to the cell renderer for the String cell?
Here's what I have so far, lightly abridged:
public class EmployeeTableModel extends AbstractTableModel {
...
private ArrayList<Employee> myDataObjects = new ArrayList<Employee>();
...
#Override
public Object getValueAt(int row, int column) {
Employee emp = myDataObjects.get(row);
switch (column) {
case 0:
return emp.getName();
case 1:
return emp.getShift();
case 2:
return emp.getCertifications();
default:
return "";
}
}
}
Employees:
public class Employee {
private String name;
private String shift;
private ArrayList<Cert> certs;
...
public String getName() {
return name;
}
public String getShift() {
return shift;
}
public ArrayList<Cert> getCerts() {
return certs;
}
...
}
And the initializations:
EmployeeTableModel etm = new EmployeeTableModel();
JTable employeeTable = new JTable();
employeeTable.setModel( etm );
you can to start with, simplest code as is possible, maybe depends if you want to see JComboBox as Renderer too by #aterai
import java.awt.BorderLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
public class TableRenderDemo extends JPanel {
private static final long serialVersionUID = 1L;
public TableRenderDemo() {
super(new BorderLayout(5, 5));
final JTable table = new JTable(new MyTableModel());
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.setFillsViewportHeight(true);
table.setRowHeight(20);
JScrollPane scrollPane = new JScrollPane(table);
initColumnSizes(table);
setUpSportColumn(table, table.getColumnModel().getColumn(2));
add(scrollPane, BorderLayout.CENTER);
JButton resetButton = new JButton("Reset to default");
resetButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < table.getRowCount(); i++) {
table.getModel().setValueAt("None of the above", i, 2);
}
}
});
add(resetButton, BorderLayout.SOUTH);
}
private void initColumnSizes(JTable table) {
MyTableModel model = (MyTableModel) table.getModel();
TableColumn column = null;
Component comp = null;
int headerWidth = 0;
int cellWidth = 0;
Object[] longValues = model.longValues;
TableCellRenderer headerRenderer = table.getTableHeader().getDefaultRenderer();
for (int i = 0; i < 5; i++) {
column = table.getColumnModel().getColumn(i);
comp = headerRenderer.getTableCellRendererComponent(null, column.getHeaderValue(), false, false, 0, 0);
headerWidth = comp.getPreferredSize().width;
comp = table.getDefaultRenderer(model.getColumnClass(i)).getTableCellRendererComponent(table, longValues[i], false, false, 0, i);
cellWidth = comp.getPreferredSize().width;
column.setPreferredWidth(Math.max(headerWidth, cellWidth));
}
}
private void setUpSportColumn(JTable table, TableColumn sportColumn) {
ArrayList<String> listSomeString = new ArrayList<String>();
listSomeString.add("Snowboarding");
listSomeString.add("Rowing");
listSomeString.add("Knitting");
listSomeString.add("Speed reading");
listSomeString.add("Pool");
listSomeString.add("None of the above");
JComboBox comboBox = new JComboBox();
comboBox.addItem(new Item(1, "-"));
comboBox.addItem(new Item(2, "Snowboarding"));
comboBox.addItem(new Item(3, "Rowing"));
comboBox.addItem(new Item(4, "Knitting"));
comboBox.addItem(new Item(5, "Speed reading"));
comboBox.addItem(new Item(6, "Pool"));
comboBox.addItem(new Item(7, "None of the above"));
comboBox.setMaximumRowCount(3);
comboBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JComboBox comboBox = (JComboBox) e.getSource();
Item item = (Item) comboBox.getSelectedItem();
System.out.println(item.getId() + " : " + item.getDescription());
}
});
comboBox.setRenderer(new ItemRenderer());
sportColumn.setCellEditor(new DefaultCellEditor(comboBox));
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
sportColumn.setCellRenderer(renderer);
}
class ItemRenderer extends BasicComboBoxRenderer {
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value != null) {
Item item = (Item) value;
setText(item.getDescription().toUpperCase());
}
if (index == -1) {
Item item = (Item) value;
setText("" + item.getId());
}
return this;
}
}
class Item {
private int id;
private String description;
public Item(int id, String description) {
this.id = id;
this.description = description;
}
public int getId() {
return id;
}
public String getDescription() {
return description;
}
#Override
public String toString() {
return description;
}
}
class MyTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian"};
private Object[][] data = {{"Kathy", "Smith", "Snowboarding", new Integer(5), false},
{"John", "Doe", "Rowing", new Integer(3), true}, {"Sue", "Black", "Knitting", new Integer(2), false},
{"Jane", "White", "Speed reading", new Integer(20), true}, {"Joe", "Brown", "Pool", new Integer(10), false}};
public final Object[] longValues = {"Jane", "Kathy", "None of the above", new Integer(20), Boolean.TRUE};
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public int getRowCount() {
return data.length;
}
#Override
public String getColumnName(int col) {
return columnNames[col];
}
#Override
public Object getValueAt(int row, int col) {
return data[row][col];
}
#Override
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
#Override
public boolean isCellEditable(int row, int col) {
if (col < 2) {
return false;
} else {
return true;
}
}
#Override
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
System.out.println("New value of data: " + getValueAt(row, col));
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("TableRenderDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TableRenderDemo newContentPane = new TableRenderDemo();
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}

How to reset the JComboBox in JTable to the first value of the JComboBox

I'm working on a code in Java Swing. I have created a JComboBox in JTable. It's working :). But once I select a value and click on the save or cancel button, it has to reset to the default value (1st value in the combo box). I tried a lot of ways like combobox.setSelectedIndex(0). This isn't working.
Code:
String[] manTimeHr = { "00","01", "02", "03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23"};
String[] manTimeMin = {"00","01", "02", "03","04","05","06","07","08","09","10","11","12","13", "14", "15","16","17","18","19","20","21","22","23","24","25", "26", "27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59"};
String[][] data = {{"-select-","-select-"}};
String[] cols = {"Hrs","Mins"};
String[][] data1 = {{"-select-","-select-"}};
String[] cols1 = {"Hrs","Mins"};
JLabel manTimeStart = new JLabel("Start From",JLabel.LEFT);
STimeTbl = new JTable(data,cols);
hrsColumn=STimeTbl.getColumnModel().getColumn(0);
minsColumn=STimeTbl.getColumnModel().getColumn(1);
manSiteStimeHrCBx = new JComboBox(manTimeHr);
manSiteStimeHrCBx.setSelectedIndex(0);
hrsColumn.setCellEditor(new DefaultCellEditor(manSiteStimeHrCBx));
manSiteStimeMinCBx = new JComboBox(manTimeMin);
manSiteStimeMinCBx.setSelectedIndex(0);
minsColumn.setCellEditor(new DefaultCellEditor(manSiteStimeMinCBx));
JLabel manTimeEnd = new JLabel("End To",JLabel.LEFT);
ETimeTbl = new JTable(data1,cols1);
hrsColumn1=ETimeTbl.getColumnModel().getColumn(0);
minsColumn1=ETimeTbl.getColumnModel().getColumn(1);
manSiteEtimeHrCBx = new JComboBox(manTimeHr);
manSiteEtimeHrCBx.setSelectedIndex(0);
hrsColumn1.setCellEditor(new DefaultCellEditor(manSiteEtimeHrCBx));
manSiteEtimeMinCBx = new JComboBox(manTimeMin);
manSiteEtimeMinCBx.setSelectedIndex(0);
minsColumn1.setCellEditor(new DefaultCellEditor(manSiteEtimeMinCBx));
.
.
.
.
if("Save".equals(e.getActionCommand())) {
try{
mSHr = Integer.parseInt((String)manSiteStimeHrCBx.getSelectedItem());
mEHr=Integer.parseInt((String)manSiteEtimeHrCBx.getSelectedItem());
mSMin=Integer.parseInt((String)manSiteStimeMinCBx.getSelectedItem());
mEMin=Integer.parseInt((String)manServEtimeMinCBx.getSelectedItem());
}catch (Exception en){
System.out.println("Main Exception : "+ en);
return;
}
if(validateBlockTime(mSHr,mEHr,mSMin,mEMin) != true)
{
System.out.println("Enter valid Time");
return;
}
manSiteStimeHrCBx.setSelectedIndex(0);
manSiteStimeMinCBx.setSelectedIndex(0);
manSiteEtimeHrCBx.setSelectedIndex(0);
manSiteEtimeMinCBx.setSelectedIndex(0);
.
.
.
private static boolean validateBlockTime(int val3, int val4, int val5, int val6){
if(val4 > val3)
return true;
else if((val4 == val3) && (val6 > val5))
return true;
else
return false;
}
JTable tutorial contains description about Combo Box as an Editor
all data are stored in the XxxTableModel
all changes in the JTable view are described in Concepts: Editors and Renderers
then you have to know that in the XxxTableModel is stored only String value (or Double or Long or Integer or Icon, depends of value stored in ComboBoxModel) for Combo Box as an Editor
result is
quick code (sorry I'm so lazy) based on tutorial code
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import javax.swing.JButton;
public class TableRenderDemo extends JPanel {
private static final long serialVersionUID = 1L;
private boolean DEBUG = false;
public TableRenderDemo() {
super(new BorderLayout(5, 5));
final JTable table = new JTable(new MyTableModel());
table.setRowHeight(18);
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
initColumnSizes(table);
setUpSportColumn(table, table.getColumnModel().getColumn(2));
add(scrollPane);
JButton resetButton = new JButton("Reset to default");
resetButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < table.getRowCount(); i++) {
table.getModel().setValueAt("None of the above", i, 2);
}
}
});
add(resetButton, BorderLayout.SOUTH);
}
private void initColumnSizes(JTable table) {
MyTableModel model = (MyTableModel) table.getModel();
TableColumn column = null;
Component comp = null;
int headerWidth = 0;
int cellWidth = 0;
Object[] longValues = model.longValues;
TableCellRenderer headerRenderer = table.getTableHeader().getDefaultRenderer();
for (int i = 0; i < 5; i++) {
column = table.getColumnModel().getColumn(i);
comp = headerRenderer.getTableCellRendererComponent(null, column.getHeaderValue(), false, false, 0, 0);
headerWidth = comp.getPreferredSize().width;
comp = table.getDefaultRenderer(model.getColumnClass(i)).getTableCellRendererComponent(table, longValues[i], false, false, 0, i);
cellWidth = comp.getPreferredSize().width;
if (DEBUG) {
System.out.println("Initializing width of column " + i + ". " + "headerWidth = " + headerWidth + "; cellWidth = " + cellWidth);
}
column.setPreferredWidth(Math.max(headerWidth, cellWidth));
}
}
private void setUpSportColumn(JTable table, TableColumn sportColumn) {
JComboBox comboBox = new JComboBox();
comboBox.addItem("Snowboarding");
comboBox.addItem("Rowing");
comboBox.addItem("Knitting");
comboBox.addItem("Speed reading");
comboBox.addItem("Pool");
comboBox.addItem("None of the above");
sportColumn.setCellEditor(new DefaultCellEditor(comboBox));
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
sportColumn.setCellRenderer(renderer);
}
private class MyTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian"};
private Object[][] data = {
{"Kathy", "Smith", "Snowboarding", new Integer(5), false},
{"John", "Doe", "Rowing", new Integer(3), true},
{"Sue", "Black", "Knitting", new Integer(2), false},
{"Jane", "White", "Speed reading", new Integer(20), true},
{"Joe", "Brown", "Pool", new Integer(10), false}
};
public final Object[] longValues = {"Jane", "Kathy", "None of the above", new Integer(20), Boolean.TRUE};
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return data.length;
}
#Override
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
#Override
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
#Override
public boolean isCellEditable(int row, int col) {
if (col < 2) {
return false;
} else {
return true;
}
}
#Override
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
System.out.println(getValueAt(row, col));
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("TableRenderDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TableRenderDemo newContentPane = new TableRenderDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
output from AbstractTableModel, code line 135th.
run:
None of the above
None of the above
None of the above
None of the above
None of the above
BUILD SUCCESSFUL (total time: 37 seconds)

Categories