简体   繁体   中英

repaint does not seem to call paintComponent

I am trying to simulate a traffic light with radio buttons. No matter where I put the call to repaint(), it does not seem to call the paintComponent method. Any help would be appreciated. Here is my code. Sorry if this is kind of long.

package trafficlight;

import java.awt.BorderLayout;
import javax.swing.*;
import java.awt.event.*;

public class Frame extends JFrame{
   Drawing ob = new Drawing();
   private JPanel buttonPanel;
   private JRadioButton red;
   private JRadioButton yellow;
   private JRadioButton green;

   public Frame(String title, int width, int height) {
        super(title);                       
        setSize(width, height);     

        buttonPanel = new JPanel();

        //creating JFrame components
        red = new JRadioButton("Red");
        yellow = new JRadioButton("Yellow");
        green = new JRadioButton("Green");

        buttonPanel.add(red);
        buttonPanel.add(yellow);
        buttonPanel.add(green);

        //JRadioButton group allows only one button to be selected at a time
        ButtonGroup group = new ButtonGroup();
        group.add(red);
        group.add(yellow);
        group.add(green);

        //adding components to frame
        add(buttonPanel, BorderLayout.SOUTH);

        //Adding action listeners
        red.addActionListener(new Listener());
        yellow.addActionListener(new Listener());
        green.addActionListener(new Listener());

        setLocationRelativeTo(null);        
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

   }

   //Listener class to handle action events
    private class Listener implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e){            

            if(red.isSelected()){ 
                ob.setRed(true);
                ob.setYellow(false);
                ob.setGreen(false);
                ob.repaint();
            }

            else if(yellow.isSelected()){
                ob.setYellow(true);
                ob.setGreen(false);
                ob.setRed(false);
                ob.repaint();
            }

            else if(green.isSelected()){
                ob.setGreen(true);
                ob.setYellow(false);
                ob.setRed(false);
                ob.repaint();
            }    
        }
   }
}  

Here is my seconds class

package trafficlight;

import java.awt.*;
import javax.swing.*;

public class Drawing extends JPanel{

    private boolean red = false;
    private boolean yellow = false;
    private boolean green = false;

    public void setRed(boolean clicked){
        this.red = clicked; 
    }

    public void setYellow(boolean clicked){
        this.yellow = clicked;
    }

    public void setGreen(boolean clicked){
        this.green = clicked;    
    }

   @Override
    public void paintComponent(Graphics g) { 
        super.paintComponent(g);
        g.setColor(Color.black); 
        g.drawRect(85, 20, 60, 110);

        if(!red){
            g.setColor(Color.black);                
            g.drawOval(100, 25, 30, 30);          
        }
        else{
            g.setColor(Color.red);
            g.fillOval(100, 25, 30, 30);    
        }

        if(!yellow){
            g.setColor(Color.black);                
            g.drawOval(100, 60, 30, 30);
        }
        else{
            g.setColor(Color.yellow);                   
            g.fillOval(100, 60, 30, 30);  
        }

        if(!green){
            g.setColor(Color.black);                
            g.drawOval(100, 95, 30, 30);
        }
        else{
            g.setColor(Color.green);                
            g.fillOval(100, 95, 30, 30);        
        }
    }  
}

And here's the main method

package trafficlight;


public class TrafficLight  {


    public static void main(String[] args) {
        Frame test = new Frame("TrafficLight", 250, 250);
        test.add(new Drawing());
    }   
}

Some improvements for your code

  • Don't inherit from JFrame . You don't add any value to this class (composition over inheritance)
  • Your ActionListener doesn't need to be a named class because it hasn't got any state
  • No need for a field in your case
  • Use the Color constants with the UPPERCASE ie Color.BLACK
  • Enqueue Swing application in the EDT
  • Use more descriptive names for classes and variables

Then your program may look like this:

public class TrafficLightUI {

  public TrafficLightUI(String title, int width, int height) {
    JFrame frame = new JFrame(title);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(width, height);
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);

    JPanel mainPanel = new JPanel(new BorderLayout());

    JPanel buttonPanel = new JPanel();

    JRadioButton redRadioButton = new JRadioButton("Red");
    JRadioButton yellowRadioButton = new JRadioButton("Yellow");
    JRadioButton greenRadioButton = new JRadioButton("Green");
    buttonPanel.add(redRadioButton);
    buttonPanel.add(yellowRadioButton);
    buttonPanel.add(greenRadioButton);

    //JRadioButton group allows only one button to be selected at a time
    ButtonGroup buttonGroup = new ButtonGroup();
    buttonGroup.add(redRadioButton);
    buttonGroup.add(yellowRadioButton);
    buttonGroup.add(greenRadioButton);

    TrafficLightPanel trafficLight = new TrafficLightPanel();

    //adding components to frame
    mainPanel.add(buttonPanel, BorderLayout.SOUTH);
    mainPanel.add(trafficLight, BorderLayout.CENTER);

    //Adding action listeners
    redRadioButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        setTrafficLight(true, false, false, trafficLight);
      }
    });
    yellowRadioButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        setTrafficLight(false, true, false, trafficLight);
      }
    });
    greenRadioButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        setTrafficLight(false, false, true, trafficLight);
      }
    });

    frame.add(mainPanel);
    frame.setVisible(true);
  }

  private void setTrafficLight(boolean red, boolean yellow, boolean green, TrafficLightPanel trafficLight) {
    trafficLight.setGreen(green);
    trafficLight.setYellow(yellow);
    trafficLight.setRed(red);
    trafficLight.repaint();
  }
}

TrafficLightPanel

public class TrafficLightPanel extends JPanel {
  private static final long serialVersionUID = 1L;
  private boolean red = false;
  private boolean yellow = false;
  private boolean green = false;

  public void setRed(boolean isRed) {
    this.red = isRed;
  }

  public void setYellow(boolean isYellow) {
    this.yellow = isYellow;
  }

  public void setGreen(boolean isGreen) {
    this.green = isGreen;
  }

  @Override
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.BLACK);
    g.drawRect(85, 20, 60, 110);

    if (!red) {
      g.setColor(Color.BLACK);
      g.drawOval(100, 25, 30, 30);
    } else {
      g.setColor(Color.RED);
      g.fillOval(100, 25, 30, 30);
    }

    if (!yellow) {
      g.setColor(Color.BLACK);
      g.drawOval(100, 60, 30, 30);
    } else {
      g.setColor(Color.YELLOW);
      g.fillOval(100, 60, 30, 30);
    }

    if (!green) {
      g.setColor(Color.BLACK);
      g.drawOval(100, 95, 30, 30);
    } else {
      g.setColor(Color.GREEN);
      g.fillOval(100, 95, 30, 30);
    }
  }
}

Main

public class TrafficLight {

  public static void main(String... args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        new TrafficLightUI("TrafficLight", 250, 250);
      }
    });
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM