I want to imitate a table with scroll bar, but there is a problem with width. Here is an extremely simplified code (but it is complete application, so you can compile it easilly and see everything at first hand).
package view;
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import net.miginfocom.layout.AC;
import net.miginfocom.layout.CC;
import net.miginfocom.layout.LC;
import net.miginfocom.swing.MigLayout;
public class AppView
{
private final JFrame main_frame;
public AppView()
{
main_frame = new JFrame();
main_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main_frame.setTitle("Example");
JPanel main_panel = new JPanel() {
private static final long serialVersionUID = 1L;
public Dimension getPreferredSize()
{
return new Dimension(300, 200);
}
};
main_panel.setLayout(new MigLayout("fill"));
JPanel table_panel = new JPanel();
table_panel.setLayout(new MigLayout(new LC(), new AC().gap("0"), new AC().gap("0")));
JScrollPane scroll_pane = new JScrollPane(table_panel);
scroll_pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
int[] width_arr = {20, 20, 20, 20, 20};
for (int i = 0; i < 60; i++) {
for (int j = 0; j < width_arr.length; j++) {
if (j == width_arr.length - 1)
table_panel.add(new JLabel(i + 1 + ", " + (j + 1)), new CC().width(width_arr[j] + "%").wrap());
else
table_panel.add(new JLabel(i + 1 + ", " + (j + 1)), new CC().width(width_arr[j] + "%"));
}
}
main_frame.getContentPane().add(main_panel, BorderLayout.CENTER);
main_panel.add(scroll_pane, new CC().grow());
main_frame.pack();
main_frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new AppView();
}
});
}
}
As you can see, I create a table_panel
and wrap it with scroll_pane
. Then I add 60 rows with 5 JLabels in each row. The problem is that if I specify each column's width so that total row width is 100%, width of scroll element starts to increase rapidly.
Here are two screenshots - one for case when horizontal scroll is disabled and another for case when horizontal scroll is enabled.
My suggestion about such behavior is that width of JScrollPane
element is extremely large, but it seems that this suggestion is incorrect, because if I define width for each column so that total width is 98%, everything works fine.
Please, help me with understanding these weird things. Thanks in advance.
[UPDATE]
I decided to use another approach to achieve what I need. This approach is based on grid functionallity. There is a small condition - all width values should be multiple of 5. I suppose this condition is not limiting, because it's hard to imagine situations, where you need more than 5% precision.
First, I add 20 invisible elements (for further calls of span()
method):
Box empty;
for (int i = 0; i < 20; i++) {
empty = new Box(BoxLayout.X_AXIS);
empty.setVisible(false);
if (i == 19)
table_panel.add(empty, "wrap");
else
table_panel.add(empty);
}
Without these elements, span()
method will have no effect.
Here is full code sample:
package view;
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import net.miginfocom.layout.AC;
import net.miginfocom.layout.CC;
import net.miginfocom.layout.LC;
import net.miginfocom.swing.MigLayout;
public class AppView
{
private final JFrame main_frame;
public AppView()
{
main_frame = new JFrame();
main_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main_frame.setTitle("Example");
JPanel main_panel = new JPanel() {
private static final long serialVersionUID = 1L;
public Dimension getPreferredSize()
{
return new Dimension(300, 200);
}
};
main_panel.setLayout(new MigLayout("fill"));
JPanel table_panel = new JPanel();
table_panel.setLayout(new MigLayout(new LC().fill().debug(1).hideMode(2), new AC().gap("0"), new AC().gap("0")));
JScrollPane scroll_pane = new JScrollPane(table_panel);
scroll_pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
Box empty;
for (int i = 0; i < 20; i++) {
empty = new Box(BoxLayout.X_AXIS);
empty.setVisible(false);
if (i == 19)
table_panel.add(empty, "wrap");
else
table_panel.add(empty);
}
int[] width_arr = {20, 20, 20, 20, 20};
for (int i = 0; i < 60; i++)
for (int j = 0; j < width_arr.length; j++) {
if (j == width_arr.length - 1)
table_panel.add(new JLabel(i + 1 + ", " + (j + 1)), new CC().span(width_arr[j] / 5).wrap());
else
table_panel.add(new JLabel(i + 1 + ", " + (j + 1)), new CC().span(width_arr[j] / 5));
}
main_frame.getContentPane().add(main_panel, BorderLayout.CENTER);
main_panel.add(scroll_pane, new CC().grow());
main_frame.pack();
main_frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new AppView();
}
});
}
}
This works practically fine, and horizontal scroll isn't required anymore, but there is the problem with width of invisible boxes - their width is not constant and equal for all boxes, it depends on JLabels width. So proportions are not correct. And here are some screenshots, illustrating that:
1) Simplest case: five columns, 20% width each, works fine.
2) More complicated example: three columns - 10%, 40%, 50%. Proportions are invalid, because second column isn't 4 times wider than first.
Well, now I have no idea what to do next. And all my attempts to find something on the Internet were in vain.