Reputation:
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.
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
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
Reputation:
Simple fix, needed to be using setPreferredSize() rather than setSize.
Upvotes: 0