I want to gray non-editable cell in JTable.
I'm using such TableCellRenderer:
TableColumn column = table.getColumnModel().getColumn(0);
column.setCellRenderer(new GrayableCheckboxCellRenderer());
public class GrayableCheckboxCellRenderer extends JCheckBox implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int vRowIndex, int vColIndex) {
boolean editable = isEditable(vRowIndex, vColIndex);
setBackground(editable ? UIManager.getColor("Label.background") : Color.LIGHT_GRAY);
setSelected((Boolean) value);
if (isSelected) {
// TODO: cell (and perhaps other cells) are selected, need to highlight it
}
return this;
}
// perfomance
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {}
public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {}
public void revalidate() {}
public void validate() {}
}
This works but with one annoying artefact:
Initially "checkbox" is "left-arranged", when I press left mouse button it moves to "center-arranged" and when I release mouse button it moves back to "left-arranged".
How to avoid such annoying artefact and probably there are better simpler solution for my problem?
Return an instance of GrayableCheckboxCellRenderer in a TableCellEditor.
Addendum: Aesthetically, you may want to condition the renderer's and editor's colors based on the defaults provided by the current Look & Feel, for example:
Color hilite = UIManager.getColor("Table.selectionBackground");
simpliest way by using preparedRenderer
import java.awt.*;
import java.util.Random;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
public class Forum {
private JFrame frame = new JFrame("Frame");
private JPanel fatherCenter = new JPanel();
private JScrollPane tableScroll = new JScrollPane();
private myTableModel tableModel;
private JTable dialogTable;
private ListSelectionModel lsDialog;
private void addComponentsToPane(Container pane) {
tableModel = new myTableModel();
dialogTable = new JTable(tableModel) {
private static final long serialVersionUID = 1L;
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component comp = super.prepareRenderer(renderer, row, column);
JComponent jc = (JComponent) comp;//for Custom JComponent
if (!isRowSelected(row)) {
int modelRow = convertRowIndexToModel(row);
boolean type = (Boolean) getModel().getValueAt(modelRow, 2);
boolean type1 = (Boolean) getModel().getValueAt(modelRow, 3);
boolean type2 = (Boolean) getModel().isCellEditable(row, column);
comp.setForeground(Color.black);
if ((type) && (!type1)) {
comp.setBackground(Color.yellow);
} else if ((!type) && (type1)) {
comp.setBackground(Color.orange);
} else if ((!type) || (!type1)) {
comp.setBackground(Color.red);
//} else if ((!type2)) {
//comp.setForeground(Color.red);
//comp.setBackground(Color.magenta);
} else {
comp.setBackground(row % 2 == 0 ? getBackground() : getBackground().darker());
}
dialogTable.convertRowIndexToView(0);
} else {
comp.setForeground(Color.blue);
comp.setBackground(Color.lightGray);
}
if (!isCellEditable(row, column)) {
comp.setForeground(Color.red);
comp.setBackground(Color.magenta);
}
return comp;
}
};
tableScroll = new JScrollPane(dialogTable, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
tableScroll.setBorder(null);
dialogTable.getTableHeader().setReorderingAllowed(false);
dialogTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
lsDialog = dialogTable.getSelectionModel();
dialogTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
dialogTable.setRowHeight(20);
dialogTable.setRowMargin(2);
fatherCenter = new JPanel();
fatherCenter.setLayout(new BorderLayout(10, 10));
fatherCenter.add(tableScroll, BorderLayout.CENTER);
pane.add(fatherCenter);
}
private void addData() {
Runnable doRun1 = new Runnable() {
#Override
public void run() {
tableModel.resetTable();
Vector<String> tbl = new Vector<String>();
Vector<Object> tbl1 = new Vector<Object>();
Random rnd = new Random();
tbl.add("Integer");
tbl.add("Double");
tbl.add("Boolean");
tbl.add("Boolean");
tbl.add("String");
tableModel.setColumnNames(tbl);
for (int row = 0; row < 30; row++) {
tbl1 = null;
tbl1 = new Vector<Object>();
tbl1.addElement(row + 1);
tbl1.addElement(rnd.nextInt(25) + 3.14);
tbl1.addElement((row % 3 == 0) ? false : true);
tbl1.addElement((row % 5 == 0) ? false : true);
if (row % 7 == 0) {
tbl1.add(("Canc"));
} else if (row % 6 == 0) {
tbl1.add(("Del"));
} else {
tbl1.add(("New"));
}
tableModel.addRow(tbl1);
}
addTableListener();
}
};
SwingUtilities.invokeLater(doRun1);
}
private void addTableListener() {
tableModel.addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent tme) {
if (tme.getType() == TableModelEvent.UPDATE) {
System.out.println("Cell " + tme.getFirstRow() + ", "
+ tme.getColumn() + " changed. The new value: "
+ tableModel.getValueAt(tme.getFirstRow(),
tme.getColumn()));
}
}
});
}
private void createAndShowGUI() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout(10, 10));
addComponentsToPane(frame.getContentPane());
addData();
frame.setLocation(150, 150);
frame.setPreferredSize(new Dimension(400, 646));
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
Forum osFrame = new Forum();
}
public Forum() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
private class myTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private Vector<Vector<Object>> data;
private Vector<String> colNames;
private boolean[] _columnsVisible = {true, true, true, true, true};
myTableModel() {
this.colNames = new Vector<String>();
this.data = new Vector<Vector<Object>>();
}
myTableModel(Vector<String> colnames) {
this.colNames = colnames;
this.data = new Vector<Vector<Object>>();
}
public void resetTable() {
this.colNames.removeAllElements();
this.data.removeAllElements();
}
public void setColumnNames(Vector<String> colNames) {
this.colNames = colNames;
this.fireTableStructureChanged();
}
public void addRow(Vector<Object> data) {
this.data.add(data);
this.fireTableDataChanged();
this.fireTableStructureChanged();
}
public void removeRowAt(int row) {
this.data.removeElementAt(row);
this.fireTableDataChanged();
}
#Override
public int getColumnCount() {
return this.colNames.size();
}
#Override
public Class<?> getColumnClass(int colNum) {
switch (colNum) {
case 0:
return Integer.class;
case 1:
return Double.class;
case 2:
return Boolean.class;
case 3:
return Boolean.class;
default:
return String.class;
}
}
#Override
public boolean isCellEditable(int row, int colNum) {
switch (colNum) {
case 2:
return false;
default:
return true;
}
}
#Override
public String getColumnName(int colNum) {
return this.colNames.get(colNum);
}
#Override
public int getRowCount() {
return this.data.size();
}
#Override
public Object getValueAt(int row, int col) {
Vector<Object> value = this.data.get(row);
return value.get(col);
}
#Override
public void setValueAt(Object newVal, int row, int col) {
Vector<Object> aRow = data.elementAt(row);
aRow.remove(col);
aRow.insertElementAt(newVal, col);
fireTableCellUpdated(row, col);
}
public void setColumnVisible(int index, boolean visible) {
this._columnsVisible[index] = visible;
this.fireTableStructureChanged();
}
}
}
Just explicitly setting the alignment in the 'getTableCellRendererComponent()' method solves the problem. Add the below line before returning from the method.
setHorizontalAlignment(SwingConstants.CENTER);
Related
I am trying to disable selection of rows in all but 1 column in a JTable. (Layer Column in the example screenshot). In the other columns I have spinners and checkboxes that I want the user to be able to interact with, without effecting the selections in the Layer Column.
My initial attempt was to store up any selected rows as they occur, and then revert to that set of selected rows when a cell outside of column A is selected. It sort of works, but the problem is that it "flashes" when the other cell is selected, before it reverts it back. How can I prevent the "flash"?
Here is an example I set up to illustrate the problem:
public class TableTest {
static int[] selectedRows = new int[0];
final static String[] columns = new String[] { "Layer", "Enabled", "Read Only", "Storage" };
final static DefaultTableModel model = new DefaultTableModel(new Vector(), new Vector(Arrays.asList(columns))) {
#Override
public void setValueAt(Object obj, int row, int col) {
if (obj instanceof Boolean || obj instanceof Integer) {
Object localObject = super.getValueAt(row, col);
if (localObject instanceof Integer) {
Integer val = (Integer) localObject;
((SpinnerCell) obj).getSpinner().setValue(val);
} else if (localObject instanceof Boolean) {
Boolean val = (Boolean) localObject;
((CheckboxCell) obj).getCheckBox().setEnabled(val);
}
} else {
super.setValueAt(obj, row, col);
}
}
#Override
public boolean isCellEditable(int rowIndex, int colIndex) {
return colIndex != 0;
}
};
public static void main(String[] a) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTable table = new JTable(model) {
#Override
public TableCellRenderer getCellRenderer(final int rowIndex, int colIndex) {
int reaRowlIndex = convertRowIndexToModel(rowIndex);
int realColumnIndex = convertColumnIndexToModel(colIndex);
Object o = model.getValueAt(reaRowlIndex, realColumnIndex);
if (o instanceof TableCellRenderer) {
return (TableCellRenderer) o;
} else {
return super.getCellRenderer(reaRowlIndex, realColumnIndex);
}
}
//
#Override
public TableCellEditor getCellEditor(final int rowIndex, int colIndex) {
int reaRowlIndex = convertRowIndexToModel(rowIndex);
int realColumnIndex = convertColumnIndexToModel(colIndex);
Object o = model.getValueAt(reaRowlIndex, realColumnIndex);
if (o instanceof TableCellEditor) {
return (TableCellEditor) o;
} else {
return super.getCellEditor(reaRowlIndex, realColumnIndex);
}
}
};
table.getTableHeader().setReorderingAllowed(false);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent arg0) {
if (table.getSelectedColumn() == 0) {
selectedRows = table.getSelectedRows();
System.out.println("Selected Rows before " + Arrays.toString(selectedRows));
}
}
});
final ListSelectionModel columnListSelectionModel = table.getColumnModel().getSelectionModel();
columnListSelectionModel.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if (table.getSelectedColumn() != 0) {
table.clearSelection();
System.out.println("Selected Rows during " + Arrays.toString(table.getSelectedRows()));
for (int i = 0; i < selectedRows.length; i++) {
table.getSelectionModel().addSelectionInterval(selectedRows[i], selectedRows[i]);
}
System.out.println("Selected Rows after " + Arrays.toString(table.getSelectedRows()));
}
}
});
model.addRow(new Object[] { "Bird", new CheckboxCell(new JCheckBox()),
new CheckboxCell(new JCheckBox()), new SpinnerCell(new JSpinner()) });
model.addRow(new Object[] { "Cat", new CheckboxCell(new JCheckBox()), new CheckboxCell(new JCheckBox()),
new SpinnerCell(new JSpinner()) });
model.addRow(new Object[] { "Dog", new CheckboxCell(new JCheckBox()), new CheckboxCell(new JCheckBox()),
new SpinnerCell(new JSpinner()) });
model.addRow(new Object[] { "Fish", new CheckboxCell(new JCheckBox()),
new CheckboxCell(new JCheckBox()), new SpinnerCell(new JSpinner()) });
model.addRow(new Object[] { "Pig", new CheckboxCell(new JCheckBox()), new CheckboxCell(new JCheckBox()),
new SpinnerCell(new JSpinner()) });
frame.add(new JScrollPane(table));
frame.setSize(300, 200);
frame.setVisible(true);
}
});
}
static class CheckboxCell extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private static final long serialVersionUID = 1L;
private JCheckBox checkBox;
public CheckboxCell(JCheckBox inputCheckBox) {
checkBox = inputCheckBox;
}
#Override
public Object getCellEditorValue() {
return checkBox.isSelected();
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row,
int column) {
return checkBox;
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
return checkBox;
}
public JCheckBox getCheckBox() {
return checkBox;
}
#Override
public boolean isCellEditable(EventObject evt) {
return true;
}
public String toString() {
return checkBox.isSelected() + "";
}
}
static class SpinnerCell extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private static final long serialVersionUID = 1L;
private JSpinner editSpinner, renderSpinner;
public SpinnerCell() {
editSpinner = new JSpinner();
JTextField tf = ((JSpinner.DefaultEditor) editSpinner.getEditor()).getTextField();
tf.setForeground(Color.black);
renderSpinner = new JSpinner();
JTextField tf2 = ((JSpinner.DefaultEditor) renderSpinner.getEditor()).getTextField();
tf2.setForeground(Color.black);
}
public SpinnerCell(JSpinner showSpinner) {
editSpinner = showSpinner;
JTextField tf = ((JSpinner.DefaultEditor) editSpinner.getEditor()).getTextField();
tf.setForeground(Color.black);
renderSpinner = showSpinner;
JTextField tf2 = ((JSpinner.DefaultEditor) renderSpinner.getEditor()).getTextField();
tf2.setForeground(Color.black);
}
#Override
public Object getCellEditorValue() {
return editSpinner.getValue();
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row,
int column) {
return editSpinner;
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
return renderSpinner;
}
public String toString() {
return editSpinner.getValue().toString();
}
public JSpinner getSpinner() {
return editSpinner;
}
#Override
public boolean isCellEditable(EventObject evt) {
return true;
}
}
}
Here's my short example:
Override JTable#changeSelection(...)
table.setCellSelectionEnabled(true);
Override ListSelectionModel#isSelectedIndex(...)
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableTest2 {
public JComponent makeUI() {
String[] columnNames = {"Layer", "Enabled", "Read Only"};
Object[][] data = {
{"Bird", true, false}, {"Cat", true, false},
{"Dog", true, false}, {"Fish", true, false}, {"Pig", true, false}
};
TableModel model = new DefaultTableModel(data, columnNames) {
#Override public Class<?> getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
#Override public boolean isCellEditable(int row, int col) {
return col != 0;
}
};
JTable table = new JTable(model) {
#Override public void changeSelection(
int rowIndex, int columnIndex, boolean toggle, boolean extend) {
if (convertColumnIndexToModel(columnIndex) != 0) {
return;
}
super.changeSelection(rowIndex, columnIndex, toggle, extend);
}
};
table.setAutoCreateRowSorter(true);
table.setCellSelectionEnabled(true);
table.getColumnModel().setSelectionModel(new DefaultListSelectionModel() {
#Override public boolean isSelectedIndex(int index) {
return table.convertColumnIndexToModel(index) == 0;
}
});
return new JScrollPane(table);
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new TableTest2().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
If you want to prevent the flash you need to intercept an event before the selection is made because table.getSelectedColumn() only works after a selection has been made and you will always see that selection flash.
You could use a key listener to check for "Right Arrow", "Number Pad Right" and "End" key presses and a mouse clicked listener to check where the user is clicking and then change the event to instead select column A only.
For example see this answer showing how to check where a user clicks the mouse before a selection is made: https://stackoverflow.com/a/7351053/1270000
Then you just need to add some code to select the correct cell in column A instead, and don't forget to consume the event "e.consume()" to prevent the original event from completing with the wrong user selection.
Haven't tried it but you might be able to use a custom ListSelectionModel.
Here is an example that lets you toggle the selection of a row on/off:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ToggleListSelectionModel extends DefaultListSelectionModel
{
#Override
public void setSelectionInterval(int index0, int index1)
{
// Select multiple lines
if (index0 != index1)
{
super.addSelectionInterval(index0, index1);
return;
}
// Toggle selection of a single line
if (super.isSelectedIndex(index0))
{
super.removeSelectionInterval(index0, index0);
}
else
{
super.addSelectionInterval(index0, index0);
}
}
private static void createAndShowGUI()
{
String[] numbers = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
final JList<String> list = new JList<String>( numbers );
list.setVisibleRowCount( numbers.length );
list.setSelectionModel(new ToggleListSelectionModel());
// list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
JButton clear = new JButton("Clear");
clear.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
list.clearSelection();
}
});
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(list), BorderLayout.CENTER);
frame.add(clear, BorderLayout.PAGE_END);
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
In your case I guess you would need access to the table so you can use the getSelectedColumn() method.
You would remove the logic from the example above and replace it with something like:
if (table.getSelectedColumn() == 0)
super.setSelectionInterval(index0, index1);
I have been thinking a lot to solve this mistake. But unfortunately I came to final cnclusion that I need help of professionals.
Please, copy,paste this code to see issue:
public class DateFormatDemo extends JFrame
{
private JTable dataSearchResultTable;
public DateFormatDemo()
{
JButton updateTable = new JButton("Update table");
updateTable.setMaximumSize(updateTable.getPreferredSize());
updateTable.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
updateMyTableModel();
}
});
JPanel panel = new JPanel(new GridLayout(2, 1, 5, 10));
panel.setPreferredSize(new Dimension(500, 300));
panel.add(new JScrollPane(initDataSearchResultTable()));
panel.add(updateTable);
super.getContentPane().add(panel);
super.pack();
super.setDefaultCloseOperation(EXIT_ON_CLOSE);
super.setVisible(true);
}
private JTable initDataSearchResultTable()
{
dataSearchResultTable = new JTable();
// dataSearchResultTable.setAutoCreateColumnsFromModel(false);
dataSearchResultTable.setSelectionBackground(new Color(0xaaaaff));
dataSearchResultTable.setFillsViewportHeight(true);
dataSearchResultTable.setRowSelectionAllowed(true);
dataSearchResultTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
dataSearchResultTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
return dataSearchResultTable;
}
void updateMyTableModel()
{
TableModel tableModel = dataSearchResultTable.getModel();
TableColumnModel columnModel = dataSearchResultTable.getColumnModel();
if (tableModel instanceof MyTableModel) {
((MyTableModel) tableModel).updateModel();
this.initColumnWidths(tableModel, columnModel);
} else {
tableModel = new MyTableModel();
dataSearchResultTable.setModel(tableModel);
this.makeColumnsNotResizable(columnModel);
this.initColumnWidths(tableModel, columnModel);
}
}
private void makeColumnsNotResizable(TableColumnModel columnModel)
{
for (int i = 0; i < columnModel.getColumnCount(); i++) {
if (i == 0 || i == 1) {
columnModel.getColumn(i).setResizable(false);
}
}
}
private void initColumnWidths(TableModel tableModel, TableColumnModel columnModel)
{
TableColumn column = null;
Component comp = null;
int cellWidth = 0;
int headerWidth = 0;
TableCellRenderer headerRenderer = dataSearchResultTable.getTableHeader().getDefaultRenderer();
for (int i = 0; i < columnModel.getColumnCount(); i++) {
column = columnModel.getColumn(i);
comp = headerRenderer.getTableCellRendererComponent(null, column.getHeaderValue(), false, false, -1, 0);
headerWidth = comp.getPreferredSize().width;
Class<?> columnClass = tableModel.getColumnClass(i);
for (int j = 0; j < tableModel.getRowCount(); j++) {
comp = dataSearchResultTable.getDefaultRenderer(columnClass).getTableCellRendererComponent(
dataSearchResultTable, tableModel.getValueAt(j, i), false, false, j, i);
int width = comp.getPreferredSize().width;
// we cache width of first row. And compare widths of next
// rows with width of first.
// If some row has greater width it becomes width of whole
// row(unless header has greater width)
if (cellWidth < width || j == 0) {
cellWidth = width;
}
}
System.out
.println("columnClass=" + columnClass + ",headerWidth=" + headerWidth + ",cellWidth=" + cellWidth);
if (headerWidth > cellWidth) {
TableCellRenderer centeredRenderer = dataSearchResultTable.getDefaultRenderer(columnClass);
if (centeredRenderer instanceof DefaultTableCellRenderer) {
((DefaultTableCellRenderer) centeredRenderer).setHorizontalAlignment(SwingConstants.CENTER);
column.setCellRenderer(centeredRenderer);
column.setPreferredWidth(headerWidth);
}
} else {
column.setPreferredWidth(cellWidth + 5);
}
}
}
class MyTableModel extends AbstractTableModel
{
private String[] columnNames = { "First Name", "Last Name", "Timestamp", "Number", "Vegetarian" };
private Object[][] data = new Object[5][];
void updateModel()
{
data = new Object[][] {
{ "Vova", "KipokKipokKipokKipok", "2013-04-12 11:20:41", new Integer(5), new Boolean(true) },
{ "Olia", "Duo", "2010-01-11 11:11:41", new Integer(3), new Boolean(false) },
{ "Oksana", "Stack", "2012-04-12 11:20:41", new Integer(2), new Boolean(false) },
{ "Petro", "White", "2010-04-12 11:20:21", new Integer(20), new Boolean(true) },
{ "Ivan", "Brown", "2011-04-11 11:20:41", new Integer(10), new Boolean(true) } };
fireTableDataChanged();
}
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)
{
if (data.length > 0 && data[0] != null) {
return data[row][col];
}
return null;
}
/*
* 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.
*/
public Class getColumnClass(int c)
{
Object valueAt = getValueAt(0, c);
return valueAt == null ? Object.class : valueAt.getClass();
}
/*
* 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.
if (col < 2) {
return false;
} else {
return true;
}
}
/*
* Don't need to implement this method unless your table's data can
* change.
*/
public void setValueAt(Object value, int row, int col)
{
if (data.length > 0 && data[0] != null) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
}
}
public static void main(String[] args) throws ParseException
{
new DateFormatDemo();
}
}
Now please click twice on that big button called 'Update Table'. As you see column that should display checkbox as it holds boolean values do not do that but instead displays String true or false.
This code emulates my real workflow.
So, how to update tablemodel to have boolean columns with checkbozes.
Thanks!
take this as simple start point
import java.awt.*;
import java.util.Random;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
public class Forum implements ListSelectionListener {
private JFrame frame = new JFrame("Frame");
private JPanel fatherCenter = new JPanel();
private JScrollPane tableScroll = new JScrollPane();
private MyTableModel tableModel;
private JTable dialogTable;
private ListSelectionModel lsDialog;
private Color clr;
private Color clr1;
private void addData() {
Runnable doRun1 = new Runnable() {
#Override
public void run() {
tableModel.resetTable();
Vector<String> tbl = new Vector<String>();
Vector<Object> tbl1 = new Vector<Object>();
Random rnd = new Random();
tbl.add("Integer");
tbl.add("Double");
tbl.add("Boolean");
tbl.add("Boolean");
tbl.add("String");
tableModel.setColumnNames(tbl);
for (int row = 0; row < 30; row++) {
tbl1 = null;
tbl1 = new Vector<Object>();
tbl1.addElement(row + 1);
tbl1.addElement(rnd.nextInt(25) + 3.14);
tbl1.addElement((row % 3 == 0) ? false : true);
tbl1.addElement((row % 5 == 0) ? false : true);
if (row % 7 == 0) {
tbl1.add(("Canc"));
} else if (row % 6 == 0) {
tbl1.add(("Del"));
} else {
tbl1.add(("New"));
}
tableModel.addRow(tbl1);
}
addTableListener();
}
};
SwingUtilities.invokeLater(doRun1);
}
private void addTableListener() {
tableModel.addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent tme) {
if (tme.getType() == TableModelEvent.UPDATE) {
System.out.println("");
System.out.println("Cell " + tme.getFirstRow() + ", "
+ tme.getColumn() + " changed. The new value: "
+ tableModel.getValueAt(tme.getFirstRow(),
tme.getColumn()));
}
}
});
}
#Override
public void valueChanged(ListSelectionEvent le) {
int row = dialogTable.getSelectedRow();
int col = dialogTable.getSelectedColumn();
String str = "Selected Row(s): ";
int[] rows = dialogTable.getSelectedRows();
for (int i = 0; i < rows.length; i++) {
str += rows[i] + " ";
}
str += "Selected Column(s): ";
int[] cols = dialogTable.getSelectedColumns();
for (int i = 0; i < cols.length; i++) {
str += cols[i] + " ";
}
str += "Selected Cell: " + dialogTable.getSelectedRow() + ", " + dialogTable.getSelectedColumn();
System.out.println(str);
Object value = dialogTable.getValueAt(row, col);
System.out.println(String.valueOf(value));
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Forum osFrame = new Forum();
}
});
}
public Forum() {
tableModel = new MyTableModel();
dialogTable = new JTable(tableModel) {
private static final long serialVersionUID = 1L;
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component comp = super.prepareRenderer(renderer, row, column);
JComponent jc = (JComponent) comp;//for Custom JComponent
if (!isRowSelected(row)) {
int modelRow = convertRowIndexToModel(row);
boolean type = (Boolean) getModel().getValueAt(modelRow, 2);
boolean type1 = (Boolean) getModel().getValueAt(modelRow, 3);
comp.setForeground(Color.black);
if ((type) && (!type1)) {
comp.setBackground(clr1);
} else if ((!type) && (type1)) {
comp.setBackground(Color.orange);
} else if ((!type) || (!type1)) {
comp.setBackground(Color.red);
} else {
comp.setBackground(row % 2 == 0 ? getBackground() : getBackground().darker());
}
dialogTable.convertRowIndexToView(0);
} else {
comp.setForeground(Color.blue);
}
if (!isCellEditable(row, column)) {
comp.setForeground(Color.red);
comp.setBackground(Color.magenta);
}
return comp;
}
};
tableScroll = new JScrollPane(dialogTable, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
tableScroll.setBorder(null);
dialogTable.getTableHeader().setReorderingAllowed(false);
dialogTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
lsDialog = dialogTable.getSelectionModel();
dialogTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
dialogTable.setRowHeight(20);
dialogTable.setRowMargin(2);
dialogTable.setPreferredScrollableViewportSize(dialogTable.getPreferredSize());
ListSelectionModel rowSelMod = dialogTable.getSelectionModel();
//ListSelectionModel colSelMod = dialogTable.getColumnModel().getSelectionModel();
rowSelMod.addListSelectionListener(this);
//colSelMod.addListSelectionListener(this);
fatherCenter = new JPanel();
fatherCenter.setLayout(new BorderLayout(10, 10));
fatherCenter.add(tableScroll, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout(10, 10));
frame.add(fatherCenter);
frame.setPreferredSize(new Dimension(400, 660));
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
addData();
}
private class MyTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private Vector<Vector<Object>> _data;
private Vector<String> _colNames;
private boolean[] _columnsVisible = {true, true, true, true, true};
public MyTableModel() {
_colNames = new Vector<String>();
_data = new Vector<Vector<Object>>();
}
public MyTableModel(Vector<String> colnames) {
_colNames = colnames;
_data = new Vector<Vector<Object>>();
}
public void resetTable() {
_colNames.removeAllElements();
_data.removeAllElements();
}
public void setColumnNames(Vector<String> colNames) {
_colNames = colNames;
fireTableStructureChanged();
}
public void addRow(Vector<Object> data) {
_data.add(data);
fireTableRowsInserted(_data.size() - 1, _data.size() - 1);
}
public void removeRowAt(int row) {
_data.removeElementAt(row);
fireTableRowsDeleted(row - 1, _data.size() - 1);
}
#Override
public int getColumnCount() {
return _colNames.size();
}
#Override
public Class<?> getColumnClass(int colNum) {
switch (colNum) {
case 0:
return Integer.class;
case 1:
return Double.class;
case 2:
return Boolean.class;
case 3:
return Boolean.class;
default:
return String.class;
}
}
#Override
public boolean isCellEditable(int row, int colNum) {
switch (colNum) {
case 2:
return false;
default:
return true;
}
}
#Override
public String getColumnName(int colNum) {
return _colNames.get(colNum);
}
#Override
public int getRowCount() {
return _data.size();
}
#Override
public Object getValueAt(int row, int col) {
Vector<Object> value = _data.get(row);
return value.get(col);
}
#Override
public void setValueAt(Object newVal, int row, int col) {
Vector<Object> aRow = _data.elementAt(row);
aRow.remove(col);
aRow.insertElementAt(newVal, col);
fireTableCellUpdated(row, col);
}
public void setColumnVisible(int index, boolean visible) {
_columnsVisible[index] = visible;
fireTableStructureChanged();
}
}
}
Your problem in getColumnClass method as you see you also return Object because of that you also get String columns.
You can determine that method in next way:
#Override
public Class<?> getColumnClass(int arg0) {
return longValues[arg0].getClass();
}
Or return Classes for your columns in another way. But you must to determine this Classes while cunstruct your model.
I need some help for my problem. I have a table with e.g. a double column and a string column. If the value in the double column is negativ, the string should be "negativ". And the other way if the value is positiv, the string should be "positiv".
The problem is now if I edit the double value in the jTable, the string should also be updated.
Update to my question, the actual code look like this:
But it doesn't work, because the string in the second column wont be updated after I edit the first column value. It only works when I start the program the first time.
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;
public class ExampleRemoveAddRows extends JFrame {
private Object[] columnNames = {"Double", "positiv / negativ"};
private Object[][] data = {
{new Double(10.0), "positiv"},
{new Double(-10.0), "negativ"},
{new Double(20.0), "positiv"},
{new Double(-30.0), "negativ"}
};
private JTable table;
private DefaultTableModel model;
public ExampleRemoveAddRows() {
model = new DefaultTableModel(data, columnNames) {
#Override
public Class getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
#Override
public Object getValueAt(int row, int column) {
if (column == 1) {
double number = Double.parseDouble(this.getValueAt(row, 0).toString());
System.out.println(number);
System.out.println("good");
System.out.println((number < 0) ? "negativ" : "positiv");
return "C: "+ this.getValueAt(row, 0);//((number < 0) ? "negativ" : "positiv");
} else {
return super.getValueAt(row, column);
}
}
};
table = new JTable(model);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ExampleRemoveAddRows frame = new ExampleRemoveAddRows();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Thanks for your help.
Sam
I've revised your sscce to show the alternate approach suggested here. Note the alternate ways to get a Double constant. I've also re-factored the String constrants.
Addendum: In helpful comments, #kleopatra observes that querying the model directly will always produce the correct result, but a TableModelListener will only see changes to column 0, not column 1. The simple expedient is to make column 1 non-editable, as its value depends completely on column 0.
#Override
public boolean isCellEditable(int row, int col) {
return col == 0;
}
The first example below uses DefaultTableModel:
import javax.swing.*;
import javax.swing.table.*;
/** #see https://stackoverflow.com/a/13628183/230513 */
public class ExampleRemoveAddRows extends JFrame {
public static final String NEGATIVE = "negativ";
public static final String POSITIVE = "positiv";
private Object[] columnNames = {"Double", POSITIVE + " / " + NEGATIVE};
private Object[][] data = {
{10d, null},
{-10.0, null},
{Double.valueOf(30), null},
{Double.valueOf("-30"), null}
};
private JTable table;
private DefaultTableModel model;
public ExampleRemoveAddRows() {
model = new DefaultTableModel(data, columnNames) {
#Override
public Class getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
#Override
public boolean isCellEditable(int row, int col) {
return col == 0;
}
#Override
public Object getValueAt(int row, int col) {
if (col == 1) {
double number = (Double) this.getValueAt(row, 0);
return (number < 0) ? NEGATIVE : POSITIVE;
} else {
return super.getValueAt(row, col);
}
}
#Override
public void setValueAt(Object aValue, int row, int col) {
super.setValueAt(aValue, row, col);
fireTableCellUpdated(row, 1); // may have changed
}
};
table = new JTable(model);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ExampleRemoveAddRows frame = new ExampleRemoveAddRows();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
This variation extends AbstractTableModel:
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.table.*;
/**
* #see https://stackoverflow.com/a/13628183/230513
*/
public class ExampleRemoveAddRows extends JFrame {
public static final String NEGATIVE = "negativ";
public static final String POSITIVE = "positiv";
public ExampleRemoveAddRows() {
DoubleModel model = new DoubleModel();
model.add(10.1);
model.add(-10.2);
model.add(Double.valueOf(30.1));
model.add(Double.valueOf("-30.2"));
JTable table = new JTable(model);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ExampleRemoveAddRows frame = new ExampleRemoveAddRows();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private class DoubleModel extends AbstractTableModel {
List<Double> data = new ArrayList<Double>();
public void add(Double d) {
data.add(d);
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return 2;
}
#Override
public String getColumnName(int col) {
if (col == 0) {
return "Double";
} else {
return POSITIVE + " / " + NEGATIVE;
}
}
#Override
public Class<?> getColumnClass(int col) {
if (col == 0) {
return Double.class;
} else {
return String.class;
}
}
#Override
public boolean isCellEditable(int row, int col) {
return col == 0;
}
#Override
public Object getValueAt(int row, int col) {
if (col == 0) {
return data.get(row);
} else {
double number = (Double) this.getValueAt(row, 0);
return (number < 0) ? NEGATIVE : POSITIVE;
}
}
#Override
public void setValueAt(Object aValue, int row, int col) {
if (col == 0) {
data.set(row, (Double) aValue);
fireTableRowsUpdated(row, row);
}
}
}
}
You do indeed have access to the TableModel, if I'm not mistaken, through TableModelEvent.getSource().
Just to provide a basic example (mostly because the one sentance answer hardly seems like much of an answer):
TableModel model = (TableModel)te.getSource();
Double number = model.getValueAt(te.firstRow, 0);
model.setValueAt(((number < 0) ? "negativ":"positiv"), te.firstRow, 1);
How can I have a JTable with both columns & rows have title?
something like this:
+------+------+------+------+
|/\/\/\| col1 | col2 | col3 |
+------+------+------+------+
| row1 | | | |
+------+------+------+------+
| row2 | | | |
+------+------+------+------+
| row3 | | | |
+------+------+------+------+
Thanks
I think that you searching RowTable
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.UIManager.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class JTableRowHeader {
private JFrame frame = new JFrame("JTable RowHeader");
private JScrollPane scrollPane;
private JTable table;
private DefaultTableModel model;
private TableRowSorter<TableModel> sorter;
private JTable headerTable;
public JTableRowHeader() {
table = new JTable(4, 4);
for (int i = 0; i < table.getRowCount(); i++) {
table.setValueAt(i, i, 0);
}
sorter = new TableRowSorter<TableModel>(table.getModel());
table.setRowSorter(sorter);
model = new DefaultTableModel() {
private static final long serialVersionUID = 1L;
#Override
public int getColumnCount() {
return 1;
}
#Override
public boolean isCellEditable(int row, int col) {
return false;
}
#Override
public int getRowCount() {
return table.getRowCount();
}
#Override
public Class<?> getColumnClass(int colNum) {
switch (colNum) {
case 0:
return String.class;
default:
return super.getColumnClass(colNum);
}
}
};
headerTable = new JTable(model);
for (int i = 0; i < table.getRowCount(); i++) {
headerTable.setValueAt("Row " + (i + 1), i, 0);
}
headerTable.setShowGrid(false);
headerTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
headerTable.setPreferredScrollableViewportSize(new Dimension(50, 0));
headerTable.getColumnModel().getColumn(0).setPreferredWidth(50);
headerTable.getColumnModel().getColumn(0).setCellRenderer(new TableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable x, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
boolean selected = table.getSelectionModel().isSelectedIndex(row);
Component component = table.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(table, value, false, false, -1, -2);
((JLabel) component).setHorizontalAlignment(SwingConstants.CENTER);
if (selected) {
component.setFont(component.getFont().deriveFont(Font.BOLD));
component.setForeground(Color.red);
} else {
component.setFont(component.getFont().deriveFont(Font.PLAIN));
}
return component;
}
});
table.getRowSorter().addRowSorterListener(new RowSorterListener() {
#Override
public void sorterChanged(RowSorterEvent e) {
model.fireTableDataChanged();
}
});
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
model.fireTableRowsUpdated(0, model.getRowCount() - 1);
}
});
scrollPane = new JScrollPane(table);
scrollPane.setRowHeaderView(headerTable);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(scrollPane);
frame.add(new JButton(new AbstractAction("Toggle filter") {
private static final long serialVersionUID = 1L;
private RowFilter<TableModel, Object> filter = new RowFilter<TableModel, Object>() {
#Override
public boolean include(javax.swing.RowFilter.Entry<? extends TableModel, ? extends Object> entry) {
return ((Number) entry.getValue(0)).intValue() % 2 == 0;
}
};
#Override
public void actionPerformed(ActionEvent e) {
if (sorter.getRowFilter() != null) {
sorter.setRowFilter(null);
} else {
sorter.setRowFilter(filter);
}
}
}), BorderLayout.SOUTH);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
public static void main(String[] args) {
try {// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if (info.getName().equals("Nimbus")) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
//e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JTableRowHeader TestTableRowHeader = new JTableRowHeader();
}
});
}
}
Row header and table value are desynchronized in solution from mKorbel. The table displays Row 1 and Row 2 instead of Row 1 and Row 3 when filtered.
Here is a solution based on his example. It duplicates row header into a new column in the table, hide this column and copy values to the other one when filtered.
It works and it's ugly, we need a better solution from someone :)
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.UIManager.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class JTableRowHeader {
private JFrame frame = new JFrame("JTable RowHeader");
private JScrollPane scrollPane;
private JTable table;
private DefaultTableModel model;
private TableRowSorter<TableModel> sorter;
private JTable headerTable;
public JTableRowHeader() {
table = new JTable(4, 5);
for (int i = 0; i < table.getRowCount(); i++) {
table.setValueAt("Row " + (i + 1), i, 0);
table.setValueAt(i, i, 1);
}
sorter = new TableRowSorter<TableModel>(table.getModel());
table.setRowSorter(sorter);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
model = new DefaultTableModel() {
private static final long serialVersionUID = 1L;
#Override
public int getColumnCount() {
return 1;
}
#Override
public boolean isCellEditable(int row, int col) {
return false;
}
#Override
public int getRowCount() {
return table.getRowCount();
}
#Override
public Class<?> getColumnClass(int colNum) {
switch (colNum) {
case 0:
return String.class;
default:
return super.getColumnClass(colNum);
}
}
};
headerTable = new JTable(model);
for (int i = 0; i < table.getRowCount(); i++) {
headerTable.setValueAt("Row " + (i + 1), i, 0);
}
headerTable.setShowGrid(false);
headerTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
headerTable.setPreferredScrollableViewportSize(new Dimension(50, 0));
headerTable.getColumnModel().getColumn(0).setPreferredWidth(50);
headerTable.getColumnModel().getColumn(0).setCellRenderer(new TableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable x, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
boolean selected = table.getSelectionModel().isSelectedIndex(row);
Component component = table.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(table, value, false, false, -1, -2);
((JLabel) component).setHorizontalAlignment(SwingConstants.CENTER);
if (selected) {
component.setFont(component.getFont().deriveFont(Font.BOLD));
component.setForeground(Color.red);
} else {
component.setFont(component.getFont().deriveFont(Font.PLAIN));
}
return component;
}
});
table.getRowSorter().addRowSorterListener(new RowSorterListener() {
#Override
public void sorterChanged(RowSorterEvent e) {
model.fireTableDataChanged();
for (int i = 0; i < table.getRowCount(); i++) {
headerTable.setValueAt(table.getValueAt(i, 0), i, 0);
}
}
});
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
model.fireTableRowsUpdated(0, model.getRowCount() - 1);
}
});
TableColumnModel columnModel = table.getColumnModel();
TableColumn column = columnModel.getColumn(0);
column.setMinWidth(0);
column.setMaxWidth(0);
column.setPreferredWidth(0);
AdjusterTableColumn columnAdjuster = new AdjusterTableColumn(table);
columnAdjuster.adjustColumns();
scrollPane = new JScrollPane(table);
scrollPane.setRowHeaderView(headerTable);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(scrollPane);
frame.add(new JButton(new AbstractAction("Toggle filter") {
private static final long serialVersionUID = 1L;
private RowFilter<TableModel, Object> filter = new RowFilter<TableModel, Object>() {
#Override
public boolean include(javax.swing.RowFilter.Entry<? extends TableModel, ? extends Object> entry) {
return ((Number) entry.getValue(1)).intValue() % 2 == 0;
}
};
#Override
public void actionPerformed(ActionEvent e) {
if (sorter.getRowFilter() != null) {
sorter.setRowFilter(null);
} else {
sorter.setRowFilter(filter);
}
}
}), BorderLayout.SOUTH);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
public static void main(String[] args) {
try {// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if (info.getName().equals("Nimbus")) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
//e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JTableRowHeader TestTableRowHeader = new JTableRowHeader();
}
});
}
}
Since JTable could be sorted.
How do I set it auto select the last inserted row whenever a row is inserted?
Thanks
your TableModel can retun number of rows, and new/added could be last by using convertRowIndexToView you can get row in TableView, then pass to the changeSelection
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend)
EDIT: example (for enjoy harcoded numbersOfRows - 3 instead of correct numbersOfRows - 1):
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.event.*;
import javax.swing.table.*;
public class TestTableRowTable {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if (info.getName().equals("Nimbus")) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
final JTable table = new JTable(10, 6);
for (int i = 0; i < table.getRowCount(); i++) {
table.setValueAt(i, i, 0);
}
final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel());
table.setRowSorter(sorter);
final AbstractTableModel model = new AbstractTableModel() {
private static final long serialVersionUID = 1L;
#Override
public int getColumnCount() {
return 1;
}
#Override
public Object getValueAt(int row, int column) {
return table.convertRowIndexToModel(row);
}
#Override
public int getRowCount() {
return table.getRowCount();
}
};
JTable headerTable = new JTable(model);
headerTable.setShowGrid(false);
headerTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
headerTable.setPreferredScrollableViewportSize(new Dimension(30, 0));
headerTable.getColumnModel().getColumn(0).setPreferredWidth(30);
headerTable.getColumnModel().getColumn(0).setCellRenderer(new TableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable x, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
boolean selected = table.getSelectionModel().isSelectedIndex(row);
Component component = table.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(table, value, false, false, -1, -2);
((JLabel) component).setHorizontalAlignment(JLabel.CENTER);
if (selected) {
component.setFont(component.getFont().deriveFont(Font.BOLD));
} else {
component.setFont(component.getFont().deriveFont(Font.PLAIN));
}
return component;
}
});
table.getRowSorter().addRowSorterListener(
new RowSorterListener() {
#Override
public void sorterChanged(RowSorterEvent e) {
model.fireTableDataChanged();
}
});
table.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
model.fireTableRowsUpdated(0, model.getRowCount() - 1);
}
});
JScrollPane pane = new JScrollPane(table);
pane.setRowHeaderView(headerTable);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(pane);
frame.getContentPane().add(new JButton(new AbstractAction("Toggle filter") {
private static final long serialVersionUID = 1L;
private RowFilter<TableModel, Object> filter = new RowFilter<TableModel, Object>() {
#Override
public boolean include(javax.swing.RowFilter.Entry<? extends TableModel, ? extends Object> entry) {
return ((Number) entry.getValue(0)).intValue() % 2 == 0;
//return ((String) entry.getValue(0)).length()>0 ;
//return ((Date) entry.getValue(0)).getTime()< ;
}
};
#Override
public void actionPerformed(ActionEvent e) {
if (sorter.getRowFilter() != null) {
sorter.setRowFilter(null);
TableModel tblModel = table.getModel();
int numbersOfRows = 0;
numbersOfRows = tblModel.getRowCount();
int lastRow = 0;
lastRow = table.convertRowIndexToView(numbersOfRows - 3);
table.changeSelection(lastRow, 0, false, false);
} else {
sorter.setRowFilter(filter);
}
}
}), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private TestTableRowTable() {
}
}
It is hard to answer,because you haven't provided any code, but, if you use some model of JTable you can write some adapter for method insert, I mean for public void insertRow(int row, Vector rowData). Here is present number of row, using this number you can select row. Do you know how to select row ?