为什么在 Jpanel 中使用 drawImage 会失败
Why does drawImage fail when I am using it inside a Jpanel
我正在 Java 中做一个简单平台游戏的初始部分。我创建了一个名为 entity
的 class,它扩展了 JPanel
并成功地将其添加到 window。
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 中,如下图所示,图形将如我所料显示在 window 上(注意 Player 是 Entity 的一个非常简单的子 class )
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 的 class 时,它也扩展了 JPanel,将 that 添加到 window,然后使用 add()
方法在它的构造函数中添加一个新的 Player,它没有出现。有趣的是,如果我将 setBackground()
添加到 Player/Entity 的构造函数中,我可以在实体应该所在的位置看到一个彩色方块。只是 drawImage 好像不行。
如果其他人知道这里发生了什么,将不胜感激!
If I add this directly to the JFrame as below, then the graphic shows up on the window as I would expect it to
框架内容窗格的默认布局管理器是 BorderLayout
。任何无约束添加到框架的组件都将添加到 "CENTER",这意味着组件会自动调整大小以填充整个 space.
However - when I create a class called World which also extends JPanel, add that to the window instead, then use the add() method in its constructor to add a new Player to it, it doesn't appear.
JPanel
的默认布局管理器是 FlowLayout
,它尊重添加到其中的任何组件的首选大小,并将根据布局规则重置组件的位置经理。
Interestingly, if I add setBackground() to the constructor for Player/Entity, I can see a coloured square where the entity SHOULD be. Its just that drawImage doesn't appear to work
可能是因为您的首选尺寸计算不正确,图片被截断了。
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);
但是请注意,如果您使用组件方法,则甚至不需要创建自定义组件。您可以只使用 JLabel
和 ImageIcon
。您将在创建标签时指定图标。
我正在 Java 中做一个简单平台游戏的初始部分。我创建了一个名为 entity
的 class,它扩展了 JPanel
并成功地将其添加到 window。
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 中,如下图所示,图形将如我所料显示在 window 上(注意 Player 是 Entity 的一个非常简单的子 class )
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 的 class 时,它也扩展了 JPanel,将 that 添加到 window,然后使用 add()
方法在它的构造函数中添加一个新的 Player,它没有出现。有趣的是,如果我将 setBackground()
添加到 Player/Entity 的构造函数中,我可以在实体应该所在的位置看到一个彩色方块。只是 drawImage 好像不行。
如果其他人知道这里发生了什么,将不胜感激!
If I add this directly to the JFrame as below, then the graphic shows up on the window as I would expect it to
框架内容窗格的默认布局管理器是 BorderLayout
。任何无约束添加到框架的组件都将添加到 "CENTER",这意味着组件会自动调整大小以填充整个 space.
However - when I create a class called World which also extends JPanel, add that to the window instead, then use the add() method in its constructor to add a new Player to it, it doesn't appear.
JPanel
的默认布局管理器是 FlowLayout
,它尊重添加到其中的任何组件的首选大小,并将根据布局规则重置组件的位置经理。
Interestingly, if I add setBackground() to the constructor for Player/Entity, I can see a coloured square where the entity SHOULD be. Its just that drawImage doesn't appear to work
可能是因为您的首选尺寸计算不正确,图片被截断了。
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);
但是请注意,如果您使用组件方法,则甚至不需要创建自定义组件。您可以只使用 JLabel
和 ImageIcon
。您将在创建标签时指定图标。