I have JTable with some rows. I want when move one row with mouse(drag and drop) that row to move together with mouse and table rows to be reorder when mouse move(like moving JTable's columns).
This jsfiddle is exactly what i want but i have to do it in java swing(or gif image below. Example is from here but I can't understand it).
My TransferHandler :
public class TableRowTransferHandler extends TransferHandler {
private final DataFlavor localObjectFlavor = new ActivationDataFlavor(Integer.class, "application/x-java-Integer;class=java.lang.Integer", "Integer Row Index");
private JTable table = null;
private static final Logger logger = Logger.getLogger(TableRowTransferHandler.class.getName());
public TableRowTransferHandler(JTable table) {
this.table = table;
}
#Override
protected Transferable createTransferable(JComponent c) {
assert (c == table);
return new DataHandler(table.getSelectedRow(), localObjectFlavor.getMimeType());
}
#Override
public boolean canImport(TransferHandler.TransferSupport info) {
boolean b = info.getComponent() == table && info.isDrop() && info.isDataFlavorSupported(localObjectFlavor);
table.setCursor(b ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop);
return b;
}
#Override
public int getSourceActions(JComponent c) {
return TransferHandler.COPY_OR_MOVE;
}
#Override
public boolean importData(TransferHandler.TransferSupport info) {
JTable target = (JTable) info.getComponent();
JTable.DropLocation dl = (JTable.DropLocation) info.getDropLocation();
int index = dl.getRow();
int max = table.getModel().getRowCount();
if (index < 0 || index > max) {
index = max;
}
target.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
try {
Integer rowFrom = (Integer) info.getTransferable().getTransferData(localObjectFlavor);
if (rowFrom != -1 && rowFrom != index) {
((Reorderable) table.getModel()).reorder(rowFrom, index);
if (index > rowFrom) {
index--;
}
target.getSelectionModel().addSelectionInterval(index, index);
return true;
}
} catch (UnsupportedFlavorException | IOException e) {
e.printStackTrace();
logger.log(Level.SEVERE, null, e);
}
return false;
}
#Override
protected void exportDone(JComponent c, Transferable t, int act) {
if ((act == TransferHandler.MOVE) || (act == TransferHandler.NONE)) {
table.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}
That is a simple settings that i use to JTable:
childrenTable.setDragEnabled(true);
childrenTable.setDropMode(DropMode.INSERT);
childrenTable.setTransferHandler(new TableRowTransferHandler(childrenTable));
childrenTable.setRowSelectionAllowed(true);
childrenTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
At the moment when you move row with mouse between rows only have one bold line(Like this in red ellipse below in image). If it is impossible to do rows to move like this, i want this bold line to appear to whole row (not only in one cell).
Read the section from the Swing tutorial on Drag and Drop for the basics.
Here is some old code I found somewhere on the web with a custom TransferHandler to support a JTable:
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.IOException;
public class DnD_Demo extends JFrame {
public DnD_Demo() {
setTitle("DnD Demo (Version 3)");
JTextArea tips = new JTextArea("1. Select a row in Table A. " +
"Press the row again and drag. \n " +
"As you drag the cursor icon over Table B, the row that is currently under the cursor highlights " +
"- the new data will be inserted after the selected row. \n " +
"Drop the row onto Table B. Note that the row has been removed from Table A, " +
"and now appears in Table B. \n" +
"2. Select two rows from Table A and drop onto Table B. " +
"Now there are two new rows in Table B. ");
tips.setEditable(false);
tips.setBackground(new Color(255,255,204));
tips.setBorder(new LineBorder(Color.orange,5));
getContentPane().add(tips,BorderLayout.NORTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridLayout(2,1));
panel.add(createTable("Table A"));
panel.add(createTable("Table B"));
getContentPane().add(panel,BorderLayout.CENTER);
pack();
}
private JPanel createTable(String tableId) {
DefaultTableModel model = new DefaultTableModel();
model.addColumn("Column 0");
model.addColumn("Column 1");
model.addColumn("Column 2");
model.addColumn("Column 3");
model.addRow(new String[]{tableId+" 00", tableId+" 01", tableId+" 02", tableId+" 03"});
model.addRow(new String[]{tableId+" 10", tableId+" 11", tableId+" 12", tableId+" 13"});
model.addRow(new String[]{tableId+" 20", tableId+" 21", tableId+" 22", tableId+" 23"});
model.addRow(new String[]{tableId+" 30", tableId+" 31", tableId+" 32", tableId+" 33"});
JTable table = new JTable(model);
table.getTableHeader().setReorderingAllowed(false);
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setPreferredSize(new Dimension(400,100));
table.setDragEnabled(true);
table.setTransferHandler(new TableTransferHandler());
JPanel panel = new JPanel();
panel.add(scrollPane);
panel.setBorder(BorderFactory.createTitledBorder(tableId));
return panel;
}
public static void main(String[] args) {
new DnD_Demo().setVisible(true);
}
abstract class StringTransferHandler extends TransferHandler {
protected abstract String exportString(JComponent c);
protected abstract void importString(JComponent c, String str);
protected abstract void cleanup(JComponent c, boolean remove);
protected Transferable createTransferable(JComponent c) {
return new StringSelection(exportString(c));
}
public int getSourceActions(JComponent c) {
return COPY_OR_MOVE;
}
public boolean importData(JComponent c, Transferable t) {
if (canImport(c, t.getTransferDataFlavors())) {
try {
String str = (String)t.getTransferData(DataFlavor.stringFlavor);
importString(c, str);
return true;
} catch (UnsupportedFlavorException ufe) {
} catch (IOException ioe) {
}
}
return false;
}
protected void exportDone(JComponent c, Transferable data, int action) {
cleanup(c, action == MOVE);
}
public boolean canImport(JComponent c, DataFlavor[] flavors) {
for (int i = 0; i < flavors.length; i++) {
if (DataFlavor.stringFlavor.equals(flavors[i])) {
return true;
}
}
return false;
}
}
class TableTransferHandler extends StringTransferHandler {
public JTable target;
public int[] rows = null;
public int addIndex = -1; //Location where items were added
public int addCount = 0; //Number of items added.
protected String exportString(JComponent c) {
JTable table = (JTable)c;
rows = table.getSelectedRows();
int colCount = table.getColumnCount();
StringBuffer buff = new StringBuffer();
for (int i = 0; i < rows.length; i++) {
for (int j = 0; j < colCount; j++) {
Object val = table.getValueAt(rows[i], j);
buff.append(val == null ? "" : val.toString());
if (j != colCount - 1) {
buff.append(",");
}
}
if (i != rows.length - 1) {
buff.append("\n");
}
}
return buff.toString();
}
protected void importString(JComponent c, String str) {
target = (JTable)c;
DefaultTableModel model = (DefaultTableModel)target.getModel();
int index = target.getSelectedRow();
//Prevent the user from dropping data back on itself.
//For example, if the user is moving rows #4,#5,#6 and #7 and
//attempts to insert the rows after row #5, this would
//be problematic when removing the original rows.
//So this is not allowed.
if (rows != null && index >= rows[0] - 1 &&
index <= rows[rows.length - 1]) {
rows = null;
return;
}
int max = model.getRowCount();
if (index < 0) {
index = max;
} else {
index++;
if (index > max) {
index = max;
}
}
addIndex = index;
String[] values = str.split("\n");
addCount = values.length;
int colCount = target.getColumnCount();
for (int i = 0; i < values.length ; i++) {
model.insertRow(index++, values[i].split(","));
}
//If we are moving items around in the same table, we
//need to adjust the rows accordingly, since those
//after the insertion point have moved.
if (rows!= null && addCount > 0) {
for (int i = 0; i < rows.length; i++) {
if (rows[i] > addIndex) {
rows[i] += addCount;
}
}
}
}
protected void cleanup(JComponent c, boolean remove) {
JTable source = (JTable)c;
if (remove && rows != null) {
DefaultTableModel model =
(DefaultTableModel)source.getModel();
for (int i = rows.length - 1; i >= 0; i--) {
model.removeRow(rows[i]);
}
}
rows = null;
addCount = 0;
addIndex = -1;
}
}
}
I think that ListTransferHandler.java for item swapping of JList in the Swing tutorial will be also helpful.
Here is an example that I modified ListTransferHandler for JTable:
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.*;
import java.util.List;
import javax.activation.*;
import javax.swing.*;
import javax.swing.table.*;
public final class TableRowsDnDTest {
private final TransferHandler handler = new TableRowTransferHandler();
private final String[] columnNames = {"String", "Integer", "Boolean"};
private final Object[][] data = {
{"AAA", 12, true}, {"aaa", 1, false},
{"BBB", 13, true}, {"bbb", 2, false},
{"CCC", 15, true}, {"ccc", 3, false},
{"DDD", 17, true}, {"ddd", 4, false},
{"EEE", 18, true}, {"eee", 5, false},
{"FFF", 19, true}, {"fff", 6, false},
{"GGG", 92, true}, {"ggg", 0, false}
};
private final TableModel model = new DefaultTableModel(data, columnNames) {
#Override public Class<?> getColumnClass(int column) {
switch (column) {
case 0:
return String.class;
case 1:
return Number.class;
case 2:
return Boolean.class;
default:
return super.getColumnClass(column);
}
}
};
private final JTable table = new JTable(model);
public JComponent makeUI() {
table.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setTransferHandler(handler);
table.setDropMode(DropMode.INSERT_ROWS);
table.setDragEnabled(true);
table.setFillsViewportHeight(true);
//table.setAutoCreateRowSorter(true); //XXX
//Disable row Cut, Copy, Paste
ActionMap map = table.getActionMap();
Action dummy = new AbstractAction() {
#Override public void actionPerformed(ActionEvent e) { /* Dummy action */ }
};
map.put(TransferHandler.getCutAction().getValue(Action.NAME), dummy);
map.put(TransferHandler.getCopyAction().getValue(Action.NAME), dummy);
map.put(TransferHandler.getPasteAction().getValue(Action.NAME), dummy);
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table));
p.setBorder(BorderFactory.createTitledBorder("Drag & Drop JTable"));
return p;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new TableRowsDnDTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
//Demo - BasicDnD (Drag and Drop and Data Transfer) https://docs.oracle.com/javase/tutorial/uiswing/dnd/basicdemo.html
//Demo - DropDemo (Drag and Drop and Data Transfer) https://docs.oracle.com/javase/tutorial/uiswing/dnd/dropmodedemo.html
//#see https://docs.oracle.com/javase/tutorial/uiswing/examples/dnd/DropDemoProject/src/dnd/ListTransferHandler.java
//#see https://github.com/aterai/java-swing-tips/blob/master/DnDReorderTable/src/java/example/TableRowsDnDTest.java
class TableRowTransferHandler extends TransferHandler {
private final DataFlavor localObjectFlavor;
private int[] indices;
private int addIndex = -1; //Location where items were added
private int addCount; //Number of items added.
protected TableRowTransferHandler() {
super();
localObjectFlavor = new ActivationDataFlavor(Object[].class, DataFlavor.javaJVMLocalObjectMimeType, "Array of items");
}
#Override protected Transferable createTransferable(JComponent c) {
JTable table = (JTable) c;
DefaultTableModel model = (DefaultTableModel) table.getModel();
List<Object> list = new ArrayList<>();
indices = table.getSelectedRows();
for (int i : indices) {
list.add(model.getDataVector().get(i));
}
Object[] transferedObjects = list.toArray();
return new DataHandler(transferedObjects, localObjectFlavor.getMimeType());
}
#Override public boolean canImport(TransferHandler.TransferSupport info) {
JTable table = (JTable) info.getComponent();
boolean isDropable = info.isDrop() && info.isDataFlavorSupported(localObjectFlavor);
table.setCursor(isDropable ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop);
return isDropable;
}
#Override public int getSourceActions(JComponent c) {
return TransferHandler.MOVE;
}
#Override public boolean importData(TransferHandler.TransferSupport info) {
if (!canImport(info)) {
return false;
}
TransferHandler.DropLocation tdl = info.getDropLocation();
if (!(tdl instanceof JTable.DropLocation)) {
return false;
}
JTable.DropLocation dl = (JTable.DropLocation) tdl;
JTable target = (JTable) info.getComponent();
DefaultTableModel model = (DefaultTableModel) target.getModel();
int index = dl.getRow();
int max = model.getRowCount();
if (index < 0 || index > max) {
index = max;
}
addIndex = index;
target.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
try {
Object[] values = (Object[]) info.getTransferable().getTransferData(localObjectFlavor);
addCount = values.length;
for (int i = 0; i < values.length; i++) {
int idx = index++;
model.insertRow(idx, (Vector) values[i]);
target.getSelectionModel().addSelectionInterval(idx, idx);
}
return true;
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
return false;
}
#Override protected void exportDone(JComponent c, Transferable data, int action) {
cleanup(c, action == TransferHandler.MOVE);
}
//If the remove argument is true, the drop has been
//successful and it's time to remove the selected items
//from the list. If the remove argument is false, it
//was a Copy operation and the original list is left
//intact.
protected void cleanup(JComponent c, boolean remove) {
if (remove && indices != null) {
c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
DefaultTableModel model = (DefaultTableModel)((JTable) c).getModel();
//If we are moving items around in the same list, we
//need to adjust the indices accordingly, since those
//after the insertion point have moved.
if (addCount > 0) {
for (int i = 0; i < indices.length; i++) {
if (indices[i] >= addIndex) {
indices[i] += addCount;
}
}
}
for (int i = indices.length - 1; i >= 0; i--) {
model.removeRow(indices[i]);
}
}
indices = null;
addCount = 0;
addIndex = -1;
}
}
Related
This is a Drag and Drop Java Swing
Here's my code
prod.removeColumn(prod.getColumnModel().getColumn(0));
String sql = "select prod_id,prod_description,prod_wh_name,prod_fr_name from product order by prod_description asc";
PreparedStatement pst = con.prepareStatement(sql);
ResultSet rs = pst.executeQuery();
while(rs.next())
{
int columns = rs.getMetaData().getColumnCount();
Object[] row = new Object[columns];
for(int i = 1 ; i <=columns;i++)
{
row[i - 1] = rs.getObject(i);
}
((DefaultTableModel) prod.getModel()).insertRow(rs.getRow() -1,row);
}
I want to add a checkbox on the left side of every data in jtable(Prod Description), Any solution for that? and can select more than one? and how can i get the data of the selected item? Thanks in advance!
One way is to create a "wrapper" TableModel.
In this example a column containing check marks will be added to the left of the columns in any existing TableModel:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class CheckBoxWrapperTableModel extends AbstractTableModel
{
private ArrayList<Boolean> checkBoxes = new ArrayList<>();
private DefaultTableModel model;
private String columnName;
public CheckBoxWrapperTableModel(DefaultTableModel model, String columnName)
{
this.model = model;
this.columnName = columnName;
for (int i = 0; i < model.getRowCount(); i++)
checkBoxes.add( Boolean.FALSE );
}
#Override
public String getColumnName(int column)
{
return (column > 0) ? model.getColumnName(column - 1) : columnName;
}
#Override
public int getRowCount()
{
return model.getRowCount();
}
#Override
public int getColumnCount()
{
return model.getColumnCount() + 1;
}
#Override
public Object getValueAt(int row, int column)
{
if (column > 0)
return model.getValueAt(row, column - 1);
else
{
Object value = checkBoxes.get(row);
return (value == null) ? Boolean.FALSE : value;
}
}
#Override
public boolean isCellEditable(int row, int column)
{
if (column > 0)
return model.isCellEditable(row, column - 1);
else
return true;
}
#Override
public void setValueAt(Object value, int row, int column)
{
if (column > 0)
model.setValueAt(value, row, column - 1);
else
{
checkBoxes.set(row, (Boolean)value);
}
fireTableCellUpdated(row, column);
}
#Override
public Class getColumnClass(int column)
{
return (column > 0) ? model.getColumnClass(column - 1) : Boolean.class;
}
public void removeRow(int row)
{
checkBoxes.remove(row);
fireTableRowsDeleted(row, row);
model.removeRow(row);
}
private static void createAndShowGUI()
{
// Create the table with check marks in the first column
DefaultTableModel model = new DefaultTableModel(5, 1);
for (int i = 0; i < model.getRowCount(); i++)
{
model.setValueAt("" + i, i, 0);
}
CheckBoxWrapperTableModel wrapperModel = new CheckBoxWrapperTableModel(model, "Select");
JTable table = new JTable(wrapperModel);
// Add button to delete selected rows
JButton button = new JButton( "Delete Selected Rows" );
button.addActionListener( new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
for (int i = table.getRowCount() - 1; i >= 0; i--)
{
Boolean selected = (Boolean)table.getValueAt(i, 0);
System.out.println(selected + " : " + i);
if (selected)
{
wrapperModel.removeRow(i);
}
}
}
});
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new JScrollPane( table ) );
frame.add( button, BorderLayout.PAGE_END );
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
This allows you to add the check box even if you don't have access to the original TableModel when it is created to add your own column of check boxes.
I have a JTable with actually 6 columns and many rows. Now i want to change the selection and jump to that row by pressing one or more keys on the keyboard.
This is the example of what i want:
If I press "S" on keyboard my application should select the first row in my table which has an entry beginning with the char "S".
However if I press two keys "SC" it should do the same with rows beginning with "SC" like above.
When I press another keys, for example "BHM", it should do the same with the rows beginning with "BHM" like above.
I have implemented this but it is not working properly
P.S The GUI also freezes after too many key presses.
Here is my complete code.
MyTable.java
public class MyTable extends JPanel {
public JScrollPane jScrollPane1;
public JTextField searchField;
public JTable table;
Object[] data = new Object[6];
ArrayList rows = new ArrayList();
MyTable() {
table = new JTable();
table.setAutoCreateRowSorter(true);
table.setModel(new DefaultTableModel(
new Object[][]{},
new String[]{
"Description", "Code", "Qty", "Cost", "Rate", "Packing"
}
) {
Class[] types = new Class[]{
String.class, String.class, Integer.class, Double.class, Double.class, String.class
};
boolean[] canEdit = new boolean[]{
false, false, false, false, false, false
};
public Class getColumnClass(int columnIndex) {
return types[columnIndex];
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit[columnIndex];
}
});
table.setColumnSelectionAllowed(true);
table.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
table.getTableHeader().setReorderingAllowed(false);
table.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
if (table.getColumnModel().getColumnCount() > 0) {
table.getColumnModel().getColumn(0).setMinWidth(300);
table.getColumnModel().getColumn(0).setPreferredWidth(300);
table.getColumnModel().getColumn(0).setMaxWidth(1000);
table.getColumnModel().getColumn(1).setMinWidth(100);
table.getColumnModel().getColumn(1).setPreferredWidth(100);
table.getColumnModel().getColumn(1).setMaxWidth(500);
table.getColumnModel().getColumn(2).setMinWidth(50);
table.getColumnModel().getColumn(2).setPreferredWidth(50);
table.getColumnModel().getColumn(2).setMaxWidth(100);
table.getColumnModel().getColumn(3).setMinWidth(80);
table.getColumnModel().getColumn(3).setPreferredWidth(80);
table.getColumnModel().getColumn(3).setMaxWidth(200);
table.getColumnModel().getColumn(4).setMinWidth(80);
table.getColumnModel().getColumn(4).setPreferredWidth(80);
table.getColumnModel().getColumn(4).setMaxWidth(200);
table.getColumnModel().getColumn(5).setMinWidth(80);
table.getColumnModel().getColumn(5).setPreferredWidth(80);
table.getColumnModel().getColumn(5).setMaxWidth(200);
}
table.setPreferredScrollableViewportSize(new Dimension(800, 600));
table.setFillsViewportHeight(true);
table.setRowHeight(30);
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
table.addKeyListener(new SearchingKeyAdapter(table));
addRowData();
table.changeSelection(0, 0, false, false);
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("MyTable");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
MyTable newContentPane = new MyTable();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
private void addRowData() {
String desc = "SL 123";
Integer code = 12345;
Integer qty = 10;
Double rate = new Double(1000);
Double cost = new Double(900);
String pack = "10x10x10";
data[0] = desc;
data[1] = code;
data[2] = qty;
data[3] = cost;
data[4] = rate;
data[5] = pack;
DefaultTableModel model = (DefaultTableModel) table.getModel();
for (int i = 0; i < 5; i++) {
data[0] = "SL " + i;
rows.add(data);
model.addRow(data);
}
rows.clear();
for (int i = 0; i < 5; i++) {
data[0] = "SC " + i;
rows.add(data);
model.addRow(data);
}
data[0] = "AP";
model.addRow(data);
data[0] = "GP";
model.addRow(data);
data[0] = "PS";
model.addRow(data);
data[0] = "PP";
model.addRow(data);
data[0] = "BHM";
model.addRow(data);
data[0] = "BGP";
model.addRow(data);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
SearchingKeyAdapter.java
public class SearchingKeyAdapter extends KeyAdapter {
String key = "";
private final JTable table;
private int selectedRow = -1;//before start
public SearchingKeyAdapter(JTable table) {
this.table = table;
}
#Override
public void keyPressed(KeyEvent e) {
key += String.valueOf(e.getKeyChar());
}
#Override
public void keyReleased(KeyEvent e) {
String keyChar = key.toUpperCase();
key = "";
TableModel model = table.getModel();
int startRow = selectedRow;
if (selectedRow == model.getRowCount() - 1) {
startRow = -1;//Go before start
}
int col = 0;
for (int row = startRow + 1; row < model.getRowCount(); row++) {
String value = (String) model.getValueAt(row, col);
if (value != null && !value.isEmpty() && value.toUpperCase().startsWith(keyChar)) {
table.getSelectionModel().clearSelection();
table.getColumnModel().getSelectionModel().clearSelection();
table.setRowSelectionInterval(row, row);
table.changeSelection(row, col, false, false);
selectedRow = row;
return;
}
}
}
}
Thank you !
I have implemented this but it is not working properly
Your example does not seem to assume that the selected row is changed by arrow keys or mouse click.
It might be easier to modify a similar function in JList than to create your own KeyListener.
JList#getNextMatch(...): Returns the next list element whose toString value starts with the given prefix.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.Position;
public class MyTable2 extends JPanel {
public JScrollPane jScrollPane1;
public JTextField searchField;
public JTable table;
private final Object[] data = new Object[6];
private final ArrayList<Object[]> rows = new ArrayList<>();
private MyTable2() {
table = new JTable();
table.setAutoCreateRowSorter(true);
table.setModel(new DefaultTableModel(
new String[] {
"Description", "Code", "Qty", "Cost", "Rate", "Packing"
}, 0
) {
Class[] types = new Class[] {
String.class, String.class, Integer.class, Double.class, Double.class, String.class
};
#Override public Class getColumnClass(int columnIndex) {
return types[columnIndex];
}
#Override public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
});
table.setColumnSelectionAllowed(true);
table.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
table.getTableHeader().setReorderingAllowed(false);
table.getColumnModel().getSelectionModel().setSelectionMode(
ListSelectionModel.SINGLE_SELECTION);
table.setPreferredScrollableViewportSize(new Dimension(800, 600));
table.setFillsViewportHeight(true);
table.setRowHeight(30);
//table.addKeyListener(new SearchingKeyAdapter(table));
table.addKeyListener(new TableNextMatchKeyHandler());
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
addRowData();
table.changeSelection(0, 0, false, false);
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("MyTable");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MyTable2());
frame.pack();
frame.setVisible(true);
}
private void addRowData() {
String desc = "SL 123";
Integer code = 12345;
Integer qty = 10;
Double rate = new Double(1000);
Double cost = new Double(900);
String pack = "10x10x10";
data[0] = desc;
data[1] = code;
data[2] = qty;
data[3] = cost;
data[4] = rate;
data[5] = pack;
DefaultTableModel model = (DefaultTableModel) table.getModel();
for (int i = 0; i < 5; i++) {
data[0] = "SL " + i;
rows.add(data);
model.addRow(data);
}
rows.clear();
for (int i = 0; i < 5; i++) {
data[0] = "SC " + i;
rows.add(data);
model.addRow(data);
}
data[0] = "AP";
model.addRow(data);
data[0] = "GP";
model.addRow(data);
data[0] = "PS";
model.addRow(data);
data[0] = "PP";
model.addRow(data);
data[0] = "BHM";
model.addRow(data);
data[0] = "BGP";
model.addRow(data);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
//#see javax/swing/plaf/basic/BasicListUI.Handler
//#see javax/swing/plaf/basic/BasicTreeUI.Handler
class TableNextMatchKeyHandler extends KeyAdapter {
private static final int TARGET_COLUMN = 0;
private static final long TIME_FACTOR = 500L;
private String prefix = "";
private String typedString;
private long lastTime;
private boolean isNavigationKey(KeyEvent event) {
JTable table = (JTable) event.getComponent();
InputMap im = table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
KeyStroke key = KeyStroke.getKeyStrokeForEvent(event);
return Objects.nonNull(im) && Objects.nonNull(im.get(key));
}
#Override public void keyPressed(KeyEvent e) {
if (isNavigationKey(e)) {
prefix = "";
typedString = "";
lastTime = 0L;
}
}
#Override public void keyTyped(KeyEvent e) {
JTable src = (JTable) e.getComponent();
int max = src.getRowCount();
if (max == 0 || e.isAltDown() || isNavigationKey(e)) {
//|| BasicGraphicsUtils.isMenuShortcutKeyDown(e)) {
// Nothing to select
return;
}
boolean startingFromSelection = true;
char c = e.getKeyChar();
int increment = e.isShiftDown() ? -1 : 1;
long time = e.getWhen();
int startIndex = src.getSelectedRow();
if (time - lastTime < TIME_FACTOR) {
typedString += c;
if (prefix.length() == 1 && c == prefix.charAt(0)) {
// Subsequent same key presses move the keyboard focus to the next
// object that starts with the same letter.
startIndex += increment;
} else {
prefix = typedString;
}
} else {
startIndex += increment;
typedString = String.valueOf(c);
prefix = typedString;
}
lastTime = time;
selectAndScrollNextMatch(src, max, e, prefix, startIndex, startingFromSelection);
}
private static void selectAndScrollNextMatch(
JTable src, int max, KeyEvent e, String prefix,
int startIndex, boolean startingFromSelection) {
int start = startIndex;
boolean isStartingSelection = startingFromSelection;
if (start < 0 || start >= max) {
if (e.isShiftDown()) {
start = max - 1;
} else {
isStartingSelection = false;
start = 0;
}
}
Position.Bias bias = e.isShiftDown() ? Position.Bias.Backward : Position.Bias.Forward;
int index = getNextMatch(src, prefix, start, bias);
if (index >= 0) {
src.getSelectionModel().setSelectionInterval(index, index);
src.scrollRectToVisible(src.getCellRect(index, TARGET_COLUMN, true));
} else if (isStartingSelection) { // wrap
index = getNextMatch(src, prefix, 0, bias);
if (index >= 0) {
src.getSelectionModel().setSelectionInterval(index, index);
src.scrollRectToVisible(src.getCellRect(index, TARGET_COLUMN, true));
}
}
}
//#see javax/swing/JList#getNextMatch(String prefix, int startIndex, Position.Bias bias)
//#see javax/swing/JTree#getNextMatch(String prefix, int startIndex, Position.Bias bias)
public static int getNextMatch(
JTable table, String prefix, int startingRow, Position.Bias bias) {
int max = table.getRowCount();
if (Objects.isNull(prefix) || startingRow < 0 || startingRow >= max) {
throw new IllegalArgumentException();
}
String uprefix = prefix.toUpperCase(Locale.ENGLISH);
// start search from the next/previous element froom the
// selected element
int increment = bias == Position.Bias.Forward ? 1 : -1;
int row = startingRow;
do {
Object value = table.getValueAt(row, TARGET_COLUMN);
String text = Objects.toString(value, "");
if (text.toUpperCase(Locale.ENGLISH).startsWith(uprefix)) {
return row;
}
row = (row + increment + max) % max;
} while (row != startingRow);
return -1;
}
}
I have a jTable that I have created to display the names of countries and the flag icons in the cells next to the names. How can I display each icon in the same column but different rows using the ImageIcon class, without displaying just a string?
The following is what I have written to display the France flag icon at a certain place in the jTable but it just displays the string
ImageIcon icon = new ImageIcon("http://www.stoma.fr/assets/images/French_Flag_Small_Icon.jpg");
jTable.setValueAt(icon, 1, 2);
This is solved easily by simply making sure that the column for the icons returns Icon.class in the table model's getColumnClass(...) method. Fortunately JTables know how to display icons without any extra work if you do this. For example.
A modification of my code from there uses this table model:
DefaultTableModel model = new DefaultTableModel(COL_NAMES, 0) {
#Override
public Class<?> getColumnClass(int column) {
if (getRowCount() > 0) {
Object value = getValueAt(0, column);
if (value != null) {
return getValueAt(0, column).getClass();
}
}
return super.getColumnClass(column);
}
};
The whole program:
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class ImageColumnTest2 {
public static final String IMAGE_SHEET_PATH = "http://speckycdn.sdm.netdna-cdn.com/"
+ "wp-content/uploads/2010/08/flag_icons_04.jpg";
public static final String[] COUNTRIES = {
"Denmark", "China", "Chile", "Canada", "Belgium", "Austria",
"Argentina", "France", "Malaysina", "Lebanon", "Korea", "Japan",
"Italy", "Ireland", "India", "Hong Kong", "Greece", "Germany"
};
public static final int COLS = 6;
public static final int ROWS = 3;
private static final String[] COL_NAMES = {"Country", "Flag"};
private JTable table = new JTable();
private JScrollPane mainPane = new JScrollPane(table);
public ImageColumnTest2() throws IOException {
DefaultTableModel model = new DefaultTableModel(COL_NAMES, 0) {
#Override
public Class<?> getColumnClass(int column) {
if (getRowCount() > 0) {
Object value = getValueAt(0, column);
if (value != null) {
return getValueAt(0, column).getClass();
}
}
return super.getColumnClass(column);
}
};
URL url = new URL(IMAGE_SHEET_PATH);
BufferedImage img = ImageIO.read(url);
int x1 = 15; // sorry about the magic numbers
img = img.getSubimage(x1, 0, img.getWidth() - 2 * x1, img.getHeight());
int y1 = 20 ; // ditto!
int w = img.getWidth() / COLS;
int h = img.getHeight() / ROWS;
for (int row = 0; row < ROWS; row++) {
int y = (row * img.getHeight()) / ROWS;
for (int col = 0; col < COLS; col++) {
int x = (col * img.getWidth()) / COLS;
BufferedImage subImg = img.getSubimage(x, y, w, h);
subImg = subImg.getSubimage(x1, 0, subImg.getWidth() - 2 * x1, subImg.getHeight() - y1);
ImageIcon icon = new ImageIcon(subImg);
String country = COUNTRIES[col + row * COLS];
Object[] rowData = {country, icon};
model.addRow(rowData);
}
}
table.setModel(model);
table.setRowHeight(((ImageIcon)model.getValueAt(0, 1)).getIconHeight());
}
public JComponent getMainComponent() {
return mainPane;
}
private static void createAndShowGui() {
ImageColumnTest2 imgColumnTest = null;
try {
imgColumnTest = new ImageColumnTest2();
} catch (MalformedURLException e) {
e.printStackTrace();
System.exit(-1);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
JFrame frame = new JFrame("ImageColumnTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(imgColumnTest.getMainComponent());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Which displays as:
This issue is hurting me for a long time.
It is very nasty and I managed to prepare sample that will show it to you expert.
Just copy paste this :
public class CellBorderDemo extends JFrame
{
private JTable dataSearchResultTable;
private boolean selectRow = false;
public CellBorderDemo()
{
JPanel panel = new JPanel(new GridLayout(2, 1, 5, 10));
panel.setPreferredSize(new Dimension(500, 300));
MyTableModel myTableModel = new MyTableModel();
dataSearchResultTable = new JTable();
dataSearchResultTable.addKeyListener(new KeyAdapter()
{
private String attemptId = new String();
#Override
public void keyTyped(KeyEvent e)
{
System.out.println("selectRow=" + selectRow + " keyChar=" + (int) e.getKeyChar() + " event=" + e);
if ((e.getModifiers() == KeyEvent.CTRL_MASK && (int) e.getKeyChar() == 10)) {
System.out.println("Ctrl+J was pressed when focus was ok");
selectRow = true;
attemptId = new String();
dataSearchResultTable.editCellAt(-1, -1);
dataSearchResultTable.getSelectionModel().clearSelection();
return;
} else if ((int) e.getKeyChar() == 32) {
return;
}
if (selectRow) {
char keyChar = e.getKeyChar();
if (keyChar >= 48 && keyChar <= 57) {
attemptId += String.valueOf(keyChar);
if (selectRow(Integer.valueOf(attemptId).intValue())) {
System.out.println("attemptId=" + attemptId);
return;
}
}
selectRow = false;
attemptId = new String();
}
}
});
dataSearchResultTable.setSelectionBackground(new Color(0xbbccdd));
dataSearchResultTable.setSelectionForeground(new Color(0x333300));
dataSearchResultTable.setFillsViewportHeight(true);
dataSearchResultTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
dataSearchResultTable.setAutoCreateRowSorter(true);
dataSearchResultTable.setRowHeight(30);
dataSearchResultTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
dataSearchResultTable.getColumnModel().setColumnMargin(0);
dataSearchResultTable.setPreferredScrollableViewportSize(dataSearchResultTable.getPreferredSize());
dataSearchResultTable.setModel(myTableModel);
panel.add(new JScrollPane(dataSearchResultTable));
super.getContentPane().add(panel);
super.pack();
super.setDefaultCloseOperation(EXIT_ON_CLOSE);
super.setVisible(true);
}
public boolean selectRow(int attemptId)
{
MyTableModel tableModel = (MyTableModel) dataSearchResultTable.getModel();
int row = 0;
if (attemptId >= 0 && attemptId < tableModel.getRowCount()) {
System.out.println("rowToSelect=" + row);
dataSearchResultTable.setRowSelectionInterval(attemptId, attemptId);
dataSearchResultTable.setColumnSelectionInterval(2, 2);
tableModel.fireTableCellUpdated(row, 2);
dataSearchResultTable.requestFocusInWindow();
return true;
}
return false;
}
class MyTableModel extends AbstractTableModel
{
private String[] columnNames = { "First Name", "Last name", "Vegetarian" };
private Object[][] data;
int prefRow = 1, prefCol = 2;
MyTableModel()
{
data = new Object[][] { { "Vova", "KipokKipokKipokKipok", false }, { "Olia", "Duo", true },
{ "Ivan", "Brown", false } };
}
public int getColumnCount()
{
return columnNames.length;
}
public int getRowCount()
{
return data.length;
}
public String getColumnName(int col)
{
return columnNames[col];
}
public Object getValueAt(int row, int col)
{
if (data.length > 0 && data[0] != null) {
return data[row][col];
}
return null;
}
public Class getColumnClass(int c)
{
Object valueAt = getValueAt(0, c);
return valueAt == null ? Object.class : valueAt.getClass();
}
public boolean isCellEditable(int row, int col)
{
return true;
}
public void setValueAt(Object value, int row, int col)
{
if (data.length > 0 && data[0] != null) {
if (data[row][col] instanceof Boolean && (Boolean) value) {
setValueAt(false, prefRow, prefCol);
prefRow = row;
prefCol = col;
}
data[row][col] = value;
fireTableCellUpdated(row, col);
}
}
}
public static void main(String[] args) throws ParseException
{
new CellBorderDemo();
}
}
I understand that it's long. Don't look at class MyTableModel at all but only at keylistener and selectRow method.
Now please press Ctrl+J and then press either 0 or 1 or 2.
You will notice that appropriate row is selected you may press Space to select checkbox. Now press Ctrl+J again and press number from 0 to 2 but it should be different from the first attempt. You notice that new row is selected according to new number . And now press Space and you will see my issue new cell was selected but wasn't focused and that's why Space unselected previously selected checkbox but not currently selected one.
I will be very grateful for this help because this feature is very important.
Thank you!
Problem in next in your selectRow method you never change your row variable it always 0. In next example i change your row variable and try to edit that row with editCellAt method
public boolean selectRow(int attemptId) {
MyTableModel tableModel = (MyTableModel) dataSearchResultTable.getModel();
int row = 0;
if (attemptId >= 0 && attemptId < tableModel.getRowCount()) {
System.out.println("rowToSelect=" + row);
dataSearchResultTable.setRowSelectionInterval(attemptId, attemptId);
dataSearchResultTable.setColumnSelectionInterval(2, 2);
tableModel.fireTableCellUpdated(row, 2);
dataSearchResultTable.requestFocusInWindow();
row = dataSearchResultTable.getSelectedRow();
if(row != -1){
dataSearchResultTable.editCellAt(row, 2);
}
return true;
}
return false;
}
I think it what do you want.
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.