Hello,
I have an app that displays lots of information in JTables. At program
start, the tables are empty and are later filled based on user
actions. My problem is that the JScrollPane in which the tables are
placed are not changed in size when the table size changes.
THe program below illustrates what I mean. When you click the button,
rows are added as expected, but the JScrollPane remains unchanged.
Since in my real program, the tables are empty at the beginning, I
don´t even see the scrollbars, only the column headers.
Many thanks for your help
Piet
Code snippet:
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
public class ResizingTable extends JFrame implements ActionListener{
JTable table;
GridBagLayout iGBL = new GridBagLayout();
GridBagConstraints iGBC = new GridBagConstraints();
JScrollPane tablePane;
ResizingTable(){
super("Resizing Table Test");
this.getContentPane().setLayout(iGBL);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
table = new JTable();
table.setModel(new ResizingTableModel());
((ResizingTableModel)(table.getModel())).update(5);
tablePane = new JScrollPane(table);
tablePane.getViewport().setPreferredSize(table.getPreferredSize());
addGBL(tablePane,0,0,1,1,5,GridBagConstraints.NONE,GridBagConstraints.WEST);
JButton addButton = new JButton("Add Row");
addButton.addActionListener(this);
addGBL(addButton,0,1,1,1,5,GridBagConstraints.NONE,GridBagConstraints.WEST);
}
public void addGBL(JComponent component,int xpos,int ypos,int
width,int height,int border, int fill,int anchor){
iGBC.gridx = xpos;
iGBC.gridy = ypos;
iGBC.gridwidth = width;
iGBC.gridheight = height;
iGBC.ipadx = border;
iGBC.fill = fill;
iGBC.anchor = anchor;
iGBL.setConstraints(component,iGBC);
this.getContentPane().add(component);
}
public void actionPerformed(ActionEvent e){
((ResizingTableModel)(table.getModel())).appendEntry();
table.revalidate();
tablePane.getViewport().setPreferredSize(table.getPreferredSize());
}
public static void main(String[] args){
ResizingTable resizingtable = new ResizingTable();
resizingtable.setSize(new Dimension(500,500));
resizingtable.show();
}
}
class ResizingTableModel extends AbstractTableModel{
public String[] headers = new String[5];
public ArrayList data;
private int columnNumber;
public ResizingTableModel(){
data = new ArrayList();
this.headers[0] = "Data";
this.headers[1] = "x1";
this.headers[2] = "y1";
this.headers[3] = "x2";
this.headers[4] = "y2";
}
public void update(int number){
data = new ArrayList();
for (int i=0;i<number;i++){
ArrayList row = new ArrayList();
row.add("This");
row.add("is");
row.add("a");
row.add("new");
row.add("row");
this.data.add((Object)(row));
++columnNumber;
}
this.fireTableRowsInserted(0,columnNumber);
}
public void appendEntry(){
ArrayList row = new ArrayList();
row.add("This");
row.add("is");
row.add("an");
row.add("appended");
row.add("row");
this.data.add((Object)(row));
this.fireTableRowsInserted(0,0);
System.out.println("Row inserted!");
System.out.println("New Data:");
System.out.println(this.data);
++this.columnNumber;
this.fireTableRowsInserted(0,1);
}
public int getRowCount(){
return this.columnNumber;
}
public int getColumnCount(){
return 5;
}
public String getColumnName(int colNum){
return headers[colNum];
}
public Object getValueAt(int rowNum,int colNum){
ArrayList row = (ArrayList)(this.data.get(rowNum));
return row.get(colNum);
}
}
Christian Kaufhold - 02 Apr 2005 18:29 GMT
> I have an app that displays lots of information in JTables. At program
> start, the tables are empty and are later filled based on user
[quoted text clipped - 27 lines]
> ((ResizingTableModel)(table.getModel())).update(5);
> tablePane = new JScrollPane(table);
> tablePane.getViewport().setPreferredSize(table.getPreferredSize());
Problem 1 is that JScrollPane isValidateRoot(), i.e. unless something
drastic changes like the window being resized, it will stay at the
size is once (initially) has gotten, even if its preferred (or minimum,
or maximum) size changes, even if incompatibly with its present size.
So JScrollPane relies on initially getting a "good" size because it will
rarely change afterwards. If it must, use
((JComponent)scrollPane.getParent()).revalidate();
Problem 2 is the line above which fixes the initial preferred size at the
*current* preferred size of the table (which is very small). Instead over-
ride getPreferredScrollableViewportSize (or use setPreferredScrollable-
ViewportSize) and use some proper initial value for the height.
Problem 3 is GridBagLayout.
Christian
Piet - 05 Apr 2005 16:08 GMT
Christian,
thanks for your answer.
> Problem 1 is that JScrollPane isValidateRoot(), i.e. unless something
> drastic changes like the window being resized, it will stay at the
[quoted text clipped - 3 lines]
> rarely change afterwards. If it must, use
> ((JComponent)scrollPane.getParent()).revalidate();
> Problem 2 is the line above which fixes the initial preferred size at the
> *current* preferred size of the table (which is very small). Instead over-
> ride getPreferredScrollableViewportSize (or use setPreferredScrollable-
> ViewportSize) and use some proper initial value for the height.
Thats my current solution. In fact, I have come to believe that if the
autoresizing JScrollPanes could have been realized, they would have
probably created a little too much noise. Now thinks look prettey
good.
Many thanks
Piet