简体   繁体   English

重绘/刷新JFrame

[英]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. 我有一个使用图形g用各种物体制作的“汽车”,我想在按下按钮时移动它。 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. 在这个类中只有移动东西的方法,类扩展了另一个具有非移动对象,按钮,标签......和paintComponent方法的方法。

How can I clear the old position, every time the for statement goes around ? 每当for语句出现时,我如何清除旧位置?

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: 在staticnaGrafika中我有很多代码,但这是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: 下面我有另一种方法,它添加了按钮,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 paintComponent()方法中

@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. 你永远不应该在UI线程上调用sleep()。 Instead, I highly recommend that you use javax.swing.Timer and an ActionListener. 相反,我强烈建议您使用javax.swing.Timer和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. 您可以为Car对象创建一个类,并且每个car对象都会跟踪它们自己的坐标。

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. 只需点击每次按钮,即可在ActionListener中更新汽车的位置。

OUTPUT: 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. 特别注意我的paintComponent()方法。 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() . 对于像这样的任务,使用javax.swing.timer而不是使用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();
         }
      });       
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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