Lioriage
Lioriage

Reputation: 3

How to force a JPanel size to size of Graphic?

I have a JPanel with the paintComponent method drawing things in a square shape. I would like that square to always be centered horizontally in my JFrame (filling the whole height of the frame) and to have two black JPanels (one on each side) filling the rest of the width (they will contain buttons and text).

However I can't manage to force the JPanel containing the Graphic object to be how I need. The JPanel always fills the rest of the screen and I don't know how to fix that or to force the side panels to be come to the sides of the square.

What I'd like to achieve:

https://i.sstatic.net/iHHeu.png

What I have right now:

https://i.sstatic.net/Uh5sc.png

Upvotes: 0

Views: 708

Answers (1)

Gilbert Le Blanc
Gilbert Le Blanc

Reputation: 51565

What you want isn't how Java Swing normally allocates space.

I created a GUI that keeps the center JPanel square.

Here's the GUI at its defined size.

Triple JPanel GUI

Here's the GUI after I manually stretched it out.

Triple JPanel GUI 2

Stack Overflow shrank the image to fit the answer. You can tell because the text font appears to shrink.

Caution: If you maximize the GUI by clicking on the square in the upper right, you lose the ability to restore the GUI to its original size.

I did this by creating three JPanels and setting their preferred size. I put these three JPanels inside of the main JPanel, whose size I monitor with a ComponentListener.

When you resize the JFrame by grabbing an edge and dragging, the ComponentListener calculates the new size of the three JPanels, keeping the center JPanel square, and dividing the rest of the space between the left JPanel and the right JPanel.

I used FlowLayouts for the three JPanels. You can also use a GridBagLayout. The layout manager you choose to use has to respect the JPanel resizing.

Here's the complete runnable code.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TripleJPanelGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new TripleJPanelGUI());
    }
    
    private JFrame frame;
    
    private JPanel leftPanel;
    private JPanel centerPanel;
    private JPanel rightPanel;

    @Override
    public void run() {
        frame = new JFrame("Triple JPanel GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        PanelListener listener = new PanelListener(this);
        
        frame.add(createMainPanel(listener), BorderLayout.CENTER);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createMainPanel(PanelListener listener) {
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
        panel.addComponentListener(listener);
        
        leftPanel = createLeftPanel();
        centerPanel = createCenterPanel();
        rightPanel = createRightPanel();
                
        panel.add(leftPanel);
        panel.add(centerPanel);
        panel.add(rightPanel);
        
        return panel;
    }
    
    private JPanel createLeftPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBackground(Color.YELLOW);
        panel.setPreferredSize(new Dimension(100, 400));
        
        JLabel label = new JLabel("JPanel");
        label.setFont(panel.getFont().deriveFont(24f));
        panel.add(label);
        
        return panel;
    }
    
    private JPanel createCenterPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBackground(Color.GREEN);
        panel.setPreferredSize(new Dimension(400, 400));
        
        JLabel label = new JLabel("Always a Square");
        label.setFont(panel.getFont().deriveFont(24f));
        panel.add(label);
        
        
        return panel;
    }
    
    private JPanel createRightPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBackground(Color.BLUE);
        panel.setPreferredSize(new Dimension(100, 400));
        
        JLabel label = new JLabel("JPanel");
        label.setFont(panel.getFont().deriveFont(24f));
        label.setForeground(Color.WHITE);
        panel.add(label);
        
        return panel;
    }
    
    public void updateLeftPanel(int width, int height) {
        leftPanel.setPreferredSize(new Dimension(width, height));
    }
    
    public void updateCenterPanel(int width, int height) {
        centerPanel.setPreferredSize(new Dimension(width, height));
    }
    
    public void updateRightPanel(int width, int height) {
        rightPanel.setPreferredSize(new Dimension(width, height));
    }
    
    public JFrame getFrame() {
        return frame;
    }
    
    private class PanelListener extends ComponentAdapter {
        
        private TripleJPanelGUI frame;

        public PanelListener(TripleJPanelGUI frame) {
            this.frame = frame;
        }

        @Override
        public void componentResized(ComponentEvent event) {
            JPanel panel = (JPanel) event.getSource();
            Dimension d = panel.getSize();
            int width = (d.width - d.height) / 2; 
            int height = d.height;
            
            frame.updateLeftPanel(width, height);
            frame.updateCenterPanel(height, height);
            frame.updateRightPanel(width, height);
            frame.getFrame().pack();
        }
        
    }

}

Upvotes: 1

Related Questions