Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get horizontal scroll bars in JScrollPane

I have a panel layout issue that I can't seem to solve. I have the following code:

public class Test extends ApplicationFrame {
    public Test(String title) {
        super(title);

        JPanel jpanel = new JPanel();
        jpanel.setPreferredSize(new Dimension(100 * 2, 300));
        jpanel.setBackground(new Color(0xFF0000));

        JScrollPane scrollPane = new JScrollPane(jpanel);
        scrollPane.setBackground(new Color(0xFF0000));
        scrollPane.getViewport().setPreferredSize(new Dimension(100 * 2, 300));

        this.add(scrollPane, BorderLayout.WEST);
        this.setPreferredSize(new Dimension(500, 500));
    }

    public static void main(String args[]) {
        Test test = new Test("Layout Test");
        test.pack();
        RefineryUtilities.centerFrameOnScreen(test);
        test.setVisible(true);
    }
}

to create the following layout:

enter image description here

When I drag the right hand side of the window and move it over into the red JPanel and JScrollPane, I'd like the horizontal scroll bars to appear on the JScrollPane. But currently the window just shrinks without showing the horizontal scroll bar. Is this possible?

I'd like to keep the BorderLayout.WEST since my use case for this is to keep a JFreeChart from stretching when I don't have a big enough chart to fill the entire window.

like image 895
Gavin Miller Avatar asked Nov 06 '12 22:11

Gavin Miller


1 Answers

There are many reasons not to use setPreferredSize(), but the critical one here is that the desired result depends on the preferred size of the enclosed components. In particular,

  • ChartPanel has the default FlowLayout specified by JPanel, but the chart ignores this and adjusts to fill the space available; you can override getPreferredSize() to choose any desired initial geometry.

  • The scroll bars of a JScrollPane only appear when the size of the viewport is smaller than the size of the content. BorderLayout.WEST and BorderLayout.EAST don't change, so the scroll bars never appear.

Invoking pack() "causes this Window to be sized to fit the preferred size and layouts of its subcomponents." In the example below, the frame's size is artificially reduced after pack() in order to cause the scroll bars to appear. GridLayout causes the two panels to be equal is size. Resize the frame to see the effect.

Addendum: If you want a ChartPanel to have a fixed size, add it to a JPanel; the default FlowLayout uses the preferred size.

image

public class ChartPanelTest {

    private static final int N = 64;
    private static final int SIZE = 400;
    private static final Random random = new Random();

    private static XYDataset createDataset() {

        final TimeSeries series = new TimeSeries("Random Data");
        Day current = new Day();
        for (int i = 0; i < N; i++) {
            series.add(current, random.nextGaussian());
            current = (Day) current.next();
        }
        return new TimeSeriesCollection(series);
    }

    private static JFreeChart createChart(final XYDataset dataset) {
        JFreeChart chart = ChartFactory.createTimeSeriesChart(
            "Test", "Day", "Value", dataset, false, false, false);
        return chart;
    }

    public static void main(String[] args) {

        JFrame f = new JFrame();
        f.setLayout(new GridLayout(1, 0));
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JFreeChart chart = createChart(createDataset());
        f.add(new JScrollPane(new JPanel() {

            {
                setBackground(Color.red);
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(SIZE, SIZE);
            }
        }));
        f.add(new ChartPanel(chart) {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(SIZE, SIZE);
            }
        });
        f.pack();
        f.setSize(2 * (SIZE - N), SIZE - N);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}
like image 200
trashgod Avatar answered Nov 05 '22 11:11

trashgod