【问题标题】:Why does drawImage fail when I am using it inside a Jpanel为什么我在 Jpanel 中使用 drawImage 会失败
【发布时间】:2016-05-28 13:21:57
【问题描述】:

我正在用 Java 做一个简单平台游戏的初始部分。我创建了一个名为 entity 的类,它扩展了 JPanel 并成功将其添加到窗口中。

import javax.swing.*;
import java.awt.*;

/**
 * Created by bw12954 on 27/05/16.
 */
public abstract class Entity extends JPanel {

   private final SpriteSheet sprites;

   private       Point       location;
   private       Dimension   dimensions;

   public Entity(int x, int y, int w, int h, SpriteSheet sprites)
   {
      location     = new Point(x, y);
      dimensions   = new Dimension(w, h);
      this.sprites = sprites;
   }

   public Entity(int x, int y, int w, int h)
   {
      this(x, y, w, h, null);
   }

   @Override
   public Dimension getPreferredSize()
   {
      return dimensions;
   }

   public void setLocation(int x, int y)
   {
      location.setLocation(x, y);
   }

   /* Some code removed here for brevity */

   @Override
   public void paintComponent(Graphics g)
   {
      super.paintComponent(g);
      g.drawImage(sprites.get(),
                  (int)location.getX(),
                  (int)location.getY(),
                  null);
   }

}

如果我像下面这样直接将它添加到 JFrame 中,那么图形会按照我的预期显示在窗口上(请注意,Player 是 Entity 的一个非常简单的子类)

public class Window {

   private JFrame window;

   public Window()
   {
      SwingUtilities.invokeLater(this::run);
   }

   private void run()
   {
      try {
         window = new JFrame();
         window.setDefaultCloseOperation(window.EXIT_ON_CLOSE);
         window.setLocationByPlatform(true);
         window.setUndecorated(true);
         Player p = new Player(0,0);
         window.add(p);
         window.setExtendedState(JFrame.MAXIMIZED_BOTH);
         window.setVisible(true);
      } catch (IOException e) {
         // TODO handle exception
         e.printStackTrace();
      }
   }
}

但是 - 当我创建一个名为 World 的类时,它也扩展了 JPanel,将 that 添加到窗口,然后在其构造函数中使用 add() 方法向它添加一个新的 Player,它没有出现。有趣的是,如果我将setBackground() 添加到 Player/Entity 的构造函数中,我可以在实体应该在的位置看到一个彩色方块。只是 drawImage 似乎不起作用。

如果有人知道这里发生了什么,将不胜感激!

【问题讨论】:

  • 提供也有问题的代码。
  • 1) 为了尽快获得更好的帮助,请发帖 minimal reproducible exampleShort, Self Contained, Correct Example。 2) 例如,获取图像的一种方法是热链接到在this Q&A 中看到的图像。
  • 顺便说一句 - 似乎基本问题是布局。在更“这是解决方案”的方法中,在单个 JPanel 中绘制每个游戏元素。所以EntityPlayer 不应该扩展任何JComponent,而只是知道在需要时如何以及在哪里将自己吸引到Graphics 实例。
  • 谢谢@AndrewThompson,我以后会努力做到的。

标签: java image swing jpanel


【解决方案1】:

如果我像下面这样直接将它添加到 JFrame 中,那么图形会按照我的预期显示在窗口上

框架内容窗格的默认布局管理器是BorderLayout。任何无约束添加到框架的组件都将添加到“CENTER”,这意味着组件会自动调整大小以填充整个空间。

但是 - 当我创建一个名为 World 的类同时扩展 JPanel 时,将其添加到窗口中,然后在其构造函数中使用 add() 方法向其中添加一个新 Player,它不会出现。

JPanel 的默认布局管理器是 FlowLayout,它尊重添加到其中的任何组件的首选大小,并将根据布局管理器的规则重置组件的位置。

有趣的是,如果我将 setBackground() 添加到 Player/Entity 的构造函数中,我可以看到实体应该存在的彩色方块。只是drawImage似乎不起作用

可能是因为您的首选尺寸计算不正确,图像被截断。

  location     = new Point(x, y);
  dimensions   = new Dimension(w, h);

上述代码仅在 Point 为 (0, 0) 时有效。更一般的案例代码应该是:

  location     = new Point(x, y);
  dimensions   = new Dimension(x + w, y + h);

因为您需要考虑实际绘制与组件相关的图像的位置。

因此,当您执行此操作时,您应该会看到图像,但是您不会在正确的位置看到图像,因为布局管理器会覆盖该位置。

因此,如果您想继续这种使用组件的方法,您将需要使用空布局,这意味着您将需要手动使用每个组件的 setSize(...) 和 setLocation(...)。在这种情况下,组件的大小将是 (w, h),您将使用以下方法绘制图像:

  g.drawImage(sprites.get(), 0, 0, this);

但是请注意,如果您使用组件方法,则甚至不需要创建自定义组件。您可以只使用JLabelImageIcon。您将在创建标签时分配图标。

【讨论】:

  • 谢谢!我最终以不同的方式解决了它,但我认为这接近于我将得到的原始问题的答案。
猜你喜欢
  • 1970-01-01
  • 2012-08-30
  • 2010-12-31
  • 1970-01-01
  • 1970-01-01
  • 2014-04-24
  • 1970-01-01
  • 2016-04-11
  • 2021-10-10
相关资源
最近更新 更多