Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

JTable, JScrollPane and empty space

1,893 views
Skip to first unread message

A. W. Dunstan

unread,
Jan 10, 2012, 4:55:48 PM1/10/12
to
I have an application where I want to have two JTables (one above the other)
in a single JPanel. Both tables have enough data that their containing
JScrollPanes kick in & show a scroll bar (in the window's initial
configuration) but if I make the window tall enough I can see all rows of
both tables (& the scroll bars go away). The number of rows in each table
is different and fixed.

As the window gets taller the tables also get taller, showing more and more
rows (which is what I want). The problem occurs when the window gets more
than tall enough for all rows of a table to be seen - the containing
JScrollPane continues to get taller, leaving a (sometimes large) blank area
below the JTable. The extra space is distributed evenly across both
JScrollPanes, even though one no longer needs it.

How do I make a JScrollPane stop growing when it's big enough to display all
rows of it's table?

Once a table is showing all it's rows I'd like the additional space to be
distributed to other components that could grow taller (like other
JScrollPane/JTables that aren't yet showing all their rows). Once all
components are as tall as they need to be I'd like the additional space to
be distributed between components.

Any ideas?



I'm currently using a GridBagLayout with GridBagContraints set as follows:

JTable table = new JTable(the_table_model);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setPreferredSize(new Dimension(400, 100));
scrollPane.setMinimumSize(new Dimension(200, 50));
// m_gbc is a GridBagContraints
m_gbc.fill = GridBagConstraints.BOTH;
m_gbc.weighty = 1;
m_gbc.weightx = 1;
// m_gbl is a GridBagLayout
m_gbl.setConstraints(scrollPane, m_gbc);
m_settings.add(scrollPane);

I have a straightforward example I can post but at 145 lines I'm hesitant to
do so unless someone asks for it.

I'd be more than happy to switch to some other layout manager if that's
needed.

--
Al Dunstan, Software Engineer

markspace

unread,
Jan 10, 2012, 10:43:40 PM1/10/12
to
On 1/10/2012 1:55 PM, A. W. Dunstan wrote:

> I'd be more than happy to switch to some other layout manager if that's
> needed.


I'd take a look at your 145 line example. That's not too many lines,
and I have a feeling it's not in your layout anyway.



Message has been deleted

A. W. Dunstan

unread,
Jan 11, 2012, 9:12:44 AM1/11/12
to
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class Sandbox extends JFrame {

public Sandbox(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setLayout(new BorderLayout());
m_settings = new JPanel();

m_gbc = new GridBagConstraints();
m_gbc.gridx = 0;
m_gbc.gridy = 0;
m_gbc.anchor = GridBagConstraints.WEST;
m_gbc.insets = new Insets(2, 5, 2, 5);
m_gbl = new GridBagLayout();
m_settings.setLayout(m_gbl);
add(m_settings, BorderLayout.CENTER);

// Title across the top
JLabel l = new JLabel("Range?");
m_gbl.setConstraints(l, m_gbc);
m_settings.add(l);

m_gbc.gridx++;
l = new JLabel("Parameter");
m_gbl.setConstraints(l, m_gbc);
m_settings.add(l);

m_gbc.gridx++;
l = new JLabel("Value");
m_gbl.setConstraints(l, m_gbc);
m_settings.add(l);

m_gbc.gridy++;

// First table
addTable("ATM", new DummyTableModel(6));

// Second table
addTable("ICLD", new DummyTableModel(15));
}

private void addTable(String label, TableModel tm) {
JScrollPane scrollPane = new JScrollPane(new JTable(tm));
//scrollPane.setPreferredSize(new Dimension(400, 100));
//scrollPane.setMinimumSize(new Dimension(200, 50));
m_gbc.fill = GridBagConstraints.BOTH;
m_gbc.weighty = 1;
m_gbc.weightx = 1;
addNonRangeComponent(label, scrollPane);
}


protected void addNonRangeComponent(final String paramName,
final JComponent component) {
m_gbc.gridx = 1;
m_gbc.gridy++;

// Label what we're showing.
JLabel quantity = new JLabel(paramName);
m_gbl.setConstraints(quantity, m_gbc);
m_settings.add(quantity);
m_gbc.gridx++;

// Show the parameter.
m_gbl.setConstraints(component, m_gbc);
m_settings.add(component);
}


// Where we put things & how they're laid out.
private JPanel m_settings;
private GridBagLayout m_gbl;
private GridBagConstraints m_gbc;


public static void main(String[] args) {
Sandbox sb = new Sandbox("New Range Layout Sandbox");
sb.setVisible(true);
sb.pack();
}

}





/**
* Simple table model. First column is 'is selected?', 2nd column is a
* description of what's selected. 1st column is boolean & editable, 2nd
* is String & not editable.
*/
class DummyTableModel extends AbstractTableModel {

public DummyTableModel(int nRows) {
m_isSelected = new boolean[nRows];
}

public int getRowCount() { return m_isSelected.length; }

public int getColumnCount() { return 2; }

public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0: return m_isSelected[rowIndex];
case 1: return "The value for this row is " + rowIndex;
default: return null;
}
}

public String getColumnName(int column) {
switch (column) {
case 0: return "Selected?";
case 1: return "Description";
default: return "Oops";
}
}

public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0: return Boolean.class;
case 1: return String.class;
default: return null;
}
}

public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 0;
}

public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Boolean b = (Boolean)aValue;
m_isSelected[rowIndex] = b.booleanValue();
}

final private boolean[] m_isSelected;

markspace

unread,
Jan 11, 2012, 4:08:28 PM1/11/12
to
I think I see what is going on. I haven't double checked (modified the
code to see if I'm right) but I think the issue is that you are adding
components horizontally. That is you add the label and the table in one
row, and then you add another label and table for the next row.

That would allow the components to expand horizontally, if they needed
to, but you want the tables to be able to expand vertically. So the
basic approach isn't going to work.

Take a look at this example from the tutorial. Notice that button 4
spans three cells in the grid bag layout and expands as needed:

<http://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html>

What you want to do I think is take John's suggestion to use something
like a Box or Flow layout. Make a JPanel, and make it the last
component (or only component) in the last column, like button 4 is the
only component in the tutorial example. Then instead of adding the
tables to the grid layout directly, you'll add them to the panel.

That should let the panel expand up and down, like button 4 does, but
also its layout (box or flow) will scoot the tables up and down as
needed. Grid bag is a *grid*, so it always tries to keep things lined
up. They can't flow up and down as needed on their own with just grid bag.

In general, this is an easy way to make layouts do what you want,
composing layouts out of other, smaller layout components. I find it
easier to "see" what the components will do, rather than trying to find
one big layout that does everything you want.

You might also be better served by other layouts, like Spring, but it's
hard to say as I don't know your actual requirements. Making the last
component in your existing layout into a JPanel and adding the tables to
that is the least intrusive change I can think of.


A. W. Dunstan

unread,
Jan 12, 2012, 11:16:37 AM1/12/12
to
Thanks for looking - I'll give those a try.

The 'full-sized' version of this has a grid of several different components,
used for entering parameters that will then be fed to an engineering
simulation package. The 1st column (not shown in my sample code) is either
empty or a checkbox, the 2nd is a label (tells the user what value they're
entering and it's units), the 3rd column is the value they'll enter. The
JTables are for enumerated values; I use JSpinners for scalar values, and a
custom component for when the user wants to run the simulation over a range
of values (height of 20 meters vs height of {10, 20, 30, 40, 50} meters).
The checkbox lets the user switch between scalar and range-of-values.

So the underlying problem is pretty much grid oriented, which led me to
GridBagLayout initially. GridLayout wants to make all the rows the same
height & all the columns the same width, but my rows are of varying heights
(ditto the columns). I didn't think nested BoxLayouts would keep the rows
_and_ columns lined up. GroupLayout is a possibility.

thanks again!


wrote:
--
Al Dunstan, Software Engineer
OptiMetrics, Inc.
3115 Professional Drive
Ann Arbor, MI 48104-5131

"There are two ways of constructing a software design. One way is to
make it so simple that there are obviously no deficiencies. And the
other way is to make it so complicated that there are no obvious
deficiencies."
- C. A. R. Hoare
0 new messages