1

I have this piece of code that is basically a JFrame that contains a JSplitPane which contains on the left side a JScrollPane which contains a JPanel. I expected to see the scroll bars since the JPanel inside the JScrollPane is larger that the JScrollPane itself. Why are the scroll bars not displayed? If I replace setSize() with setPreferredSize() then it works, but I want to use setSize(). Is there any way I can use setSize() and have the scroll bars showing?

import java.awt.*;
import javax.swing.*;

public class Test {

    public static void main( String[] args ) {
        JFrame frame = new JFrame();
        frame.setLayout( new BorderLayout() );
        JSplitPane splitPane = new JSplitPane();
        frame.add( splitPane, BorderLayout.CENTER );
        JPanel panel = new JPanel();
        panel.setBackground( Color.red );
        panel.setSize( 1920, 1200 );
        //panel.setPreferredSize( new Dimension( 1920, 1200 ) );
        JScrollPane scrollPane = new JScrollPane( panel );
        splitPane.setLeftComponent( scrollPane );
        splitPane.setRightComponent( new JPanel() );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.pack();
        frame.setVisible( true );
        frame.setSize( 960, 600 );
    }
}

Edit: I've added a modified version where I use setPreferredSize(). Is there a better solution for dynamically changing the size?

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test {

    public static void main( String[] args ) {
        JFrame frame = new JFrame();
        frame.setLayout( new BorderLayout() );
        JSplitPane splitPane = new JSplitPane();
        frame.add( splitPane, BorderLayout.CENTER );
        final JPanel panel = new JPanel();
        panel.setBackground( Color.red );
        panel.setPreferredSize( new Dimension( 1920, 1200 ) );
        JScrollPane scrollPane = new JScrollPane( panel );
        splitPane.setLeftComponent( scrollPane );
        JButton button = new JButton();
        button.addActionListener( new ActionListener() {

            @Override
            public void actionPerformed( ActionEvent e ) {
                panel.setPreferredSize( new Dimension( 3840, 2400 ) );
                panel.revalidate();
            }
        });
        splitPane.setRightComponent( button );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.pack();
        frame.setVisible( true );
        frame.setSize( 960, 600 );
    }
}
corneliu
  • 656
  • 13
  • 37
  • 1
    Add something to the panel which causes the size of panel to exceeded the viewable area of the scroll pane; override the panel's getPreferredSize method instead of using setSize – MadProgrammer Jan 29 '16 at 20:16
  • `with setPreferredSize() then it works, but I want to use setSize()` Why do you want to use something that doesn't work? – FredK Jan 29 '16 at 20:22
  • `If I replace setSize() with setPreferredSize() then it works, but I want to use setSize().` - but that is NOT the way Swing works or was designed to work. So you can't use setSize() because that means nothing to the viewport of the scrollpane. – camickr Jan 29 '16 at 20:38
  • @FredK I have an image (1920x1200) that i need to display at various zooms. At zoom 8x for example the image is too big for the memory so I have to calculate the offset of the section that is visible and it is easier to calculate that offset when the JLabel inside that JPanel is the same size as the image. I can use setSize() to dynamically change the size of the JPanel but I think setPreferredSize() won't dynamically change the size. Am I wrong? – corneliu Jan 29 '16 at 20:56
  • @corneliu: [Don't use `setPreferredSize()` when you really mean to override `getPreferredSize()`](http://stackoverflow.com/q/7229226/230513), for [example](https://stackoverflow.com/a/10110232/230513). See also [*Initial Threads*](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html). – trashgod May 29 '17 at 11:48
  • @trashgod. Thank you for your reply. That question is more than a year old. You are probably right but I can't provide any feedback due to the fact that that project is long gone. – corneliu May 29 '17 at 17:35

1 Answers1

1

Your setSize will be ignored by the JSplitPane because the layout of the left/right components is not null, and it tries to fit the internal components in the available space.

The layout manager for the JSplitPane's left/right components honors the preferredSize property(and not the size property) and if it hasn't been set, it just tries to fit the internal component inside the available space of left/right area in JSplitPane.

Use setPreferredSize instead or override the getPreferredSize method for your panel as camickr described in the comment.

STaefi
  • 4,297
  • 1
  • 25
  • 43
  • You should override the getPreferredSize() method. Each component should be responsible for determining its own preferred size. – camickr Jan 29 '16 at 20:38
  • OK, I've updated my original post and I added another version of my code. I use revalidate() in order to make it work. Is there a better solution? – corneliu Jan 29 '16 at 21:15
  • I think according to the documentations of JSplitPane after each time you call the setPreferredSize you should call the `revalidate` method, because `setPreferredSize` invalidates the component's hierarchy. So you are good to call `revalidate` after `setPreferredSize` – STaefi Jan 29 '16 at 22:04