I'm resizing my columns according to their data with the following:
/**
* Set the widths of the columns in the table according to the data in the table.
* #param table
*/
private static void setColumnWidths(JTable table)
{
int columnCount = table.getModel().getColumnCount();
int rowCount = table.getModel().getRowCount();
TableColumnModel columnModel = table.getColumnModel();
for (int col=0; col<columnCount; col++)
{
TableColumn column = columnModel.getColumn(col);
TableCellRenderer renderer = column.getCellRenderer();
if (renderer == null)
{
renderer = new DefaultTableCellRenderer();
}
int overallColumnWidth = 0;
for (int row = 0; row < rowCount; row++)
{
Object value = table.getValueAt(row, col);
Component component = renderer.getTableCellRendererComponent(table, value, false, false, row, col);
int componentWidth = (int) component.getPreferredSize().getWidth();
overallColumnWidth = Math.max(componentWidth, overallColumnWidth);
}
column.setPreferredWidth(overallColumnWidth);
}
}
This works when all the columns are visible, but I've got code that hides some of them (JTable.removeColumn(TableColumn column)). It appears that both the JTable instance and the TableColumnModel instance have the list of data columns, i.e., all columns regardless of visibility. How can I get a list of only columns that are visible, or test whether a given column is visible?
(I've searched for this, but get longs lists of articles on how to hide the columns, and no explanation of where the visible/invisible information is kept. I thought, since I asked the JTable to hide the column, that somewhere in there it would know which columns were hidden and I could get that info.)
Check if table.convertColumnIndexToView(col) returns -1.
From the documentation:
public int convertColumnIndexToView(int modelColumnIndex)
Maps the index of the column in the table model at modelColumnIndex to
the index of the column in the view. Returns the index of the
corresponding column in the view; returns -1 if this column is not
being displayed. If modelColumnIndex is less than zero, returns
modelColumnIndex.
Source
The problem with your code if that your loops is controlled by the values returned in the TableMdoel.
Instead you should be using values from the table:
int rowCount = table.getRowCount();
int columnCount = table.getRowCount();
Then there is no need for exception logic to determine if a column is visible or not because by default it will be visible because it is the job of the view (JTable) to only display visible columns.
You need to understand the difference between the "view" and the "model".
how do I determine which columns in a JTable are visible
So the better answer is to use the methods of the JTable. Your current solution confuses the view and model.
You could also use the Table Column Adjuster to do the column adjustment for you. It provides features like dynamically resizing the column as the data changes.
Related
This question already has answers here:
How to get cell value of jtable depending on which row is clicked
(2 answers)
Closed 7 years ago.
When I double click the cell of the JTable, I want it to take the value of that cell and write it in the textfield. What should I do? Here is what I have tried so far, but I don't know where to go from here:
table_1.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
JTable table = (JTable) me.getSource();
Point p = me.getPoint();
int row = table.rowAtPoint(p);
if (me.getClickCount() == 2) {
textfield.settext(???????????);
}
}
});
i understand how it works:
int row = table.rowAtPoint(p);
int column = table.columnAtPoint(p);
textfield.settext(table_1.getValueAt(row, column));
Jtable table = (JTable)e.getsource();
int row = table.getSelectedRow();
int column = table.getSelectedColumn();
ObjectType o = (ObjectType)target.getValueAt(row, column) );
Do this. Will get the value in your JTable based on the row and column selected and then casts the returned value to your object type in the table and returns the value at the row, column. This is inside your Listener.
Shown in similar question Possible Dup?
You can get the value of the table by using:
table.getModel().getValueAt(row, col);
where
row - the row whose value is to be queried
col - the column whose value is to be queried
table - your object name (class jTable)
Note: The column is specified in the table view's display order, and not in the TableModel's column order. This is an important
distinction because as the user rearranges the columns in the table,
the column at a given index in the view will change. Meanwhile the
user's actions never affect the model's column ordering.
In addition, I recommend to read this documentation.
Try to write something like this:
table.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(final MouseEvent e) {
if (e.getClickCount() == 1) {
final JTable jTable= (JTable)e.getSource();
final int row = jTable.getSelectedRow();
final int column = jTable.getSelectedColumn();
final String valueInCell = (String)jTable.getValueAt(row, column);
textfield.setText(valueInCell);
}
});
I need my JTable to automatically re-size its column widths to fit the content. I found the TableColumnAdjuster class very useful. But there's a small problem. Say i have 5 columns, and their content is very short. In that case, if i use the auto adjuster, it sets the first four columns widths according to their content and gives all the rest of space to the last column. Please see the example.
Here the last column, Balance is given all the excess space. But what if i need to give that space to one of the middle columns. In the above case, i need to assign that space to the third column, name. I tried modifying the TableColumnAdjuster class's adjustColumns() method. But I couldn't get it working.
I tried both column.setPreferredWidth() and column.setWidth() for changing column sizes. But seems it doesn't change anything. How can I effectively change the column sizes of a JTable. If there's some other alternative or a direct answer to my main problem, that's better. Thanks!
You can try the next:
public void resizeColumnWidth(JTable table) {
final TableColumnModel columnModel = table.getColumnModel();
for (int column = 0; column < table.getColumnCount(); column++) {
int width = 15; // Min width
for (int row = 0; row < table.getRowCount(); row++) {
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component comp = table.prepareRenderer(renderer, row, column);
width = Math.max(comp.getPreferredSize().width +1 , width);
}
if(width > 300)
width=300;
columnModel.getColumn(column).setPreferredWidth(width);
}
}
This needs to be executed before the resize method.
If you have:
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
There is no option to automatically resize one column larger than the other.
Maybe you can to something like:
tca = new TableColumnAdjuster( table, 0 );
tca.adjustColumns();
TableColumnModel tcm = table.getColumnModel();
TableColumn tc = tcm.getColumn(1);
tc.setWidth(tc.getWidth() + 25);
This would allow you to add extra space to column 1. This extra space would only be added the first time the table is displayed.
Another option is to use:
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
This would allocate extra space proportionally to each column.
setAutoResizeMode() will tell your table how to resize you should give it a try will all different options available to see the differences, in My case I wanted to specifically resize two columns and let it decide how to adjust all the other ones.
jTable1.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
TableColumnModel colModel=jTable1.getColumnModel();
colModel.getColumn(1).setPreferredWidth(25);
colModel.getColumn(2).setPreferredWidth(400);
You can do this:
JPanel jp = new JPanel();
jp.add(table);
jp.setLayout(new GridLayout(1,1)); /* little trick ;) and believe me that this step is important to the automatic all columns resize! A import is also needed for using GridLayout*/
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); // this is obvius part
With a slight modification to Paul Vargas's answer, you can also take into account the column header size:
public static void resizeColumnWidth(JTable table) {
final TableColumnModel columnModel = table.getColumnModel();
for (int column = 0; column < table.getColumnCount(); column++) {
// Account for header size
double width = table.getTableHeader().getHeaderRect(column).getWidth();
for (int row = 0; row < table.getRowCount(); row++) {
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component comp = table.prepareRenderer(renderer, row, column);
width = Math.max(comp.getPreferredSize().width + 1, width);
}
if (width > 300)
width = 300;
columnModel.getColumn(column).setPreferredWidth((int) width);
}
}
So I have a JTable with 24 columns. When the table is initialized, I make set the widths of the columns and the user interface looks great. No complaints. The user can click a button to only see 4 of the columns. I change the array of columns on the table model and then call
firetablestructurechanged()
which then removes all of the column widths I established (but now only shows the 4 columns, the intended behavior). When I try re-defining the column widths, nothing seems to change.
This is what I use to set column widths
TableColumnModel columnModel = table.getColumnModel();
for (int i = 1; i < columnModel.getColumnCount(); i++) {
columnModel.getColumn(i).setMinWidth(50);
columnModel.getColumn(i).setMaxWidth(50);
}
How do I get the columns to resize after firetablestructurechanged() gets called?
I have a sortable JTable set up to use a custom extension of the AbstractTableModel. However, some behavior of this table is what I expected, and I would love some advice on how to figure this out.
I have the JTable set up to be sortable using:
thisJTable.setAutoCreateRowSorter(true);
This allows me to sort the table by clicking on the column headers as expected.
However, I find that when I sort the table by clicking on the column headers, the formatting (background and foreground color) of my rows are not sorted as well.
I had set up those rows to be color-coded based on the values they contain. When I sort by column header the formatting at a given row NUMBER stays the same (although the content that was previously in that row moved).
The color of the row is set by overriding the default prepareRenderer call for the JTable:
thisTable = new JTable(thisModel){
//Set up custom rendering - Sets background color of row to correct value
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
CustTableModel thisModel = (CustTableModel) getModel();
c.setBackground(thisModel.getRowBackgroundColor(row));
c.setForeground(thisModel.getRowForeColor(row));
return c;
}
};
Is there a better/different way to approach this?
Should I be using a different method to do my rendering, a method which would update the rendering of the JTable on a sort?
Or do I want to look into writing my own sorting method?
Solution (Thanks mKorbel!)
I thought I would post my solution, since I had to play with this a bit since I wasn't sure if the new index would be passed to the prepareRenderer as well.
thisTable = new JTable(thisModel){
//Set up custom rendering - Sets background color of row to correct value
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
int viewIdx = row;
int modelIdx = convertRowIndexToModel(viewIdx);
Component c = super.prepareRenderer(renderer, row, column);
CustTableModel thisModel = (CustTableModel) getModel();
c.setBackground(thisModel.getRowBackgroundColor(modelIdx));
c.setForeground(thisModel.getRowForeColor(modelIdx));
return c;
}
};
you have to convert row index from View to the Model
int modelRow = convertRowIndexToModel(row);
You can enable table sorting by clicking on header using this
table.setAutoCreateRowSorter(true);
for more information visit this site http://www.codejava.net/java-se/swing/6-techniques-for-sorting-jtable-you-should-know
I am trying to display the data of hidden column as tooltip. Hiding is working perfectly using the following code:
JTable table = new JTable(model){
//Implement table cell tool tips.
public String getToolTipText(MouseEvent e) {
String tip = null;
java.awt.Point p = e.getPoint();
int rowIndex = rowAtPoint(p);
int colIndex = columnAtPoint(p);
int realColumnIndex = convertColumnIndexToModel(colIndex);
try {
tip = getValueAt(rowIndex, 8).toString();
} catch (RuntimeException e1) {
//catch null pointer exception if mouse is over an empty line
}
return tip;
}
};
TableColumnModel tcm = table.getColumnModel();
TableColumn tc;
for(int i = 1; i <= 7; i++){
tc = tcm.getColumn(8);
tcm.removeColumn(tc);
}
But the tooltip is not showing the data of hidden column (getValue function is not returning value). So do hiding the column delete the data as well ?
You do not need to for loop as you do not use the i variable ;-)
The removeColumn on the JTable does not remove the data from the model, as clearly stated in the javadoc
Removes aColumn from this JTable's array of columns. Note: this method does not remove the column of data from the model; it just removes the TableColumn that was responsible for displaying it.
There is no mention in the javadoc for the same method on the TableColumnModel, but I would assume it works the same way, but you can always give it a try to call it on the JTable instead
The real problem in your code is the use of getValueAt, which uses the row and column index of the table, and not of the model
Note: The column is specified in the table view's display order, and not in the TableModel's column order. This is an important distinction because as the user rearranges the columns in the table, the column at a given index in the view will change. Meanwhile the user's actions never affect the model's column ordering.
And since you removed that column, it simply does not exists for the table. Call the getValue method on the model instead, and do not forget to convert the row index