0

I have code

import javax.swing.JFrame;
import javax.swing.JPanel;

import java.awt.Graphics;
import java.awt.FlowLayout;

class GUI extends JFrame {

    JPanel mainPanel;

    public GUI(String header) {

        super(header);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //setLayout(new FlowLayout(FlowLayout.CENTER));

        init();

        add(mainPanel);
        pack();
    }

    public void init() {
        mainPanel = new JPanel(){
            @Override
            public void paintComponent(Graphics g) {
                g.fillOval(0, 0, 50, 50);
            }
        };
    }
}

and in my main method, I have

GUI progam = new GUI("Title");
progam.setLocationRelativeTo(null);
progam.setVisible(true);

If I run the program, I get output:

OUTPUT-1

and if I uncomment the setLayout, I get output:

OUTPUT-2

Two questions:

  1. Why isn't pack() working as expected in the first case? Shouldn't I see the full circle instead of seeing half of it?
  2. Why did the oval turn into a triangle in the second output?
Spikatrix
  • 20,225
  • 7
  • 37
  • 83

2 Answers2

2

Why isn't pack() working as expected in the first case? Shouldn't I see the full circle instead of seeing half of it?

It is, your mainPanel is providing no sizing hints for the layout manager to work with, so it's using it's component's default sizing hints (0x0)

Add

@Override
public Dimension getPreferredSize() {
    return new Dimension(50, 50);
}

to you mainPanel and super.paintComponent(g) to your paintComponent method, before you do any custom painting

Why did the oval turn into a triangle in the second output?

That would be the difference between BorderLayout and FlowLayout

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
1

As you're drawing in the JPanel, you're actually not putting a component in there, thus it doesn't have any dimension(width, height) as well as your JPanel.

As explicited here https://docs.oracle.com/javase/tutorial/uiswing/components/frame.html, item 4:

The pack method sizes the frame so that all its contents are at or above their preferred sizes. An alternative to pack is to establish a frame size explicitly by calling setSize or setBounds (which also sets the frame location). In general, using pack is preferable to calling setSize, since pack leaves the frame layout manager in charge of the frame size, and layout managers are good at adjusting to platform dependencies and other factors that affect component size.

To solve this, use setBounds or setSize or add a component with preferred size.

Hope it helps =)

Gabriel Câmara
  • 1,249
  • 15
  • 22
  • Usi setSize or setBound is ill advised given the fact that the parent container is using a layout manager, which will override anything you specify – MadProgrammer Jul 02 '15 at 21:38
  • Hello, @MadProgrammer, would you mind explain it better? I mean with some kind o scenario? I saw your answer and I kinda like it – Gabriel Câmara Jul 03 '15 at 22:28
  • The problem is, the layout manager will make it's own calculations based on it's algorithm and set the size of the components the way it wants to. So anything you set will be discarded when ever the parent container is revalidated – MadProgrammer Jul 03 '15 at 22:41
  • I see. But in this case you're talking about the size of the components, right? My answer is based on the size of the Dialog itself. But I got your point, I believe both approaches are correct. Choose between one or another will depend on the case. Anyway, thank you for your explanation – Gabriel Câmara Jul 04 '15 at 00:22
  • Personally. I prefer pack as it's a system independent way to ensure the window is sized correctly, but that's me – MadProgrammer Jul 04 '15 at 00:49
  • I agree with you. There will be cases where the `setSize` will be necessary. But generally I'd rather go for `pack()` – Gabriel Câmara Jul 04 '15 at 01:00