Custom JComponent to set preferred scrollable viewport size

1.6k views Asked by At

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?

1

There are 1 answers

2
MadProgrammer On BEST ANSWER

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;
        }
    }
}