0

I have a JFrame (frame) with a JScrollPane. The JScrollPane contains my ContainerJComponent (DebugPanel). This ContainerJComponent contains JComponentItems (DebugItem). This is an abstracted problem from my project for the purpose of understanding.

FRAME I create a JFrame. The For loop is used to create sample items for the panel.

public class DebugGUI {
    
    private static JFrame frame;
    private static DebugPanel panel = new DebugPanel();
    
    public static void generateGUI() {
        
        
        frame = new JFrame();
        
        
        for (int i = 1; i < 20; i++) {
            panel.addItem(0.2);
        }
        
        frame.setContentPane(new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS));
        frame.setVisible(true);
    }

}

PANEL For the sake of simplicity, the panel in this example takes up the entire JFrame area. The panel serves as a container, which in turn contains items - in this example the 20 items added via the For loop.

public class DebugPanel extends JComponent {
    
    private static final long serialVersionUID = -7384855597611519487L;
    private LinkedList<DebugItem> items = new LinkedList<>();
    
    public DebugPanel() {
        GridLayout layout = new GridLayout();
        layout.setRows(1);
        this.setLayout(layout);
    }
    
    public void addItem(double widthRatio) {
        DebugItem item = new DebugItem(widthRatio);
        items.add(item);
        add(item);
    }


    @Override
    protected void paintComponent(Graphics g) {
        this.setPreferredSize(new Dimension((int) getPreferredSize().getWidth(), getParent().getHeight()));
        super.paintComponent(g);
        for (DebugItem item : items) {
            item.resize((int) getPreferredSize().getHeight());
        }
        
    }
}

ITEMS The items should draw something in the panel. In my example, this is a rectangle. This rectangle should fill the full height of the panel and maintain a certain width in relation to the height.

public class DebugItem extends JComponent {

    private static final long serialVersionUID = 1630268284249666775L;
    private double widthRatio;
    private int width;
    
    DebugItem(double widthRatio) {
        this.widthRatio = widthRatio;
    }
    
    void resize(int height) {
        width = (int) (height * widthRatio);
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        // TODO Auto-generated method stub
        super.paintComponent(g);
        g.setColor(Color.RED);
        g.drawRect(0, 0, width, getParent().getHeight());
        
    }
}

However, the ratio to be drawn is not taken into account. The JScrollPane is useless because all items always fill the panel. Does anyone know a hint? The classes work in isolation. The code is complete except for the reference to the package and the imports. Simply call generateGUI() in the main method.

2
  • 2
    You shouldn't "setPreferredSize" in your paint component method. It's a bit late at that point. It's not clear why your are setting the preferred size at all? Your DebugItem should override "getPreferredSize" so that the parent component will know how big it should be when it does a layout.
    – matt
    Commented Nov 14, 2023 at 15:40
  • An minimal reproducible example should be a single file with the main() method and import statements so we can copy/paste/compile/test easily.
    – camickr
    Commented Nov 14, 2023 at 16:21

1 Answer 1

0

It seems to me that you want a panel that completely fills the height of a JScrollPane and the width of the components added to that panel is related to the height. Therefore you will never have a vertical scrollbar.

If so then I think you can use the Scrollable Panel. This will allow the panel to fill the height of the scroll pane. The width will be determined based on the number of components added and the width ratio. A horizontal scrollbar will appear as required.

Basic example:

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

public class DebugGUI {

    public static void main(String[] args)
    {
        JFrame frame = new JFrame();

        ScrollablePanel panel = new ScrollablePanel( new GridLayout(1, 0) );
        panel.setScrollableHeight( ScrollablePanel.ScrollableSizeHint.FIT );

        for (int i = 0; i < 5; i++) {
            panel.add( new DebugItem(0.2) );
        }

        frame.setContentPane(new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS));
        frame.setSize(400, 400);
        frame.setVisible(true);
    }

    static class DebugItem extends JComponent {

        private double widthRatio;

        DebugItem(double widthRatio) {
            this.widthRatio = widthRatio;
        }

        public Dimension getPreferredSize()
        {
            Dimension parent = super.getSize();

            return new Dimension((int)(parent.height * widthRatio), parent.height);
        }

        @Override
        protected void paintComponent(Graphics g) {
            // TODO Auto-generated method stub
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
        }
    }

}

Not the answer you're looking for? Browse other questions tagged or ask your own question.