移动Java Swing矩形会留下其他矩形

4

当我终于弄清楚repaint方法后,我遇到了一个问题。我想要将一个矩形沿着屏幕移动,而不是重新绘制它。重新绘制也可以,但是它会在旧矩形的后面留下残影!这是我的代码:

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Tutorial3{

    public static void main(String[] agrs){
        createAndStartGui();
    }
    static void createAndStartGui(){
        JFrame f = new JFrame("tutorial 3");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().setPreferredSize(new Dimension(500, 300));

        MyPanel panel = new MyPanel();
        f.add(panel);

        f.pack();
        f.setVisible(true);

        for (int i = 0; i < 10; i++){
            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                Logger.getLogger(Tutorial3.class.getName()).log(Level.SEVERE, null, ex);
            }
            panel.user.move("right");
            panel.repaint();
        }
    }
}

class MyRectangle{
    int x;
    int y;
    public MyRectangle(int x, int y){
        this.x = x;
        this.y = y;
    }
    void move(String direction){
        switch (direction){
            case "up":
                this.y -= 10;
                break;
            case "down":
                this.y += 10;
                break;
            case "left":
                this.x -= 10;
                break;
            case "right":
                this.x += 10;
                break;
            default:
                break;
        }
    }
}

class MyPanel extends JPanel{
    MyRectangle user = new MyRectangle(10, 10);
    public MyPanel(){

    }
    public void paintComponent(Graphics g){
        Graphics2D g2d = (Graphics2D) g;
        g.drawRect(user.x, user.y, 10, 10);
    }

}

如何让留下的矩形消失(我不想清除整个窗口)?或者更好的方法是,如何使矩形“移动”(如果可能的话)?
最终结果: enter image description here 我最终想要的是: enter image description here 注意:简单地在该点绘制矩形并不是我想要的。我希望看到它被拖动。
1个回答

10

你的问题是你只绘制了矩形而不是整个面板,所以在调用该方法时面板最终会充满矩形。你需要也绘制面板的背景。这样将“擦除”以前的矩形,因此面板中只有你在特定调用中绘制的内容而不是以前做过的。为了实现这一点,你需要调用:

super.paintComponent(g);
在你的paintComponent方法开始时(在绘制任何其他内容之前),添加以下代码。这样做的原因是在空的JPanel中,paintComponent需要做的唯一一件事就是绘制背景。
所以:
public void paintComponent(Graphics g){
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    g.drawRect(user.x, user.y, 10, 10);
}

编辑:

回答一些评论:

我想移动一个矩形,而不是重新绘制它。

没有所谓的“移动”矩形。你可以在屏幕上绘制物体。如果你想看到其他物体,你必须画出那些其他物体。不存在本质上的“将像素的颜色移动到像素...”,就是这样的。你想要东西吗?画出来。你想让它们移动吗?反复以不同的位置绘制它们。

(我不想清除整个窗口)

但你需要。每次有什么东西改变,你就要重新绘制整个面板。如果面板中还有其他东西,你不想“擦除”,那就重新绘制它们。

清除“旧”的矩形位置并绘制一个新的矩形,而不影响面板的其余部分,是可能的。但那是不必要的棘手。当你覆盖paintComponent时,在第一行调用super.paintComponent(g)是标准操作。不这样做必须是一个非常有意识的决定,并且你最好确信自己在做什么。

如果你的程序在重新绘制面板背景时的某个代码部分表现不良,我可以很自信地告诉你,这些部分设计得不好,而不是调用super.paintComponent(g) 是一个坏主意。

paintComponent有责任绘制整个组件。背景是组件的一部分。当你覆盖它时,这是Swing中的自然、良好的设计。


+1 谢谢。我假设当一次重新绘制多个组件时(例如,背景中的非移动形状也将被重新绘制),这个方法也适用。 - user3557348
1
很高兴能帮忙!我不确定我理解你的评论,你说的“一次重绘多个组件”是什么意思?super.paintComponent只会用背景色填充(清除所有内容)该区域,然后你可以在其上绘制任意数量的形状。 - DSquare

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接