Java 绘制图像时,paintComponent清除JPanel

Java 绘制图像时,paintComponent清除JPanel,java,swing,jframe,jpanel,paintcomponent,Java,Swing,Jframe,Jpanel,Paintcomponent,我有以下代码: package game; import java.awt.Graphics; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.JPanel; public class Draw { Object block; public Draw(JFrame frame, Obje

我有以下代码:

package game;

import java.awt.Graphics;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Draw {

Object block;

public Draw(JFrame frame, Object object) {
    this.block = object;

    JPanel pane = new JPanel() {
        private static final long serialVersionUID = 3869097656854760151L;

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            try {
                g.drawImage(ImageIO.read(new File(object.getTexture())), object.getX(), object.getY(), object.getWidth(),
                        object.getHeight(), null);
            } catch (IOException e) {
                System.err.println("Image '" + object.getTexture() + "' could not be found!");
            }
        }
    };

    frame.add(pane);
}
}
我把这个班叫做:

package game;

import javax.swing.JFrame;

public class Frame {

private final int X_SIZE = new vena.util.Computer().screenWidth();
private final int Y_SIZE = new vena.util.Computer().screenHeight();

public Frame() {
    JFrame f = new vena.util.Frame().frame("2D Game", X_SIZE - X_SIZE   /   5,  Y_SIZE - Y_SIZE / 5, true, false, false,
            "res/icon.png");

    new Draw(f, new Object(0, 0, 100, 100, "grass"));
    new Draw(f, new Object(100, 0, 100, 100, "grass"));

    f.setVisible(true);
}

public static void main(String[] args) {
    new Frame();
}
}
当我调用带有

new Draw(f, new Object(0, 0, 100, 100, "grass"));
但是当我再次调用图像时,它旁边

new Draw(f, new Object(100, 0, 100, 100, "grass"));

它只渲染第二个图像,并删除第一个图像。我注意到,在paintComponent方法中调用g.drawImage()两次时,不会出现这种情况。是否有一种方法可以在不清除JPanel的情况下调用Draw类任意多次?

框架内容窗格的默认布局管理器是BorderLayout。将构件添加到BorderLayout且未指定约束时,构件将移至中心。只有最后添加的零部件才能显示在中心

如果希望框架上有多个组件,则可以更改布局管理器。试一试

f.setLayout( new FlowLayout() );
看看有什么不同

我注意到,在paintComponent方法中调用g.drawImage()两次时,不会出现这种情况


是的,如果您试图在框架上的特定位置绘制图像,那么您确实应该覆盖paintComponent()来绘制每个图像。

框架内容窗格的默认布局管理器是BorderLayout。将构件添加到BorderLayout且未指定约束时,构件将移至中心。只有最后添加的零部件才能显示在中心

如果希望框架上有多个组件,则可以更改布局管理器。试一试

f.setLayout( new FlowLayout() );
看看有什么不同

我注意到,在paintComponent方法中调用g.drawImage()两次时,不会出现这种情况


是的,如果您试图在帧上的特定位置绘制图像,那么您真的应该覆盖paintComponent()来绘制每个图像。

看起来您从未为帧设置过。这意味着添加第二个面板时,第二个面板将简单地替换第一个面板。使用适当的布局来定位两个面板,就像您想要的那样。另外,您不应该在绘制方法中调用
ImageIO.read
。那将有糟糕的表现。创建对象时读取中的图像,然后每次调用
paintComponent
时重复使用相同的实例。看起来您从未为帧设置一个实例。这意味着添加第二个面板时,第二个面板将简单地替换第一个面板。使用适当的布局来定位两个面板,就像您想要的那样。另外,您不应该在绘制方法中调用
ImageIO.read
。那将有糟糕的表现。创建对象时,请阅读中的图像,然后每次调用
paintComponent
时重复使用同一实例。我这样做了,现在它只是在帧的中心顶部绘制一个小黑框。知道为什么吗?@Vena FlowLayout尊重面板的首选尺寸(基本上是10x10,因为您没有向面板添加任何组件)。因此,您需要覆盖面板的
getPreferredSize()
,以返回图像的大小。或者更简单的解决方案是只使用带有图像图标的JLabel来显示图像。不需要自定义面板。我真的不知道你的要求是什么。我应该把覆盖的getPreferredSize放在哪里?另外,您的意思是我应该创建一个ImageIcon,将该ImageIcon设置为JLabel,将JLabel放在JPanel上,然后将JPanel放在JFrame上吗?这不是更难更费时吗?@Vena,是的,这就是我的意思。不,这并不难,因为您使用的是JDK类,而不是通过在面板上绘制图像来重新发明轮子。阅读Swing教程中的部分,了解更多信息和工作示例。我用ImageIcon作为参数创建了一个新的JLabel。然后我将其设置为传递对象的大小以及位置。然后我做了“newframe().p.add(label);”,但它不起作用。(p是带有FlowLayout的JPanel)。框架不会出现,除非我注释掉“new frame().p.add(label);”。知道为什么吗?我这么做了,现在它只是在画面的中心顶部画了一个小黑匣子。知道为什么吗?@Vena FlowLayout尊重面板的首选尺寸(基本上是10x10,因为您没有向面板添加任何组件)。因此,您需要覆盖面板的
getPreferredSize()
,以返回图像的大小。或者更简单的解决方案是只使用带有图像图标的JLabel来显示图像。不需要自定义面板。我真的不知道你的要求是什么。我应该把覆盖的getPreferredSize放在哪里?另外,您的意思是我应该创建一个ImageIcon,将该ImageIcon设置为JLabel,将JLabel放在JPanel上,然后将JPanel放在JFrame上吗?这不是更难更费时吗?@Vena,是的,这就是我的意思。不,这并不难,因为您使用的是JDK类,而不是通过在面板上绘制图像来重新发明轮子。阅读Swing教程中的部分,了解更多信息和工作示例。我用ImageIcon作为参数创建了一个新的JLabel。然后我将其设置为传递对象的大小以及位置。然后我做了“newframe().p.add(label);”,但它不起作用。(p是带有FlowLayout的JPanel)。框架不会出现,除非我注释掉“new frame().p.add(label);”。知道为什么吗?