Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 向JPanel添加图像时遇到问题_Java_Image_Swing_Jpanel_Paintcomponent - Fatal编程技术网

Java 向JPanel添加图像时遇到问题

Java 向JPanel添加图像时遇到问题,java,image,swing,jpanel,paintcomponent,Java,Image,Swing,Jpanel,Paintcomponent,我正在制作一个视频游戏,我需要将一个图像添加到JPanel,然后将该JPanel添加到JFrame。我看到的所有教程都说要将其添加到JLabel中,但图像需要能够四处移动。除非你能移动一个JLabel,否则我不能这样做。如何将图像直接添加到JPanel。这是我到目前为止所做的,但它就像是在一个日本人身上 class Penguin extends JPanel { public Image image; public void paintComponent( Graphics

我正在制作一个视频游戏,我需要将一个图像添加到JPanel,然后将该JPanel添加到JFrame。我看到的所有教程都说要将其添加到JLabel中,但图像需要能够四处移动。除非你能移动一个JLabel,否则我不能这样做。如何将图像直接添加到JPanel。这是我到目前为止所做的,但它就像是在一个日本人身上

class Penguin extends JPanel {

    public Image image;

    public void paintComponent( Graphics g ) {

        image = getImage( getDocumentBase(), "Penguins.jpg" );
        g.drawImage( image, 0, 0, this );
    }
}

您可以轻松地移动JLabel,因此这仍然是一个可行的选项,并且有一些技巧可以让您做到这一点,包括使用JLayeredPane或玻璃窗格。尽管如此,在JPanel中绘制图像并不困难(我敢打赌,你的谷歌搜索已经向你展示了如何做到这一点)。关键是在JPanel的
paintComponent(…)
方法覆盖中使用图形对象的
drawImage(…)
方法绘制它

如果您愿意,我们可能会给您提供更好、更具体的建议,如果您提供有关当前代码和当前问题的更多详细信息

编辑
关于您发布的代码:首先,不要读取
paintComponent(…)
方法中的文件。这将减慢GUI的绘制速度,并使GUI的响应性变得糟糕。另外,为什么每次重新绘制时都要在同一图像文件中重新读取代码?否,而是读取一次文件并将其保存在Image变量中。也许您应该使用
ImageIO.read(…)
阅读它

接下来,您仍然需要将该文件移动到jar文件中,正如前面向您推荐的那样

编辑2
例如,对于这样的代码:

Penguin.java

package myPackage;

import java.awt.Graphics;
import java.awt.Image;
import java.io.IOException;
import java.io.InputStream;

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

@SuppressWarnings("serial")
public class Penguin extends JPanel {
   private Image image;

   public Penguin(String imageResource) throws IOException {
      InputStream inStream = getClass().getResourceAsStream(imageResource);
      image = ImageIO.read(inStream);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (image != null) {
         g.drawImage(image, 0, 0, this);
      }
   }
}
java

package myPackage;

import java.awt.BorderLayout;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import javax.swing.*;

@SuppressWarnings("serial")
public class PenguinApplet extends JApplet {
   @Override
   public void init() {
      try {
         SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
               createAndShowGui();
            }
         });
      } catch (InterruptedException e) {
         e.printStackTrace();
      } catch (InvocationTargetException e) {
         e.printStackTrace();
      }
   }

   public void createAndShowGui() {
      String penguinImgResource = "images/MyImage.jpg";
      try {
         Penguin penguinPanel = new Penguin(penguinImgResource );
         getContentPane().add(penguinPanel, BorderLayout.CENTER);
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}
您可以将图像放在images包中,与类文件一起放在包外:


这里的关键问题是,相对于类文件,图像存储在哪里?在我的示例中,类文件保存在myPackage中,而映像位于myPackage/images中,因此相对路径就是images。因此,图像文件夹中的任何图像都必须使用此路径(此处为“images/MyImage.jpg”)引用,并作为资源而不是文件获取。

您可以轻松地移动JLabel,因此这仍然是一个可行的选项,并且有一些技巧可以让您做到这一点,包括使用JLayeredPane或玻璃窗格。尽管如此,在JPanel中绘制图像并不困难(我敢打赌,你的谷歌搜索已经向你展示了如何做到这一点)。关键是在JPanel的
paintComponent(…)
方法覆盖中使用图形对象的
drawImage(…)
方法绘制它

如果您愿意,我们可能会给您提供更好、更具体的建议,如果您提供有关当前代码和当前问题的更多详细信息

编辑
关于您发布的代码:首先,不要读取
paintComponent(…)
方法中的文件。这将减慢GUI的绘制速度,并使GUI的响应性变得糟糕。另外,为什么每次重新绘制时都要在同一图像文件中重新读取代码?否,而是读取一次文件并将其保存在Image变量中。也许您应该使用
ImageIO.read(…)
阅读它

接下来,您仍然需要将该文件移动到jar文件中,正如前面向您推荐的那样

编辑2
例如,对于这样的代码:

Penguin.java

package myPackage;

import java.awt.Graphics;
import java.awt.Image;
import java.io.IOException;
import java.io.InputStream;

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

@SuppressWarnings("serial")
public class Penguin extends JPanel {
   private Image image;

   public Penguin(String imageResource) throws IOException {
      InputStream inStream = getClass().getResourceAsStream(imageResource);
      image = ImageIO.read(inStream);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (image != null) {
         g.drawImage(image, 0, 0, this);
      }
   }
}
java

package myPackage;

import java.awt.BorderLayout;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import javax.swing.*;

@SuppressWarnings("serial")
public class PenguinApplet extends JApplet {
   @Override
   public void init() {
      try {
         SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
               createAndShowGui();
            }
         });
      } catch (InterruptedException e) {
         e.printStackTrace();
      } catch (InvocationTargetException e) {
         e.printStackTrace();
      }
   }

   public void createAndShowGui() {
      String penguinImgResource = "images/MyImage.jpg";
      try {
         Penguin penguinPanel = new Penguin(penguinImgResource );
         getContentPane().add(penguinPanel, BorderLayout.CENTER);
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}
您可以将图像放在images包中,与类文件一起放在包外:


这里的关键问题是,相对于类文件,图像存储在哪里?在我的示例中,类文件保存在myPackage中,而映像位于myPackage/images中,因此相对路径就是images。因此,图像文件夹中的任何图像都必须使用此路径(此处为“images/MyImage.jpg”)进行引用,并作为资源而不是文件获取。

为什么不使用
Graphics
中的图形。移动它会更容易尝试以下操作:@brano88:您不认为一次就足够了吗?请参见编辑2以回答。为什么不使用
图形
中的图形呢。移动它会更容易尝试以下内容:@brano88:你不认为一次就足以让你发表评论吗?请参见编辑2来回答。我想我忘了提到这需要在JFrame上…这也可以在JFrame上工作吗?@user1276078:是的,概念完全相同,代码也很相似。@user1276078:是的,你不想
invokeAndWait(…)
用于JFrame,而是
invokeLater(…)
。非常感谢你不知道你现在帮了我多少忙:)我想我忘了提到这需要在JFrame上…这在JFrame上也能起作用吗?@user1276078:是的,概念完全一样,代码是相似的。@user1276078:是的,你不想为JFrame调用
invokeAndWait(…)
,而是
invokeLater(…)
。非常感谢你不知道你现在帮了我多少忙:)