2

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. enter image description hereenter image description here

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.

enter image description here

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. enter image description here

2) More complicated example: three columns - 10%, 40%, 50%. Proportions are invalid, because second column isn't 4 times wider than first.

enter image description here enter image description here

Well, now I have no idea what to do next. And all my attempts to find something on the Internet were in vain.

Kirill Smirnov
  • 1,452
  • 2
  • 21
  • 28
  • whats happens if you change scrollbar policy to IF_NEEDED.. – mKorbel Nov 13 '12 at 08:29
  • @mKorbel Result of using `scroll_pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);` is on the second screenshot. – Kirill Smirnov Nov 13 '12 at 08:32
  • 2
    not MigLayout User, but there couldnt be issue by using GrigLayout, have to test what size returns JLabel (2nd. image) there must be methods or parameter how to schrink JLabel to the one PreferredSize – mKorbel Nov 13 '12 at 09:01
  • @mKorbel Thanks, your answer helped me. You mentioned GridLayout, so I decided to use grid functionality in Miglayout and it works just fine. Of course, there is a small drawback - columns should have the same width, but it is possible to avoid this using column spanning. May be you should duplicate your comment and post it as an answer so I can mark it as accepted? – Kirill Smirnov Nov 13 '12 at 09:23
  • 2
    you can post your own answer, I'll upvote if will be there printscreen :-) – mKorbel Nov 13 '12 at 09:35
  • @mKorbel I tested more carefully and understood that this approach solved my problem only partly. For simple cases with equal widths it works great, but in more complicated cases doesn't. I updated post to illustrate my words. – Kirill Smirnov Nov 13 '12 at 13:20
  • Were IN VAIN :) I think you mean. If all your attempts were vain, it means you searched in an overly proud manner (which you may have done also). – Ben Nov 13 '12 at 13:21
  • @Steve Thank you for correcting me, my English level leaves much to be desired :) – Kirill Smirnov Nov 13 '12 at 13:25
  • there must be simple hack, because there must be second parameter, maybe to search in answers by [@kleopatra](http://stackoverflow.com/search?q=user%3A203657+miglayout) – mKorbel Nov 13 '12 at 13:28

0 Answers0