Java 如何让swing显示/重新绘制自定义组件?

Java 如何让swing显示/重新绘制自定义组件?,java,swing,Java,Swing,所以我有一个我正在做的小“游戏”,其中一部分有图标以行的形式显示(每个图标都是一个jpanel)。我正在添加的这些图标组件在隔离时可以完美地显示,但是当我将它们添加到它们的每一行时,它们似乎根本不会显示。我是swing新手,所以我想知道这是否是因为图像比它们所放入的行小一点 以下是图标的代码,该图标独立运行良好: import java.awt.Color; import java.awt.Graphics; import java.awt.image.BufferedImage; import

所以我有一个我正在做的小“游戏”,其中一部分有图标以行的形式显示(每个图标都是一个jpanel)。我正在添加的这些图标组件在隔离时可以完美地显示,但是当我将它们添加到它们的每一行时,它们似乎根本不会显示。我是swing新手,所以我想知道这是否是因为图像比它们所放入的行小一点

以下是图标的代码,该图标独立运行良好:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.concurrent.TimeUnit;

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

import java.nio.file.Path;

public class fermiPicoNanoImage extends JPanel {
    private BufferedImage image = null;
    private int[] imageDims = new int[] { 83, 47};

    //for testing
    public String currentImage;

    public fermiPicoNanoImage() throws IOException {

    }

    public void set(String whichImage) throws IOException, IllegalArgumentException  {

        whichImage = whichImage.toLowerCase();

        try {

            if(  whichImage == "fermi"  || whichImage == "f"  ) {
                Path filePath = Paths.get("src\\resources\\icon-fermi.png").toAbsolutePath();
                image = ImageIO.read(  new File(  filePath.toString()  )  );
                currentImage = "fermi";
            }
            else if(  whichImage == "nano"  || whichImage == "n"  ){
                Path filePath = Paths.get("src\\resources\\icon-nano.png").toAbsolutePath();
                image = ImageIO.read(  new File(  filePath.toString()  )  );
                currentImage = "nano";
            } 
            else if(  whichImage == "pico"  || whichImage == "p"  ) {
                Path filePath = Paths.get("src\\resources\\icon-pico.png").toAbsolutePath();
                image = ImageIO.read(  new File(  filePath.toString()  )  );
                currentImage = "pico";
            }else {
                throw new IllegalArgumentException();
            }



        }catch(Exception err) {
            System.err.println( err.getMessage() );
            err.printStackTrace();
        }


        this.repaint();

    }


    public void unset(){
        image = null;
        currentImage = null;
        this.repaint();
    }



    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

       if(image != null) {
            g.drawImage(image, 0, 0, null);
       }else if(image == null) {
           g.drawImage(image, 0, 0, Color.WHITE, null);
       }


    }

    public static void main(String[] args) throws IOException{
        fermiPicoNanoImage fnpImage = new fermiPicoNanoImage();

        JFrame frame = new JFrame();
        frame.add(fnpImage);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(200, 200);
        frame.setVisible(true);


       fnpImage.set("pico");


    }




}

呈现所有内容的JFrame就在这里。正如在其他堆栈帖子中所建议的,我在框架设置为可见之前添加了组件。我不确定这是渲染的问题还是使用的问题

现在我找不到一个简单的方法让主类为你们工作,因为正在使用本地图像,所以我把整个eclipse项目放在一个GoogleDrive文件夹中供大家使用

任何关于我需要什么来让组件渲染的建议都会非常有帮助。谢谢

任何关于让组件渲染所需内容的建议都会大有帮助

是否通过在if条件中添加System.out.println(…)语句来验证代码是否正在执行

一个可能的问题是:

else if(  whichImage == "pico"  || whichImage == "p"  ) {
不要使用“==”进行字符串比较

“==”检查对象是否为同一实例,而不是对象的值是否相同

而是使用
等于(…)
方法:

else if(  "pico".equals(whichImage) || "p".equals(whichImage)  ) {
比较顺序已更改,因此即使“whichImage”变量为null,它仍将工作

任何关于让组件渲染所需内容的建议都会大有帮助

是否通过在if条件中添加System.out.println(…)语句来验证代码是否正在执行

一个可能的问题是:

else if(  whichImage == "pico"  || whichImage == "p"  ) {
不要使用“==”进行字符串比较

“==”检查对象是否为同一实例,而不是对象的值是否相同

而是使用
等于(…)
方法:

else if(  "pico".equals(whichImage) || "p".equals(whichImage)  ) {

比较顺序已更改,因此即使“whichImage”变量为空,它仍将工作。

1)获取图像的一种方法(例如,热链接到中看到的图像)。例如,嵌入到中的图像的热链接。2) 请学习常见的Java命名法(命名约定-例如,
EachWordUpperCaseClass
firstWordLowerCaseMethod()
firstWordLowerCaseAttribute
,除非它是一个
大写常量
),并一致地使用它。。。。3) 在源代码中只需要一行空白就可以了。
{
之后或
}
之前的空行通常也是多余的。4) 应用程序资源在部署时将成为嵌入式资源,因此现在就开始访问它们是明智的。必须通过URL而不是文件访问。有关如何形成URL的信息,请参阅。您只加载过一个图像。用加载的新图像替换图像,然后只绘制图像。另外,请注意检查
image
是否为null,以及它是否为null。你无论如何都要试着画它。这种情况的意义是什么?null与unset方法结合使用,将画布重新绘制为白色。我应该更具体一些<代码>g.drawImage(图像,0,0,Color.WHITE,null)创建一个白色矩形,它只使用图像文件作为白色图像的尺寸1)获取图像的一种方法例如,热链接到中看到的图像。例如,嵌入到中的图像的热链接。2) 请学习常见的Java命名法(命名约定-例如,
EachWordUpperCaseClass
firstWordLowerCaseMethod()
firstWordLowerCaseAttribute
,除非它是一个
大写常量
),并一致地使用它。。。。3) 在源代码中只需要一行空白就可以了。
{
之后或
}
之前的空行通常也是多余的。4) 应用程序资源在部署时将成为嵌入式资源,因此现在就开始访问它们是明智的。必须通过URL而不是文件访问。有关如何形成URL的信息,请参阅。您只加载过一个图像。用加载的新图像替换图像,然后只绘制图像。另外,请注意检查
image
是否为null,以及它是否为null。你无论如何都要试着画它。这种情况的意义是什么?null与unset方法结合使用,将画布重新绘制为白色。我应该更具体一些<代码>g.drawImage(图像,0,0,Color.WHITE,null)创建一个白色矩形,它只使用图像文件作为白色图像的尺寸。我忘记了在比较字符串时应该这样做。我确实更改了代码,但是正如我提到的那样,
fermiPicoNanoImage
类本身运行良好。就在这条线的某个地方,它偏离了轨道,你还没有验证代码是否真的得到了执行。我忘了我在比较字符串时应该这么做。我确实更改了代码,但是正如我提到的那样,
fermiPicoNanoImage
类本身运行良好。就在这条线的某个地方,它偏离了轨道,你还没有验证代码是否真的得到了执行。张贴一个适当的说明问题的帖子。