Resize JTable columns to suit table contents - java

I used the code pasted below to resize the column width with a delay of 5 seconds once the JTable gets displayed. However, when I run "TestColumnResizer.java", it shows error "java.lang.NoClassDefFoundError", main not found. How can I modify the code to get it run?Or how can I call the TestColumnResizer program in some other class?
public class ColumnResizer {
public static void adjustColumnPreferredWidths(JTable table) {
// strategy - get max width for cells in column and
// make that the preferred width
TableColumnModel columnModel = table.getColumnModel();
for (int col = 0; col < table.getColumnCount(); col++) {
int maxwidth = 0;
for (int row = 0; row < table.getRowCount(); row++) {
TableCellRenderer rend = table.getCellRenderer(row, col);
Object value = table.getValueAt(row, col);
Component comp = rend.getTableCellRendererComponent(table,
value, false, false, row, col);
maxwidth = Math.max(comp.getPreferredSize().width, maxwidth);
} // for row
TableColumn column = columnModel.getColumn(col);
column.setPreferredWidth(maxwidth);
} // for col
}
}
// Testing automatic column sizing
public class TestColumnResizer {
final static Object[][] TABLE_DATA = {
{ new Integer(1), "ONJava", "http://www.onjava.com/" },
{ new Integer(2), "Joshy's Site", "http://www.joshy.org/" },
{ new Integer(3), "Anime Weekend Atlanta",
"http://www.awa-con.com/" },
{ new Integer(4), "QTJ book",
"http://www.oreilly.com/catalog/quicktimejvaadn/" } };
final static String[] COLUMN_NAMES = { "Count", "Name", "URL" };
public static void main(String[] args) {
// 142 mac l&f has a header bug - force metal for today
try {
UIManager.setLookAndFeel(UIManager
.getCrossPlatformLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
DefaultTableModel mod = new DefaultTableModel(TABLE_DATA, COLUMN_NAMES);
JTable table = new JTable(mod);
JScrollPane pane =
new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
JFrame frame = new JFrame("JTable Column Widths");
frame.getContentPane().add(pane);
frame.pack();
frame.setVisible(true);
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
// now get smart about col widths
final JTable fTable = table;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ColumnResizer.adjustColumnPreferredWidths(fTable);
fTable.revalidate();
}
});
}
}

From what I can see there is nothing wrong with the working of the code, just the way the classes are defined.
If this is all in one class file then you are going to get an error. To correct this just edit the class modifiers like this:
import java.awt.Component;
import javax.swing.*;
import javax.swing.table.*;
//Testing automatic column sizing
public class TestColumnResizer {
final static Object[][] TABLE_DATA = {
{ new Integer(1), "ONJava", "http://www.onjava.com/" },
{ new Integer(2), "Joshy's Site", "http://www.joshy.org/" },
{ new Integer(3), "Anime Weekend Atlanta",
"http://www.awa-con.com/" },
{ new Integer(4), "QTJ book",
"http://www.oreilly.com/catalog/quicktimejvaadn/" } };
final static String[] COLUMN_NAMES = { "Count", "Name", "URL" };
public static void main(String[] args) {
// 142 mac l&f has a header bug - force metal for today
try {
UIManager.setLookAndFeel(UIManager
.getCrossPlatformLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
DefaultTableModel mod = new DefaultTableModel(TABLE_DATA, COLUMN_NAMES);
JTable table = new JTable(mod);
JScrollPane pane =
new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
JFrame frame = new JFrame("JTable Column Widths");
frame.getContentPane().add(pane);
frame.pack();
frame.setVisible(true);
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
// now get smart about col widths
final JTable fTable = table;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ColumnResizer.adjustColumnPreferredWidths(fTable);
fTable.revalidate();
}
});
}
}
class ColumnResizer {
public static void adjustColumnPreferredWidths(JTable table) {
// strategy - get max width for cells in column and
// make that the preferred width
TableColumnModel columnModel = table.getColumnModel();
for (int col = 0; col < table.getColumnCount(); col++) {
int maxwidth = 0;
for (int row = 0; row < table.getRowCount(); row++) {
TableCellRenderer rend = table.getCellRenderer(row, col);
Object value = table.getValueAt(row, col);
Component comp = rend.getTableCellRendererComponent(table,
value, false, false, row, col);
maxwidth = Math.max(comp.getPreferredSize().width, maxwidth);
} // for row
TableColumn column = columnModel.getColumn(col);
column.setPreferredWidth(maxwidth);
} // for col
}
}
If it is not all in one class file than try: http://www.tech-recipes.com/rx/826/java-exception-in-thread-main-javalangnoclassdeffounderror/. Basically there could be a problem with your classpath.
Don't worry though, the code appears to do everything you specified!

Related

Trying to get the sorter positon to retain after a table refresh

I have the following method:
private void passStingR(StringBuilder retVal) throws BadLocationException {
int scrollPositionR = scrollR.getVerticalScrollBar().getValue();//get value of scroll position stores in javas memory
windowR.remove(scrollR);
tableR.getModel();
modelR.setRowCount(0);
Document docR = null;
try {
docR = loadXMLFromString(retVal.toString());//pull in the XML data into a new doc
} catch (Exception ex) {
Logger.getLogger(remit.class.getName()).log(Level.SEVERE, null, ex);
}
populate1R(docR);
tableR.getTableHeader().setReorderingAllowed(false);//prevent user from changing column order now at refresh level
SimpleDateFormat time_formatterR = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String current_time_strR = time_formatterR.format(System.currentTimeMillis());
updatetFieldR.setText(current_time_strR);
scrollR.remove(tableR);
tableR = new JTable(modelR)
{
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
Font myFont = new Font("Arial",Font.PLAIN,10);
Font myFont1 = new Font("Arial", Font.BOLD,10);
if (!isRowSelected(row)) {
if (tableR.getColumnCount() >= 0) {
String type = (String) getModel().getValueAt(row, 11);
c.setBackground("0.0".equals(type) ? Color.RED : Color.WHITE);
c.setForeground("0.0".equals(type) ? Color.WHITE : Color.BLACK);
c.setFont("0.0".equals(type) ? myFont1: myFont);
}
}
return c;
};
};
TableColumn column = null;
for (int i = 0; i < 18; i++) {
column = tableR.getColumnModel().getColumn(i);
if (i == 0) {
column.setPreferredWidth(70); //sport column is bigger
}
if (i == 1) {
column.setPreferredWidth(500); //sport column is bigger
}
if (i == 7) {
column.setPreferredWidth(30); //sport column is bigger
}
if (i == 8) {
column.setPreferredWidth(20); //sport column is bigger
}
if (i == 9) {
column.setPreferredWidth(25); //sport column is bigger
}
if (i == 14) {
column.setPreferredWidth(500); //sport column is bigger
}
if (i == 15) {
column.setPreferredWidth(10); //sport column is bigger
}
if (i == 16) {
column.setPreferredWidth(20); //sport column is bigger
}
}
tableR.getTableHeader().setReorderingAllowed(false);//prevent the user from sorting the columns at intialise GUI stage even though the user cannnot change this
RowSorter<TableModel> sorter = new TableRowSorter<>(modelR);//creating a new sorter here from my modelR
tableR.setRowSorter(sorter);//set the sorter positon
scrollR = new JScrollPane(tableR);
windowR.add(scrollR);
windowR.validate();
scrollR.getVerticalScrollBar().setValue(scrollPositionR);
}
I then create a sorter part way down the above code like below
RowSorter<TableModel> sorter = new TableRowSorter<>(modelR);//creating a new sorter here from my modelR
tableR.setRowSorter(sorter);//set the sorter positon
This allows me to sort on a particular column and order the column.
However the sorter than resets once a refresh takes place:
The refresh process is:
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
String stringfromDateR = tffromDateR.getText();
String stringtoDateR = tftoDateR.getText();
if(source == buttonR){
if(timerR != null) {
System.out.print("cancel");
timerR.cancel();
}
// System.out.print("cancel1bbbbb");
timerR = new Timer();
//auto refresh begins
int delayR = 0; //0 seconds startup delay
int periodR = 7000; //x seconds between refreshes
timerR.scheduleAtFixedRate(new TimerTask()
{
public void run() {
try {
getdataR(stringfromDateR,stringtoDateR);
} catch (IOException | BadLocationException ex) {
Logger.getLogger(JavaApplication63.class.getName()).log(Level.SEVERE, null, ex);
}
}
}, delayR, periodR);
}
if(source == buttonR1){
if(timerR != null) {
timerR.cancel();
}
modelR.setRowCount(0);
}
}
and then
private void getdataR(String stringfromDateR,String stringtoDateR) throws IOException, BadLocationException {
StringBuilder retVal = new StringBuilder();
URL oracle = new URL("XXXXXXXXXXXXXXXXXXXXX" );
BufferedReader in = new BufferedReader(new InputStreamReader(oracle.openStream()));
String newLine = "\n";
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
retVal.append(inputLine).append(newLine);
}
in.close();
passStingR(retVal);
}
How can i get the sorter to retain after the refresh has taken place. Im not sure if setting the
modelR.setRowCount(0);
causes the sorter to lose its sorter position.
I did experiment with get sortkeys but this didnt work, i also experimented with
before the refresh happeened
RowSorter<? extends TableModel> tablesorterpos = tableR.getRowSorter();
and then applying
tableR.setRowSorter(tablesorterpos);
after the refresh but this didnt work
This is what i have tried
private void passStingR(StringBuilder retVal) throws BadLocationException {
RowSorter<TableModel> sorter = new TableRowSorter<>(modelR);//creating a new sorter here from my modelR
List<? extends SortKey> sorterR = sorter.getSortKeys();
int scrollPositionR = scrollR.getVerticalScrollBar().getValue();//get value of scroll position stores in javas memory
windowR.remove(scrollR);
tableR.getModel();
modelR.setRowCount(0);
Document docR = null;
try {
docR = loadXMLFromString(retVal.toString());//pull in the XML data into a new doc
} catch (Exception ex) {
Logger.getLogger(remit.class.getName()).log(Level.SEVERE, null, ex);
}
populate1R(docR);
tableR.getTableHeader().setReorderingAllowed(false);//prevent user from changing column order now at refresh level
SimpleDateFormat time_formatterR = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String current_time_strR = time_formatterR.format(System.currentTimeMillis());
updatetFieldR.setText(current_time_strR);
scrollR.remove(tableR);
tableR = new JTable(modelR)
{
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
Font myFont = new Font("Arial",Font.PLAIN,10);
Font myFont1 = new Font("Arial", Font.BOLD,10);
if (!isRowSelected(row)) {
if (tableR.getColumnCount() >= 0) {
String type = (String) getModel().getValueAt(row, 11);
c.setBackground("0.0".equals(type) ? Color.RED : Color.WHITE);
c.setForeground("0.0".equals(type) ? Color.WHITE : Color.BLACK);
c.setFont("0.0".equals(type) ? myFont1: myFont);
}
}
return c;
};
};
TableColumn column = null;
for (int i = 0; i < 18; i++) {
column = tableR.getColumnModel().getColumn(i);
if (i == 0) {
column.setPreferredWidth(70); //sport column is bigger
}
if (i == 1) {
column.setPreferredWidth(500); //sport column is bigger
}
if (i == 7) {
column.setPreferredWidth(30); //sport column is bigger
}
if (i == 8) {
column.setPreferredWidth(20); //sport column is bigger
}
if (i == 9) {
column.setPreferredWidth(25); //sport column is bigger
}
if (i == 14) {
column.setPreferredWidth(500); //sport column is bigger
}
if (i == 15) {
column.setPreferredWidth(10); //sport column is bigger
}
if (i == 16) {
column.setPreferredWidth(20); //sport column is bigger
}
}
tableR.getTableHeader().setReorderingAllowed(false);//prevent the user from sorting the columns at intialise GUI stage even though the user cannnot change this
sorter.setSortKeys(sorterR);
tableR.setRowSorter(sorter);//set the sorter positon
scrollR = new JScrollPane(tableR);
windowR.add(scrollR);
windowR.validate();
scrollR.getVerticalScrollBar().setValue(scrollPositionR);
}
I get this error:
at javax.swing.DefaultRowSorter.rowsDeleted(DefaultRowSorter.java:880)
at javax.swing.JTable.notifySorter(JTable.java:4276)
at javax.swing.JTable.sortedTableChanged(JTable.java:4120)
at javax.swing.JTable.tableChanged(JTable.java:4397)
at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:296)
at javax.swing.table.AbstractTableModel.fireTableRowsDeleted(AbstractTableModel.java:261)
at javax.swing.table.DefaultTableModel.setNumRows(DefaultTableModel.java:321)
at javax.swing.table.DefaultTableModel.setRowCount(DefaultTableModel.java:339)
at javaapplication63.remit.passStingR(remit.java:238)
at javaapplication63.remit.getdataR(remit.java:227)
at javaapplication63.remit.access$000(remit.java:60)
at javaapplication63.remit$1.run(remit.java:187)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
You can get the current sort keys from the DefaultRowSorter. So the basic logic would be:
getSortKeys()
refresh TableModel
setSortKeys(...)
Edit:
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import javax.swing.*;
import javax.swing.table.*;
public class TableSortSSCCE extends JPanel
{
private String[] columnNames = {"First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian"};
private Object[][] data =
{
{"Kathy", "Smith", "Snowboarding", new Integer(5), new Boolean(false)},
{"John", "Doe", "Rowing", new Integer(3), new Boolean(true)},
{"Sue", "Black", "Knitting", new Integer(2), new Boolean(false)},
{"Jane", "White", "Speed reading", new Integer(20), new Boolean(true)},
{"Joe", "Brown", "Pool", new Integer(10), new Boolean(false)}
};
private JTable table;
public TableSortSSCCE()
{
super(new BorderLayout());
DefaultTableModel model = new DefaultTableModel(data, columnNames);
table = new JTable(model);
table.setPreferredScrollableViewportSize( table.getPreferredSize() );
table.setAutoCreateRowSorter(true);
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane, BorderLayout.CENTER);
JButton clear = new JButton("Clear Table");
clear.addActionListener( new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
DefaultTableModel model = (DefaultTableModel)table.getModel();
model.setRowCount(0);
}
});
add(clear, BorderLayout.NORTH);
JButton reload = new JButton("Reload Table");
reload.addActionListener( new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
TableRowSorter sorter = (TableRowSorter)table.getRowSorter();
List<? extends RowSorter.SortKey> sortKeys = sorter.getSortKeys();
DefaultTableModel model = new DefaultTableModel(data, columnNames);
table.setModel(model);
table.setAutoCreateRowSorter( true );
sorter = (TableRowSorter)table.getRowSorter();
sorter.setSortKeys( sortKeys );
}
});
add(reload, BorderLayout.SOUTH);
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("TableSortSSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TableSortSSCCE newContentPane = new TableSortSSCCE();
frame.setContentPane(newContentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

Error in removeRow in JButton [duplicate]

I want to delete all the rows of DefaultTable. I found two common ways to delete them on internet, but none of them works in my case because those methods does not exist in my DefaultTableModel. I wonder why. My code for using DefaultTableModel is
DefaultTableModel Table = (DefaultTableModel) Table.getModel();
One way to delete is
Table.removeRow(Table.getRowCount() - 1);
but this removerow method does not exist in my DefaultTableModel.
You can set the row count to 0.
setRowCount(0)
Quote from documentation:
public void setRowCount(int rowCount)
Sets the number of rows in the model. If the new size is greater than
the current size, new rows are added to the end of the model If the
new size is less than the current size, all rows at index rowCount and
greater are discarded.
But as you can't find removeRow either I suspect you haven't typed you model variable as DefaultTableModel perhaps, maybe just TableModel?
In that case cast your TableModel to DefaultTableModel like this:
DefaultTableModel model = (DefaultTableModel) table.getModel();
Why complicating simple things, but removes must be iterative,
if (myTableModel.getRowCount() > 0) {
for (int i = myTableModel.getRowCount() - 1; i > -1; i--) {
myTableModel.removeRow(i);
}
}
Code example
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.table.*;
public class RemoveAddRows extends JFrame {
private static final long serialVersionUID = 1L;
private Object[] columnNames = {"Type", "Company", "Shares", "Price"};
private Object[][] data = {
{"Buy", "IBM", new Integer(1000), new Double(80.50)},
{"Sell", "MicroSoft", new Integer(2000), new Double(6.25)},
{"Sell", "Apple", new Integer(3000), new Double(7.35)},
{"Buy", "Nortel", new Integer(4000), new Double(20.00)}
};
private JTable table;
private DefaultTableModel model;
public RemoveAddRows() {
model = new DefaultTableModel(data, columnNames) {
private static final long serialVersionUID = 1L;
#Override
public Class getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
table = new JTable(model) {
private static final long serialVersionUID = 1L;
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
int firstRow = 0;
int lastRow = table.getRowCount() - 1;
int width = 0;
if (row == lastRow) {
((JComponent) c).setBackground(Color.red);
} else if (row == firstRow) {
((JComponent) c).setBackground(Color.blue);
} else {
((JComponent) c).setBackground(table.getBackground());
}
/*if (!isRowSelected(row)) {
String type = (String) getModel().getValueAt(row, 0);
c.setBackground("Buy".equals(type) ? Color.GREEN : Color.YELLOW);
}
if (isRowSelected(row) && isColumnSelected(column)) {
((JComponent) c).setBorder(new LineBorder(Color.red));
}*/
return c;
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
JButton button1 = new JButton("Remove all rows");
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (model.getRowCount() > 0) {
for (int i = model.getRowCount() - 1; i > -1; i--) {
model.removeRow(i);
}
}
System.out.println("model.getRowCount() --->" + model.getRowCount());
}
});
JButton button2 = new JButton("Add new rows");
button2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Object[] data0 = {"Buy", "IBM", new Integer(1000), new Double(80.50)};
model.addRow(data0);
Object[] data1 = {"Sell", "MicroSoft", new Integer(2000), new Double(6.25)};
model.addRow(data1);
Object[] data2 = {"Sell", "Apple", new Integer(3000), new Double(7.35)};
model.addRow(data2);
Object[] data3 = {"Buy", "Nortel", new Integer(4000), new Double(20.00)};
model.addRow(data3);
System.out.println("model.getRowCount() --->" + model.getRowCount());
}
});
JPanel southPanel = new JPanel();
southPanel.add(button1);
southPanel.add(button2);
add(southPanel, BorderLayout.SOUTH);
}
public static void main(String[] args) {
RemoveAddRows frame = new RemoveAddRows();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Have you tried this
This works for me..
defaultTableModel.setRowCount(0);
Why don't you read the javadoc of DefaultTableModel?
public void removeRow(int row)
Removes the row at row from the model. Notification of the row being
removed will be sent to all the listeners.
public void setDataVector(Vector dataVector,
Vector columnIdentifiers)
Replaces the current dataVector instance variable with the new
Vector of rows, dataVector.
public void setRowCount(int rowCount)
Sets the number of rows in the model. If the new size is greater than
the current size, new rows are added to the end of the model If the
new size is less than the current size, all rows at index rowCount and
greater are discarded.
Simply keep removing the table model's first row until there are no more rows left.
// clean table
DefaultTableModel myTableModel = (DefaultTableModel) this.myjTable.getModel();
while (myTableModel.getRowCount() > 0) {
myTableModel.removeRow(0);
}
Ypu can write a method
public void clearTable()
{
getTableModel().setRowCount(0);
}
then call this method from the place that you need to clear the table

Edit Jtable on double click

I need to edit table when user double clicks on row, with new values. I tried with setValuesAt method but it didn't do anything.
This is what I got so far but I don't know how to set new values to Jtable.
public class Table extends JFrame {
private JTable table;
private JScrollPane jsPane;
private DefaultTableModel model;
private JPanel dialogPanel;
private JTextField tf[];
private JLabel lbl[];
private JPanel panel;
Object[] columns = new Object[]{"Name", "Last Name", "ID", "Email"};
Object[][] inData ;
public void prepareAndShowGUI() {
setTitle("Overview");
model = new DefaultTableModel() {
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
model.setColumnIdentifiers(columns);
table = new JTable(model);
for (int i = 1; i <= 10; i++) {
model.addRow(new Object[]{"a", "s", "w", "e"});
}
jsPane = new JScrollPane(table);
table.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
int x = e.getX();
int y = e.getY();
int row = table.rowAtPoint(new Point(x, y));
int col = table.columnAtPoint(new Point(x, y));
String array[] = new String[table.getColumnCount()];
for (int i = 0; i < array.length; i++) {
array[i] = (String) table.getValueAt(row, i);
}
populateTextField(array);
JOptionPane.showMessageDialog(null, dialogPanel, "Information", JOptionPane.INFORMATION_MESSAGE);
String[] values = new String[tf.length];
for (int i = 0; i < tf.length; i++) {
values[i] = tf[i].getText();
}
model.setValueAt(values, row, row);
}
}
});
panel = new JPanel(new BorderLayout());
JPanel panel1 = new JPanel();
panel1.setLayout(new BoxLayout(panel1, BoxLayout.X_AXIS));
panel.add(panel1, BorderLayout.NORTH);
panel.add(jsPane, BorderLayout.CENTER);
getContentPane().add(panel);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
prepareDialogPanel();
setVisible(true);
}
private void prepareDialogPanel() {
dialogPanel = new JPanel();
int col = table.getColumnCount();
dialogPanel.setLayout(new GridLayout(col, 1));
tf = new JTextField[col];
lbl = new JLabel[col];
for (int i = 0; i < col; i++) {
lbl[i] = new JLabel(table.getColumnName(i));
tf[i] = new JTextField(10);
dialogPanel.add(lbl[i]);
dialogPanel.add(tf[i]);
}
}
private void populateTextField(String[] s) {
for (int i = 0; i < s.length; i++) {
tf[i].setText(s[i]);
}
}
}
public static void main(String st[])
{
SwingUtilities.invokeLater( new Runnable()
{
#Override
public void run()
{
Table td = new Table();
td.prepareAndShowGUI();
}
});
}
For starters, you should make your model editable, so change this line:
model = new DefaultTableModel() {
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
To:
model = new DefaultTableModel() {
#Override
public boolean isCellEditable(int row, int column) {
return true; //use the row and col to determine which
//cells are editable. If you want all, have this return true.
}
};
This will invoke the JTable's DefaultCellEditor, which will then call on the model's setValueAt method, when the user has made the change on the edit.
All of these components can be replaced with custom components to perform different actions.
Here's the official Oracle documentation on JTables:
https://docs.oracle.com/javase/tutorial/uiswing/components/table.html
If you're trying to get your dialog to work, the problem is in these line:
String[] values = new String[tf.length];
for (int i = 0; i < tf.length; i++) {
values[i] = tf[i].getText();
}
model.setValueAt(values, row, row);
Basically the setValueAt only works on a cell by cell basis. You can't update a whole row like this. Instead try:
for(int i=0;i<tf.length;i++)
{
model.setValueAt(tf[i].getText(), row, i);
}

Adding icons to jTable in different rows

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:

How to adjust JTable columns to fit the longest content in column cells

I'm using answer https://stackoverflow.com/a/5820366 and http://tips4java.wordpress.com/2008/11/10/table-column-adjuster/ and it works, but frequently columns' sizes are too wide or too narrow.
No matter filling my table with HTML or text.
Using standard TableModel from oracle documentation.
Resize mode = JTable.AUTO_RESIZE_OFF
Container of my tabel is jGoodies:
FormLayout currentEventLayout = new FormLayout(
"fill:p",
"pref, pref");
PanelBuilder currentEventBuilder = new PanelBuilder(currentEventLayout);
currentEventBuilder.add(mainQuotesTable.getTableHeader(), constraints.xy(1, 1));
currentEventBuilder.add(mainQuotesTable, constraints.xy(1, 2));
HTML example:
"<html><pre><font size=+1 face='Arial'>" + firstValue + "\n" + secondValue + "</font></pre></html>"
simple row:
firstValue + " - " + secondValue
Here is the example:
public class TableAdjustExample {
private static JTable mainTable;
private static Random random = new Random();
private static List<Data> data;
private static class Data {
String name;
String surname;
private Data(String name, String surname) {
this.name = name;
this.surname = surname;
}
}
public static void main(String[] args) {
data = stubProvider();
final JFrame frame = new JFrame("table adjust example");
frame.add(createUI());
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(350, 400);
frame.setVisible(true);
update();
java.util.Timer timer = new java.util.Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
update();
}
}, 3000, 3000);
}
private static JPanel createUI() {
JPanel jPanel = new JPanel();
mainTable = new JTable(2, 3);
mainTable.setModel(new AbstractTableModel() {
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return 2;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Data dataItem = data.get(rowIndex);
if (columnIndex == 0) {
return dataItem.name;
}
if (columnIndex == 1) {
return dataItem.surname;
}
throw new IllegalStateException();
}
});
mainTable.setGridColor(Color.black);
mainTable.setShowHorizontalLines(false);
mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
final TableCellRenderer defaultRenderer = mainTable.getTableHeader().getDefaultRenderer();
mainTable.getTableHeader().setDefaultRenderer(new TableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable jTable, Object o, boolean b, boolean b1, int row, int column) {
JLabel parent = (JLabel) defaultRenderer.getTableCellRendererComponent(jTable, o, b, b1, row, column);
if (column == 0) {
parent.setText("name");
} else {
parent.setText("surname");
}
return parent;
}
});
jPanel.add(mainTable.getTableHeader());
jPanel.add(mainTable);
return jPanel;
}
private static void update() {
System.out.println("updating");
data = stubProvider();
adjustJTableRowSizes(mainTable);
for (int i = 0; i < mainTable.getColumnCount(); i++) {
adjustColumnSizes(mainTable, i, 2);
}
}
private static void adjustJTableRowSizes(JTable jTable) {
for (int row = 0; row < jTable.getRowCount(); row++) {
int maxHeight = 0;
for (int column = 0; column < jTable.getColumnCount(); column++) {
TableCellRenderer cellRenderer = jTable.getCellRenderer(row, column);
Object valueAt = jTable.getValueAt(row, column);
Component tableCellRendererComponent = cellRenderer.getTableCellRendererComponent(jTable, valueAt, false, false, row, column);
int heightPreferable = tableCellRendererComponent.getPreferredSize().height;
maxHeight = Math.max(heightPreferable, maxHeight);
}
jTable.setRowHeight(row, maxHeight);
}
}
public static void adjustColumnSizes(JTable table, int column, int margin) {
DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel();
TableColumn col = colModel.getColumn(column);
int width;
TableCellRenderer renderer = col.getHeaderRenderer();
if (renderer == null) {
renderer = table.getTableHeader().getDefaultRenderer();
}
JLabel comp = (JLabel) renderer.getTableCellRendererComponent(
table, col.getHeaderValue(), false, false, 0, 0);
width = comp.getPreferredSize().width;
for (int r = 0; r < table.getRowCount(); r++) {
renderer = table.getCellRenderer(r, column);
comp = (JLabel) renderer.getTableCellRendererComponent(
table, table.getValueAt(r, column), false, false, r, column);
int currentWidth = comp.getPreferredSize().width;
width = Math.max(width, currentWidth);
}
width += 2 * margin;
col.setPreferredWidth(width);
}
private static List<Data> stubProvider() {
List<Data> data = new ArrayList<Data>();
for (int i = 0; i < 4; i++) {
data.add(new Data(
"<html>" +
"<div style='font-size: 15px'>Jason</div>" +
"<div style='font-size: 15px'>" + random.nextInt() + "</div>" +
"</html>",
"Statham " + random.nextInt()));
}
return data;
}
}
I have such problem with row height adjustment. Using of <pre>\n</pre> instead of <br> fixed row adjustment.
Seems to be working okay for me...
public class TestTable01 extends JPanel {
private JTable mainTable;
public TestTable01() {
super(new GridLayout(1, 0));
String[] columnNames = {"First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian"};
Object[][] data = {
{"Kathy", "Smith",
"Snowboarding", new Integer(5), new Boolean(false)},
{"John", "Doe",
"Rowing", new Integer(3), new Boolean(true)},
{"Sue", "Black",
"Knitting", new Integer(2), new Boolean(false)},
{"Jane", "White",
"Speed reading", new Integer(20), new Boolean(true)},
{"Joe", "Brown",
"Pool", new Integer(10), new Boolean(false)}
};
mainTable = new JTable(data, columnNames);
mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
mainTable.setPreferredScrollableViewportSize(new Dimension(500, 70));
mainTable.setFillsViewportHeight(true);
update();
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(mainTable);
//Add the scroll pane to this panel.
add(scrollPane);
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("SimpleTableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TestTable01 newContentPane = new TestTable01();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
private void update() {
System.out.println("updating");
adjustJTableRowSizes(mainTable);
for (int i = 0; i < mainTable.getColumnCount(); i++) {
adjustColumnSizes(mainTable, i, 2);
}
}
private void adjustJTableRowSizes(JTable jTable) {
for (int row = 0; row < jTable.getRowCount(); row++) {
int maxHeight = 0;
for (int column = 0; column < jTable.getColumnCount(); column++) {
TableCellRenderer cellRenderer = jTable.getCellRenderer(row, column);
Object valueAt = jTable.getValueAt(row, column);
Component tableCellRendererComponent = cellRenderer.getTableCellRendererComponent(jTable, valueAt, false, false, row, column);
int heightPreferable = tableCellRendererComponent.getPreferredSize().height;
maxHeight = Math.max(heightPreferable, maxHeight);
}
jTable.setRowHeight(row, maxHeight);
}
}
public void adjustColumnSizes(JTable table, int column, int margin) {
DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel();
TableColumn col = colModel.getColumn(column);
int width;
TableCellRenderer renderer = col.getHeaderRenderer();
if (renderer == null) {
renderer = table.getTableHeader().getDefaultRenderer();
}
Component comp = renderer.getTableCellRendererComponent(table, col.getHeaderValue(), false, false, 0, 0);
width = comp.getPreferredSize().width;
for (int r = 0; r < table.getRowCount(); r++) {
renderer = table.getCellRenderer(r, column);
comp = renderer.getTableCellRendererComponent(table, table.getValueAt(r, column), false, false, r, column);
int currentWidth = comp.getPreferredSize().width;
width = Math.max(width, currentWidth);
}
width += 2 * margin;
col.setPreferredWidth(width);
col.setWidth(width);
}
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();
}
});
}
}
UPDATED
There are a number of issues with your example.
Tables really should be added to a JScrollPane, this will take care of adding the header...
The default layout manager for a JPanel is FlowLayout, in this case, it's probably not what you want, you probably want to use a BorderLayout
Swing is not thread safe. The user of java.util.Timer will violate this policy, this could cause the model and view to fall out sync. Use a javax.swing.Timer instead.
Rendering two <div> next to each will cause the html layout engine to place a weak break between the elements. That is, if the engine decides there's not enough available space to render the two elements together, it will split them. Better to use a single <div> with two <span> tags instead...
I would have a read of
Concurrency in Swing
How to Use Tables
public class TestColumnWidths {
private static JTable mainTable;
private static Random random = new Random();
private static List<Data> data;
private static class Data {
String name;
String surname;
private Data(String name, String surname) {
this.name = name;
this.surname = surname;
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
data = stubProvider();
final JFrame frame = new JFrame("table adjust example");
frame.add(createUI());
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
update();
// java.util.Timer timer = new java.util.Timer();
// timer.schedule(new TimerTask() {
// #Override
// public void run() {
// update();
// }
// }, 3000, 3000);
javax.swing.Timer timer = new javax.swing.Timer(3000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
update();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
});
}
private static JPanel createUI() {
JPanel jPanel = new JPanel();
mainTable = new JTable(2, 3);
mainTable.setModel(new AbstractTableModel() {
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return 2;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Data dataItem = data.get(rowIndex);
if (columnIndex == 0) {
return dataItem.name;
}
if (columnIndex == 1) {
return dataItem.surname;
}
throw new IllegalStateException();
}
});
mainTable.setGridColor(Color.black);
mainTable.setShowHorizontalLines(false);
mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
final TableCellRenderer defaultRenderer = mainTable.getTableHeader().getDefaultRenderer();
mainTable.getTableHeader().setDefaultRenderer(new TableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable jTable, Object o, boolean b, boolean b1, int row, int column) {
JLabel parent = (JLabel) defaultRenderer.getTableCellRendererComponent(jTable, o, b, b1, row, column);
if (column == 0) {
parent.setText("name");
} else {
parent.setText("surname");
}
return parent;
}
});
// jPanel.add(mainTable.getTableHeader());
// jPanel.add(mainTable);
jPanel.setLayout(new BorderLayout());
jPanel.add(new JScrollPane(mainTable));
return jPanel;
}
private static void update() {
System.out.println("updating");
data = stubProvider();
adjustJTableRowSizes(mainTable);
for (int i = 0; i < mainTable.getColumnCount(); i++) {
adjustColumnSizes(mainTable, i, 2);
}
}
private static void adjustJTableRowSizes(JTable jTable) {
for (int row = 0; row < jTable.getRowCount(); row++) {
int maxHeight = 0;
for (int column = 0; column < jTable.getColumnCount(); column++) {
TableCellRenderer cellRenderer = jTable.getCellRenderer(row, column);
Object valueAt = jTable.getValueAt(row, column);
Component tableCellRendererComponent = cellRenderer.getTableCellRendererComponent(jTable, valueAt, false, false, row, column);
int heightPreferable = tableCellRendererComponent.getPreferredSize().height;
maxHeight = Math.max(heightPreferable, maxHeight);
}
jTable.setRowHeight(row, maxHeight);
}
}
public static void adjustColumnSizes(JTable table, int column, int margin) {
DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel();
TableColumn col = colModel.getColumn(column);
int width;
TableCellRenderer renderer = col.getHeaderRenderer();
if (renderer == null) {
renderer = table.getTableHeader().getDefaultRenderer();
}
Component comp = renderer.getTableCellRendererComponent(
table, col.getHeaderValue(), false, false, 0, 0);
width = comp.getPreferredSize().width;
for (int r = 0; r < table.getRowCount(); r++) {
renderer = table.getCellRenderer(r, column);
comp = renderer.getTableCellRendererComponent(
table, table.getValueAt(r, column), false, false, r, column);
int currentWidth = comp.getPreferredSize().width;
width = Math.max(width, currentWidth);
}
width += 2 * margin;
col.setPreferredWidth(width);
}
private static List<Data> stubProvider() {
List<Data> data = new ArrayList<Data>();
for (int i = 0; i < 4; i++) {
data.add(new Data(
"<html>"
+ "<div>"
+ "<span style='font-size: 15px'>Jason</span>"
+ "<span style='font-size: 15px'>" + random.nextInt() + "</span>"
+ "</div>"
+ "</html>",
"Statham " + random.nextInt()));
}
return data;
}
}
Set reasonable MinimumWidth for the columns which are too narrow. Then calculate width according to the contents of the columns and set them.

Categories