简体   繁体   中英

Repainting/refreshing the JFrame

I have a "car" made with various objects using graphics g and I want to move it when a button is pressed. With that, I had no problem, but I have a problem with its path. When the car is moved, the old position is not cleared out.

Code of the car (to move when button is pressed):

    static void gPostavi2(Graphics g){
    Graphics2D g2d = (Graphics2D) g;

    for(int x=500; x>89; x--){
        //risanje
        g2d.setColor(Color.blue);
        g2d.fillRect(x+10, 351, 118, 23);
        g2d.fillRect(x+12, 321, 30, 40);
        g2d.fillRect(x+45, 330, 83, 20);
        g2d.setColor(Color.black);      
        g2d.fillOval(x+19, 362, 20, 20);
        g2d.fillOval(x+90, 362, 20, 20);
        g2d.drawString("2t", x+70, 344);
        try {

            Thread.sleep(5);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }       
}

In this class are only methods for moving things around, the class extends another that has non-moving objects, buttons, labels,... and the paintComponent method.

How can I clear the old position, every time the for statement goes around ?

EDIT: some more code down here. In the main class I have only this code:

    public static void main(String[] args) {
    staticnaGrafika.dodajGumbe();
}

In staticnaGrafika I have a ton of code, but this is the beginning of paintComponent:

public class staticnaGrafika extends JPanel{

staticnaGrafika(){
        setBorder(BorderFactory.createLineBorder(Color.black));
    }
    public Dimension getPreferredSize(){
        return new Dimension(1100, 740);
    }

public void paintComponent(Graphics g){
    super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.RED);

        //opticno stikalo 
        //preveri, ce ga plosca prekriva pri max. dvigu
        g2d.setColor(Color.black);
        g2d.fillOval(21, 148, 33, 33);
        g2d.setColor(Color.yellow);
        g2d.fillOval(22, 149, 31, 31);
        g2d.setColor(Color.black);      
        g2d.fillRect(13, 159, 11, 1); //el. prikljucnice
        g2d.fillRect(13, 166, 10, 1);
        g2d.drawOval(7, 157, 5, 5);
        g2d.drawOval(7, 164, 5, 5);

        //naslon; spodnji omejevalec hoda bata
        g2d.setColor(Color.black);
        g2d.fillRect(5, 350, 13, 43);
        g2d.fillRect(5, 380, 63, 13);
        g2d.fillRect(262, 350, 408, 13);
        g2d.fillRect(262, 350, 13, 43);
        g2d.fillRect(212, 380, 63, 13);

there is just painting in here. Below I have another method, which adds buttons, actionListeners:

    public static void dodajGumbe() {
    final JFrame f = new JFrame();

    //dvig, stop, spust
    JButton dvig = new JButton("DVIGNI");
    dvig.setBackground(Color.WHITE);
    dvig.setFocusPainted(false);
    dvig.setBounds(850,15,120,30);

    JButton stop = new JButton("STOP");
    stop.setBackground(Color.WHITE);
    stop.setFocusPainted(false);
    stop.setBounds(850,50,120,30);

    JButton spust = new JButton("SPUSTI");
    spust.setBackground(Color.WHITE);
    spust.setFocusPainted(false);
    spust.setBounds(850,85,120,30);

    //komande bremen
    JButton postavi2 = new JButton("nalozi breme");
    postavi2.setBackground(Color.WHITE);
    postavi2.setFocusPainted(false);
    postavi2.setBounds(760,240,120,30);

    JButton odvzemi2 = new JButton("razlozi breme");
    odvzemi2.setBackground(Color.WHITE);
    odvzemi2.setFocusPainted(false);
    odvzemi2.setBounds(760,275,120,30);

    JButton postavi5 = new JButton("nalozi breme");
    postavi5.setBackground(Color.WHITE);
    postavi5.setFocusPainted(false);
    postavi5.setBounds(760,330,120,30);

    JButton odvzemi5 = new JButton("razlozi breme");
    odvzemi5.setBackground(Color.WHITE);
    odvzemi5.setFocusPainted(false);
    odvzemi5.setBounds(760,365,120,30);

    Container gumbi = f.getContentPane();

    spust.addActionListener(new ActionListener(){ 
        public void actionPerformed(ActionEvent arg0) {
        dinamicnaGrafika.gSpusti(f.getGraphics());
    }});

    dvig.addActionListener(new ActionListener(){ 
        public void actionPerformed(ActionEvent arg0) {
            dinamicnaGrafika.gDvigni(f.getGraphics());
    }});

    stop.addActionListener(new ActionListener(){ 
        public void actionPerformed(ActionEvent arg0) {
            dinamicnaGrafika.gStop(f.getGraphics());
    }});

    postavi2.addActionListener(new ActionListener(){ 
        public void actionPerformed(ActionEvent arg0) {
            dinamicnaGrafika.gPostavi2(f.getGraphics());
    }});

    odvzemi2.addActionListener(new ActionListener(){ 
        public void actionPerformed(ActionEvent arg0) {
            dinamicnaGrafika.gOdvzemi2(f.getGraphics());
    }});

    postavi5.addActionListener(new ActionListener(){ 
        public void actionPerformed(ActionEvent arg0) {
            dinamicnaGrafika.gPostavi5(f.getGraphics());
    }});

    odvzemi5.addActionListener(new ActionListener(){ 
        public void actionPerformed(ActionEvent arg0) {
            dinamicnaGrafika.gOdvzemi5(f.getGraphics());
    }});

    gumbi.add(dvig);
    gumbi.add(stop);
    gumbi.add(spust);
    gumbi.add(postavi2);
    gumbi.add(odvzemi2);
    gumbi.add(postavi5);
    gumbi.add(odvzemi5);

    f.getContentPane();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.add(new staticnaGrafika());
    f.pack();
    f.setVisible(true);
}

You probably forgot to call

super.paintComponent(g);

in your paintComponent() method

@Override
protected void paintComponent(Graphics g){
    super.paintComponent(g);  //Clear screen before redraw
    //Your codes for painting..
}

You should never be calling sleep() on the UI thread. Instead, I highly recommend that you use javax.swing.Timer and an ActionListener. Something like:

 void paintCar(Graphics2D g2d, int x) {
    g2d.setColor(Color.blue);
    g2d.fillRect(x+10, 351, 118, 23);
    g2d.fillRect(x+12, 321, 30, 40);
    g2d.fillRect(x+45, 330, 83, 20);
    g2d.setColor(Color.black);      
    g2d.fillOval(x+19, 362, 20, 20);
    g2d.fillOval(x+90, 362, 20, 20);
    g2d.drawString("2t", x+70, 344);
}       

int x = 0;
public MyConstructor() {
  new Timer(5, this).start();
}

public void actionPerformed(ActionEvent ae) {
  x++;
  repaint();
}

public void paintComponent(Graphics g) {
  super.paintComponent(g);
  Graphics2D g2d = (Graphics2D) g;
  paintCar(g2d, x);
}

It looks like the problem lies with your implementation. You could create a class for your Car objects and each car object keep track of their own coordinates.

For your case, if you are only moving the cars only when the button is clicked, you don't even need a Timer. Just update the car's position in the ActionListener for every button click.

OUTPUT: 在此输入图像描述

class Car
{
    private Color carColor;
    private int x, y;
    private int speed;
    private static int carWidth = 100;  
    private static int carHeight = 30;

    public Car(Color carColor, int speed){
        this.carColor = carColor;
        this.speed = speed;
        x = 0;
        y = 0;
    }

    public void moveTo(int x, int y){
        this.x = x;
        this.y = y;
    }

    public void draw(Graphics g){
        //Draw a car object
        g.setColor(carColor);
        g.fillRect(x, y, carWidth, carHeight);
        g.setColor(Color.BLACK);
        //Draw Wheels
        g.fillOval(x, y+carHeight, 30, 30); 
        g.fillOval(x+carWidth-30, y+carHeight, 30, 30);     
    }

    public int getX(){return x;}
    public int getY(){return y;}    
    public int getSpeed(){return speed;}        
}

So when you move your car(s), just update their positions and that's all you need to do. Pay special attention to my paintComponent() method. You should keep that method simple and clutter free. It is only responsible for painting. All the movements of cars is done else where.

class DrawingSpace extends JPanel implements ActionListener{
    Car c1, c2, c3; 

    public DrawingSpace(){
        setPreferredSize(new Dimension(800, 400));
        c1 = new Car(Color.RED, 5);
        c2 = new Car(Color.GREEN, 8);
        c3 = new Car(Color.BLUE, 10);
        c1.moveTo(10, 50);              
        c2.moveTo(10, 180);
        c3.moveTo(10, 280);                 
    }

    public void moveCars(){             
    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        c1.draw(g);
        c2.draw(g);
        c3.draw(g);
    }

    @Override
    public void actionPerformed(ActionEvent e){
        //Used for timer (to animate moving cars)
        c1.moveTo((c1.getX()+c1.getSpeed()), c1.getY());
        c2.moveTo(c2.getX()+c2.getSpeed(), c2.getY());
        c3.moveTo(c3.getX()+c3.getSpeed(), c3.getY());
        if(c1.getX() > 800)
            c1.moveTo(0, c1.getY());
        if(c2.getX() > 800)
            c2.moveTo(0, c2.getY());
        if(c3.getX() > 800)
            c3.moveTo(0, c3.getY());                        
        repaint();          
    }
}

For a task like this, it will be better and easier to use javax.swing.timer instead of implementing your own loop with Thread.sleep() .

class MovingCars{
    public static void main(String[] args){

      javax.swing.SwingUtilities.invokeLater(new Runnable(){
         public void run() {        
            JFrame f = new JFrame("Moving Cars");
            DrawingSpace ds = new DrawingSpace();
            f.setVisible(true);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(ds);
            f.pack();
            f.setLocationRelativeTo(null);
            Timer t = new Timer(50, ds); //Delay of 50 milliseconds
            t.start();
         }
      });       
    }
}

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