user7884989
user7884989

Reputation:

Making item in BorderLayout take up correct size

I am attempting to make a simple traffic light frame. This is being made by the main frame TrafficBox:

public class TrafficBox extends JFrame {

public TrafficBox() {
    setLayout(new BorderLayout(100,100));
    add(new TrafficLight(Color.GREEN), BorderLayout.NORTH);
    add(new TrafficLight(Color.ORANGE), BorderLayout.CENTER);
    add(new TrafficLight(Color.RED), BorderLayout.SOUTH);
    setBounds(100, 100, 800, 600);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            new TrafficBox();
        }
    });

}

which then as seen, adds in 3 TrafficLight components which are based on JPanel, and have the following code:

public class TrafficLight extends JPanel {

private final int BALL_DIAMETER = 100;
private Color color;

public TrafficLight(Color color) {
    //setSize(BALL_DIAMETER, BALL_DIAMETER);
    this.color = color;
    new Timer(1000, new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            repaint();
        }
    }).start();
}

public void paintComponent(Graphics g) {
    g.setColor(color);
    g.fillOval(0, 0, BALL_DIAMETER, BALL_DIAMETER);
}

This does sort of what I want, it draws all 3 circles as expected although a majority of the North(green) and south(red) lights are being cut off. I assume this is because the north/south spot are much smaller than the center.

enter image description here

I've tried using setSize(); to set the size of the panels to the size of the circles, however that does not work. Is there a way I can make it so that the full circle will be visible?

Upvotes: 0

Views: 23

Answers (2)

MadProgrammer
MadProgrammer

Reputation: 347194

So, most layout managers will need some "hints" to be provided by the components in order to know how they want to be laid out.

You will need to override the getPreferredSize and return a size which best meets your needs, for example...

public class TrafficLight extends JPanel {

    private final int BALL_DIAMETER = 100;

    //...

    public Dimension getPreferredSize() {
        return new Dimension(BALL_DIAMETER, BALL_DIAMETER);
    }    

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent();
        g.setColor(color);
        g.fillOval(0, 0, BALL_DIAMETER, BALL_DIAMETER);
    }

Also, paintComponent doesn't ever need to be public no-one else should be calling it and you should call super.paintComponent() before performing any custom painting.

I'd also recommend maybe using GridLayout for this

I'd also argue that TrafficLight doesn't need a Timer of it's own and the should be controlled externally, but that's me

setBounds(100, 100, 800, 600);

Is best avoided, use pack() to size the window to the preferred size of the content and setLocation to position it

Upvotes: 3

user7884989
user7884989

Reputation:

Simple fix, needed to be using setPreferredSize() rather than setSize.

Upvotes: 0

Related Questions