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 am trying to add a one row JTable on top of an existing JTable which is usually created dynamically and which changes its data model quite often.
As you can see the yellow area represents just a row counter and It has been created using this source
The yellow column, therefore has been attached to the main table using the following code:
JTable rowTable = new RowNumberTable(table);
scrollTable.setRowHeaderView(rowTable);
The table columns A, B, C, and so on, if clicked, sort the JTable accordingly and this feature should be maintained (I do not want to put the JCombobox in the table header unless there is a clever way of doing both things).
My aim is to create a JTable with one row (See red row) which has as many columns as the main JTable
EDIT
Here there is the SSCCE
I would like to put JComboBoxes on top of A,B,C,D.....
The class that renders the JComboBoxes is ColumnJComboBoxTable which is called in TableDemo as follow:
//Column JCombobox
JTable columnTable = new ColumnJComboBoxTable(table);
scrollTable.setColumnHeaderView(columnTable);
Right now it is not working as I want (Well, It is not working at all)
Buttons at the top add and remove columns. Therefore if a column is deleted the respective JComboBox must be deleted too.
CODE
TableDemo
package com.table;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.AbstractAction;
public class TableDemo extends JFrame
{
private static final long serialVersionUID = 1L;
public TableDemo()
{
super("TableDemo");
Object[][] data =
{
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
{"0","1","2","3","4","5","6","7","8","9","10"},
};
String[] columnNames =
{
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
};
final JTable table = new JTable(data, columnNames);
new JPopupMenu();
final JToolBar toolBar = new JToolBar();
final XTableColumnModel columnModel = new XTableColumnModel();
table.setColumnModel(columnModel);
table.createDefaultColumnsFromModel();
toolBar.add(new JButton(new AbstractAction("ALL") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
columnModel.setAllColumnsVisible();
}
}));
toolBar.add(new JButton(new AbstractAction("Column 0") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
TableColumn column = columnModel.getColumnByModelIndex(0);
boolean visible = columnModel.isColumnVisible(column);
columnModel.setColumnVisible(column, !visible);
}
}));
toolBar.add(new JButton(new AbstractAction("Column 1") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
TableColumn column = columnModel.getColumnByModelIndex(1);
boolean visible = columnModel.isColumnVisible(column);
columnModel.setColumnVisible(column, !visible);
}
}));
toolBar.add(new JButton(new AbstractAction("Column 2") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
TableColumn column = columnModel.getColumnByModelIndex(2);
boolean visible = columnModel.isColumnVisible(column);
columnModel.setColumnVisible(column, !visible);
}
}));
toolBar.add(new JButton(new AbstractAction("Column 3") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
TableColumn column = columnModel.getColumnByModelIndex(3);
boolean visible = columnModel.isColumnVisible(column);
columnModel.setColumnVisible(column, !visible);
}
}));
toolBar.add(new JButton(new AbstractAction("Column 4") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
TableColumn column = columnModel.getColumnByModelIndex(4);
boolean visible = columnModel.isColumnVisible(column);
columnModel.setColumnVisible(column, !visible);
}
}));
toolBar.add(new JButton(new AbstractAction("Column 5") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
TableColumn column = columnModel.getColumnByModelIndex(5);
boolean visible = columnModel.isColumnVisible(column);
columnModel.setColumnVisible(column, !visible);
}
}));
toolBar.add(new JButton(new AbstractAction("Column 6") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
TableColumn column = columnModel.getColumnByModelIndex(6);
boolean visible = columnModel.isColumnVisible(column);
columnModel.setColumnVisible(column, !visible);
}
}));
toolBar.add(new JButton(new AbstractAction("Column 7") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
TableColumn column = columnModel.getColumnByModelIndex(7);
boolean visible = columnModel.isColumnVisible(column);
columnModel.setColumnVisible(column, !visible);
}
}));
toolBar.add(new JButton(new AbstractAction("Column 8") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
TableColumn column = columnModel.getColumnByModelIndex(8);
boolean visible = columnModel.isColumnVisible(column);
columnModel.setColumnVisible(column, !visible);
}
}));
toolBar.add(new JButton(new AbstractAction("Column 9") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
TableColumn column = columnModel.getColumnByModelIndex(9);
boolean visible = columnModel.isColumnVisible(column);
columnModel.setColumnVisible(column, !visible);
}
}));
toolBar.add(new JButton(new AbstractAction("Column 10") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
TableColumn column = columnModel.getColumnByModelIndex(10);
boolean visible = columnModel.isColumnVisible(column);
columnModel.setColumnVisible(column, !visible);
}
}));
//Row number
table.setFillsViewportHeight(true);
JScrollPane scrollTable = new JScrollPane(table,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollTable.setViewportView(table);
JTable rowTable = new RowNumberTable(table);
scrollTable.setRowHeaderView(rowTable);
scrollTable.setCorner(JScrollPane.UPPER_LEFT_CORNER, rowTable.getTableHeader());
//Column JCombobox
JTable columnTable = new ColumnJComboBoxTable(table);
scrollTable.setColumnHeaderView(columnTable);
getContentPane().add(toolBar, BorderLayout.NORTH);
getContentPane().add(scrollTable, BorderLayout.CENTER);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
public static void main(String[] args)
{
TableDemo frame = new TableDemo();
frame.pack();
frame.repaint();
frame.setVisible(true);
}
}
XTableColumnModel
The table model has been borrowed here
package com.table;
import javax.swing.table.*;
import java.util.Vector;
import java.util.Enumeration;
public class XTableColumnModel extends DefaultTableColumnModel {
private static final long serialVersionUID = 1L;
protected Vector allTableColumns = new Vector();
XTableColumnModel() {
}
public void setColumnVisible(TableColumn column, boolean visible) {
if(!visible) {
super.removeColumn(column);
}
else
{
int noVisibleColumns = tableColumns.size();
int noInvisibleColumns = allTableColumns.size();
int visibleIndex = 0;
for(int invisibleIndex = 0; invisibleIndex < noInvisibleColumns; ++invisibleIndex) {
TableColumn visibleColumn = (visibleIndex < noVisibleColumns ? (TableColumn)tableColumns.get(visibleIndex) : null);
TableColumn testColumn = (TableColumn)allTableColumns.get(invisibleIndex);
if(testColumn == column) {
if(visibleColumn != column) {
super.addColumn(column);
super.moveColumn(tableColumns.size() - 1, visibleIndex);
}
return;
}
if(testColumn == visibleColumn) {
++visibleIndex;
}
}
}
}
public void setAllColumnsVisible() {
int noColumns = allTableColumns.size();
for(int columnIndex = 0; columnIndex < noColumns; ++columnIndex) {
TableColumn visibleColumn = (columnIndex < tableColumns.size() ? (TableColumn)tableColumns.get(columnIndex) : null);
TableColumn invisibleColumn = (TableColumn)allTableColumns.get(columnIndex);
if(visibleColumn != invisibleColumn) {
super.addColumn(invisibleColumn);
super.moveColumn(tableColumns.size() - 1, columnIndex);
}
}
}
public TableColumn getColumnByModelIndex(int modelColumnIndex) {
for (int columnIndex = 0; columnIndex < allTableColumns.size(); ++columnIndex) {
TableColumn column = (TableColumn)allTableColumns.elementAt(columnIndex);
if(column.getModelIndex() == modelColumnIndex) {
return column;
}
}
return null;
}
public boolean isColumnVisible(TableColumn aColumn) {
return (tableColumns.indexOf(aColumn) >= 0);
}
public void addColumn(TableColumn column) {
allTableColumns.addElement(column);
super.addColumn(column);
}
public void removeColumn(TableColumn column) {
int allColumnsIndex = allTableColumns.indexOf(column);
if(allColumnsIndex != -1) {
allTableColumns.removeElementAt(allColumnsIndex);
}
super.removeColumn(column);
}
public void moveColumn(int oldIndex, int newIndex) {
if ((oldIndex < 0) || (oldIndex >= getColumnCount()) ||
(newIndex < 0) || (newIndex >= getColumnCount()))
throw new IllegalArgumentException("moveColumn() - Index out of range");
TableColumn fromColumn = (TableColumn) tableColumns.get(oldIndex);
TableColumn toColumn = (TableColumn) tableColumns.get(newIndex);
int allColumnsOldIndex = allTableColumns.indexOf(fromColumn);
int allColumnsNewIndex = allTableColumns.indexOf(toColumn);
if(oldIndex != newIndex) {
allTableColumns.removeElementAt(allColumnsOldIndex);
allTableColumns.insertElementAt(fromColumn, allColumnsNewIndex);
}
super.moveColumn(oldIndex, newIndex);
}
public int getColumnCount(boolean onlyVisible) {
Vector columns = (onlyVisible ? tableColumns : allTableColumns);
return columns.size();
}
public Enumeration getColumns(boolean onlyVisible) {
Vector columns = (onlyVisible ? tableColumns : allTableColumns);
return columns.elements();
}
public int getColumnIndex(Object identifier, boolean onlyVisible) {
if (identifier == null) {
throw new IllegalArgumentException("Identifier is null");
}
Vector columns = (onlyVisible ? tableColumns : allTableColumns);
int noColumns = columns.size();
TableColumn column;
for(int columnIndex = 0; columnIndex < noColumns; ++columnIndex) {
column = (TableColumn)columns.get(columnIndex);
if(identifier.equals(column.getIdentifier()))
return columnIndex;
}
throw new IllegalArgumentException("Identifier not found");
}
public TableColumn getColumn(int columnIndex, boolean onlyVisible) {
return (TableColumn)tableColumns.elementAt(columnIndex);
}
}
RowNumberTable
package com.table;
import java.awt.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class RowNumberTable extends JTable
implements ChangeListener, PropertyChangeListener, TableModelListener
{
private static final long serialVersionUID = -3837585325898676144L;
private JTable main;
public RowNumberTable(JTable table)
{
main = table;
main.addPropertyChangeListener( this );
main.getModel().addTableModelListener( this );
setFocusable( false );
setAutoCreateColumnsFromModel( false );
setSelectionModel( main.getSelectionModel() );
TableColumn column = new TableColumn();
column.setHeaderValue(" ");
addColumn( column );
column.setCellRenderer(new RowNumberRenderer());
getColumnModel().getColumn(0).setPreferredWidth(50);
setPreferredScrollableViewportSize(getPreferredSize());
}
#Override
public void addNotify()
{
super.addNotify();
Component c = getParent();
// Keep scrolling of the row table in sync with the main table.
if (c instanceof JViewport)
{
JViewport viewport = (JViewport)c;
viewport.addChangeListener( this );
}
}
#Override
public int getRowCount()
{
return main.getRowCount();
}
#Override
public int getRowHeight(int row)
{
int rowHeight = main.getRowHeight(row);
if (rowHeight != super.getRowHeight(row))
{
super.setRowHeight(row, rowHeight);
}
return rowHeight;
}
#Override
public Object getValueAt(int row, int column)
{
return Integer.toString(row + 1);
}
#Override
public boolean isCellEditable(int row, int column)
{
return false;
}
#Override
public void setValueAt(Object value, int row, int column) {}
public void stateChanged(ChangeEvent e)
{
// Keep the scrolling of the row table in sync with main table
JViewport viewport = (JViewport) e.getSource();
JScrollPane scrollPane = (JScrollPane)viewport.getParent();
scrollPane.getVerticalScrollBar().setValue(viewport.getViewPosition().y);
viewport.setBackground(Color.WHITE);
}
public void propertyChange(PropertyChangeEvent e)
{
// Keep the row table in sync with the main table
if ("selectionModel".equals(e.getPropertyName()))
{
setSelectionModel( main.getSelectionModel() );
}
if ("rowHeight".equals(e.getPropertyName()))
{
repaint();
}
if ("model".equals(e.getPropertyName()))
{
main.getModel().addTableModelListener( this );
revalidate();
}
}
#Override
public void tableChanged(TableModelEvent e)
{
revalidate();
}
/*
* Attempt to mimic the table header renderer
*/
private static class RowNumberRenderer extends DefaultTableCellRenderer
{
/**
*
*/
private static final long serialVersionUID = 6579115025835194953L;
public RowNumberRenderer()
{
setHorizontalAlignment(JLabel.CENTER);
}
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
if (table != null)
{
JTableHeader header = table.getTableHeader();
if (header != null)
{
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
}
if (isSelected)
{
setFont( getFont().deriveFont(Font.ITALIC) );
}
setText((value == null) ? "" : value.toString());
//setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return this;
}
}
}
ColumnJComboBoxTable
package com.table;
import java.awt.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class ColumnJComboBoxTable extends JTable implements ChangeListener,PropertyChangeListener, TableModelListener
{
private static final long serialVersionUID = -3837585325898676144L;
private JTable main;
public ColumnJComboBoxTable(JTable table)
{
main = table;
main.addPropertyChangeListener( this );
main.getModel().addTableModelListener( this );
setFocusable( false );
setAutoCreateColumnsFromModel( false );
setSelectionModel( main.getSelectionModel() );
for(int i =0; i<main.getModel().getColumnCount();i++)
{
TableColumn column = new TableColumn();
column.setHeaderValue(i);
addColumn( column );
getColumnModel().getColumn(i).setPreferredWidth(50);
column.setCellRenderer(new ColumnJComboBoxRenderer());
column.setHeaderRenderer(new ColumnJComboBoxRenderer());
}
setPreferredScrollableViewportSize(getPreferredSize());
}
#Override
public void addNotify()
{
super.addNotify();
Component c = getParent();
// Keep scrolling of the row table in sync with the main table.
if (c instanceof JViewport)
{
JViewport viewport = (JViewport)c;
viewport.addChangeListener( this );
}
}
#Override
public int getColumnCount()
{
return main.getColumnCount();
}
#Override
public int getRowHeight(int row)
{
int rowHeight = main.getRowHeight(row);
if (rowHeight != super.getRowHeight(row))
{
super.setRowHeight(row, rowHeight);
}
return rowHeight;
}
/*
* No model is being used for this table so just use the row number
* as the value of the cell.
*/
#Override
public Object getValueAt(int row, int column)
{
return Integer.toString(column + 1);
}
/*
* Don't edit data in the main TableModel by mistake
*/
#Override
public boolean isCellEditable(int row, int column)
{
return false;
}
/*
* Do nothing since the table ignores the model
*/
#Override
public void setValueAt(Object value, int row, int column) {}
//
// Implement the ChangeListener
//
public void stateChanged(ChangeEvent e)
{
// Keep the scrolling of the row table in sync with main table
JViewport viewport = (JViewport) e.getSource();
JScrollPane scrollPane = (JScrollPane)viewport.getParent();
scrollPane.getHorizontalScrollBar().setValue(viewport.getViewPosition().x);
}
//
// Implement the PropertyChangeListener
//
public void propertyChange(PropertyChangeEvent e)
{
// Keep the row table in sync with the main table
if ("selectionModel".equals(e.getPropertyName()))
{
setSelectionModel( main.getSelectionModel() );
}
if ("rowHeight".equals(e.getPropertyName()))
{
repaint();
}
if ("model".equals(e.getPropertyName()))
{
main.getModel().addTableModelListener( this );
revalidate();
}
}
//
// Implement the TableModelListener
//
#Override
public void tableChanged(TableModelEvent e)
{
revalidate();
}
/*
* Attempt to mimic the table header renderer
*/
private static class ColumnJComboBoxRenderer extends DefaultTableCellRenderer
{
/**
*
*/
private static final long serialVersionUID = 6579115025835194953L;
public ColumnJComboBoxRenderer()
{
setHorizontalAlignment(JLabel.HORIZONTAL);
}
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
if (table != null)
{
JTableHeader header = table.getTableHeader();
if (header != null)
{
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
}
if (isSelected)
{
setFont( getFont().deriveFont(Font.ITALIC) );
}
setText((value == null) ? "" : value.toString());
return this;
}
}
}
Anyone's help would be highly appreciated
Thanks
Thanks to #mKorbel for the help
Here the code of a solution
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableFilterRow implements TableColumnModelListener
{
private JTable table;
private JPanel filterRow;
public TableFilterRow(JTable table,JPanel filterRow)
{
this.table = table;
this.filterRow=filterRow;
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.getColumnModel().addColumnModelListener(this);
table.columnMarginChanged(new ChangeEvent(table.getColumnModel()));
}
#Override
public void columnMarginChanged(ChangeEvent e)
{
TableColumnModel tcm = table.getColumnModel();
int columns = tcm.getColumnCount();
for (int i = 0; i < columns; i++)
{
JComboBox<?> comboBox = (JComboBox<?>) filterRow.getComponent(i);
Dimension d = comboBox.getPreferredSize();
d.width = tcm.getColumn(i).getWidth();
comboBox.setPreferredSize(d);
}
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
filterRow.revalidate();
}
});
}
#Override
public void columnMoved(TableColumnModelEvent e)
{
Component moved = filterRow.getComponent(e.getFromIndex());
filterRow.remove(e.getFromIndex());
filterRow.add(moved, e.getToIndex());
filterRow.validate();
}
#Override
public void columnAdded(TableColumnModelEvent e)
{
}
#Override
public void columnRemoved(TableColumnModelEvent e)
{
}
#Override
public void columnSelectionChanged(ListSelectionEvent e)
{
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
JTable table = new JTable(3, 5);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.columnMarginChanged(new ChangeEvent(table.getColumnModel()));
ComboFields[] comboFields = ComboFields.values();
JScrollPane scrollPane = new JScrollPane(table);
frame.add(scrollPane, BorderLayout.CENTER);
JPanel filterRow = new JPanel();
filterRow.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
for (int i = 0; i < table.getColumnCount(); i++)
{
filterRow.add(new JComboBox<ComboFields>(comboFields));
}
new TableFilterRow(table, filterRow);
frame.add(filterRow, BorderLayout.NORTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private enum ComboFields{
VALUE_0(0),
VALUE_1(1),
VALUE_2(2),
VALUE_3(3),
VALUE_4(4),
VALUE_5(5);
// Internal state
private int fieldNumber;
private ComboFields(final int fieldNumber)
{
this.setFieldNumber(fieldNumber);
}
#SuppressWarnings("unused")
public int getFieldNumber() {
return fieldNumber;
}
public void setFieldNumber(int fieldNumber)
{
this.fieldNumber = fieldNumber;
}
}
}
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();
}
});
}
}
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);
I am creating a program to work like Microsoft Excel, in JAVA. My problem is how do I put the row numbers beside each row of the JTable? I have seen it working in other Java Programs - I just can not figure out how to include it in mine. Google gave me this website, and apparently it works. When I use it in my program this nothing happen. :/
I there a better way of adding row numbers in a JTable?
I have looked at the Java Tutorials already.
I am sorry if this question has been asked before.
There exists simple solution for that, and looks like as #camickr is more complex, (by Walter or Darryl from forums.sun.com)
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 TestTableRowTable {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if (info.getName().equals("Nimbus")) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} 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);
} else {
sorter.setRowFilter(filter);
}
}
}), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private TestTableRowTable() {
}
}