I am trying to create Jframe
that houses three JPanels
. I have extended JPanel
so that each time it may be passed a color and a diameter. The end result being a JFrame
that has 1 red, 1 yellow and 1 green stoplightpanel
. I plan on adding an ActionListener
to these panels which is why it is designed this way. It is not working because currently, I only can see the yellow panel.
Fair warning this is for a class. So I have tried every configuration I can think of and I still only see one instance of my subclass present in my Jframe
. If anyone can point out the obvious I would be appreciated. Oddly enough only my yellow light is displayed.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class TrafficLight3 extends JFrame {
public static void main ( String [] args ) {
TrafficLight3 tl = new TrafficLight3 ( );
}
// Constructor
public TrafficLight3( ) {
setTitle( "Traffic Light" );
setSize ( 200, 400 );
setLocation ( 200, 200 );
setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
StopLightPanel red = new StopLightPanel( 100, Color.RED );
// add stoplight panel's to JFrame's default border layout.
add( red, BorderLayout.NORTH );
StopLightPanel yellow = new StopLightPanel( 100, Color.YELLOW );
add( yellow, BorderLayout.CENTER );
StopLightPanel green = new StopLightPanel( 100, Color.GREEN );
add ( green, BorderLayout.SOUTH );
setVisible( true );
}
class StopLightPanel extends JPanel {
private int diameter;
private Color color;
public StopLightPanel ( int d, Color c) {
diameter = d;
color = c;
}
public void paintComponent ( Graphics g ) {
g.setColor ( color );
g.fillOval ( 50, 25, diameter, diameter );
}
}
}
1- Ensure that your code runs in EDT
2- @Flight2039 is correct, it seems that BorderLayout
where location is not the CENTER uses preferredSize
to determinate the size. So you could override getPreferredSize()
3- When you override paintComponent(..)
you have to call super.paintComponent(..)
to follow painting method chaining. More information here.
4- Add @Override annotation always this will check at compile time for example if you make some typo overriding the method.
See this runnable example, i used gridLayout with one column and three rows.
package test2;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TrafficLight3 {
private JPanel redPanel;
private JPanel yellowPanel;
private JPanel greenPanel;
// Constructor
public TrafficLight3() {
redPanel = new StopLightPanel(100, Color.RED);
yellowPanel = new StopLightPanel(100, Color.YELLOW);
greenPanel = new StopLightPanel(100, Color.GREEN);
}
private static class StopLightPanel extends JPanel {
private int diameter;
private Color color;
public StopLightPanel(int d, Color c) {
diameter = d;
color = c;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillOval(50, 25, diameter, diameter);
}
@Override
public Dimension getPreferredSize(){
int x = diameter*2;
return new Dimension(x,x);
}
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
*/
private static void createAndShowGUI() {
// Create and set up the window.
JFrame frame = new JFrame("Traffic Light");
frame.setSize(200,500);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLayout(new GridLayout(3,1));
frame.setLocationByPlatform(Boolean.TRUE);
TrafficLight3 example = new TrafficLight3();
frame.add(example.redPanel);
frame.add(example.yellowPanel);
frame.add(example.greenPanel);
// Display the window.
frame.setVisible(Boolean.TRUE);
}
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
And the output..