javaswingjscrollpanepreferredsizejviewport

Custom JComponent to set preferred scrollable viewport size


So I am trying to create a custom component so I can set the size of my scroll pane. Here is the part with the scroll pane:

JScrollPane scrollPane = new JScrollPane(leftTop);
customScroll t1 = new customScroll();
scrollPane.add(t1);
left.add(scrollPane);

leftTop is a nested panel inside of left. Here is my class for customScroll which is the custom component I am making so I can set the size of the scroll pane:

public class customScroll extends JComponent implements Scrollable {

    public customScroll() {
        getPreferredScrollableViewportSize();
    }

    @Override
    public Dimension getPreferredScrollableViewportSize() {
        return(new Dimension(266,300));
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g); 
    }

    @Override
    public int getScrollableBlockIncrement(Rectangle visibleRect,
            int orientation, int direction) {
        return 0;
    }

    @Override
    public boolean getScrollableTracksViewportHeight() {
        return false;
    }

    @Override
    public boolean getScrollableTracksViewportWidth() {
        return false;
    }

    @Override
    public int getScrollableUnitIncrement(Rectangle visibleRect,
            int orientation, int direction) {
        return 0;
    }
}

How can I set the preferred scrollable size?


Solution

  • Provide a setter...

    public void setPreferredScrollableViewportSize(Dimension size) {
        this.preferredScrollableViewportSize = size;
    }
    

    Now, obviously, your getPreferredScrollableViewportSize will need to return this value...

    public class CustomScroll extends JComponent implements Scrollable {
    
        private Dimension preferredScrollableViewportSize = new Dimension(266, 300);
    
        public CustomScroll() {
        }
    
        public void setPreferredScrollableViewportSize(Dimension size) {
            this.preferredScrollableViewportSize = size;
        }
    
        @Override
        public Dimension getPreferredScrollableViewportSize() {
            return preferredScrollableViewportSize;
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
        }
    
        @Override
        public int getScrollableBlockIncrement(Rectangle visibleRect,
                        int orientation, int direction) {
            return 64;
        }
    
        @Override
        public boolean getScrollableTracksViewportHeight() {
            return false;
        }
    
        @Override
        public boolean getScrollableTracksViewportWidth() {
            return false;
        }
    
        @Override
        public int getScrollableUnitIncrement(Rectangle visibleRect,
                        int orientation, int direction) {
            return 64;
        }
    }
    

    Should also set this before you wrap in your JScrollPane, it would just be easier to manage, otherwise, you'll need invalidate the container in which the JScrollPane resides

    You might like to have a read through Code Conventions for the Java TM Programming Language, it will make it easier for people to read your code and for you to read others

    But that will still just get the preferred size

    No it won't, it will use the preferredScrollableViewportSize (assuming you're wrapping in within a JScrollPane

    my scroll pane adjusts to what is in it so it just grows with buttons added

    Then you're doing something wrong

    JScrollPane scrollPane = new JScrollPane(leftTop);    
    customScroll t1 = new customScroll();
    // This is wrong...
    scrollPane.add(t1);
    left.add(scrollPane);
    

    You should never add anything to a JScrollPane, it's not how they work, instead, you need to wrap the component within it

    leftTop t1 = new CustomScroll();
    JScrollPane scrollPane = new JScrollPane(leftTop);    
    left.add(scrollPane);
    

    Or some such...

    I want it to remain a fixed size so I need to explicitly set a size that it cannot deviate from

    Yes, that's what preferredScrollableViewportSize is doing

    ExampleLayout

    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    import java.awt.Rectangle;
    import javax.swing.JButton;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.Scrollable;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class JavaApplication57 {
    
        public static void main(String[] args) {
            new JavaApplication57();
        }
    
        public JavaApplication57() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                setLayout(new GridBagLayout());
                CustomScroll comp = new CustomScroll();
                comp.setPreferredScrollableViewportSize(new Dimension(100, 100));
    
                comp.setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                gbc.weightx = 1;
                gbc.insets = new Insets(5, 10, 10, 5);
                for (int index = 0; index < 100; index++) {
    
                    JButton btn = new JButton("Hello world " + index);
                    comp.add(btn, gbc);
    
                }
    
                add(new JScrollPane(comp));
            }
    
        }
    
        public class CustomScroll extends JComponent implements Scrollable {
    
            private Dimension preferredScrollableViewportSize = new Dimension(266, 300);
    
            public CustomScroll() {
            }
    
            public void setPreferredScrollableViewportSize(Dimension size) {
                this.preferredScrollableViewportSize = size;
            }
    
            @Override
            public Dimension getPreferredScrollableViewportSize() {
                return preferredScrollableViewportSize;
            }
    
            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
            }
    
            @Override
            public int getScrollableBlockIncrement(Rectangle visibleRect,
                            int orientation, int direction) {
                return 64;
            }
    
            @Override
            public boolean getScrollableTracksViewportHeight() {
                return false;
            }
    
            @Override
            public boolean getScrollableTracksViewportWidth() {
                return false;
            }
    
            @Override
            public int getScrollableUnitIncrement(Rectangle visibleRect,
                            int orientation, int direction) {
                return 64;
            }
        }
    }