【问题标题】:Paint from different classes不同等级的油漆
【发布时间】:2020-12-22 15:20:49
【问题描述】:

我正在尝试用 Java(学校项目)制作游戏,并且我有以下设置:

一个用 JFrame 扩展的主类,一个用 JPanel 扩展的“游戏”类。

现在,在这个主类中,我调用了“Player”类和“Map”类。“Map”类存在两个子类“Blocks”和“Bombs”。

但我想知道..如何让所有这些类的绘制方法绘制到同一个 JPanel(类 Game)?

我给每个类都提供了“public void paint(Graphics g)”方法并进行绘画。但是当我运行程序时,只显示“游戏”类的绘画,而不是子类的绘画。

我该如何实现?

例如,我将代码简化为:

主类:

    BomberGame game = new BomberGame();
        add(game);
        setSize(400, 400);
        setTitle("Bomber");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.show();

    }

    public static void main(String[] args) {
        BomberB1 main = new BomberB1();
    }
}

游戏类:

    package bomberb1;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


import java.util.ArrayList;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class BomberGame extends JPanel {
    public BomberGame() {;
        BomberMap map = new BomberMap(this);
    }

    public void paint(Graphics g) {
        g.drawRect(10, 10, 10, 10);
        g.setColor(Color.red);
        g.fillRect(10, 10, 10, 10);
    }
}

地图类:

    package bomberb1;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.*;
import javax.swing.SwingUtilities;
public class BomberMap{
    BomberGame game;
    public BomberMap(BomberGame game) {
        this.game = game;
    }
    public void paint(Graphics g) {
        g.drawRect(30, 30, 20, 20);
    }
}

【问题讨论】:

  • "Swing 程序应该覆盖paintComponent(),而不是覆盖paint()。"—Painting in AWT and Swing: The Paint Methods
  • 如何让所有这些类的绘制方法绘制到同一个 JPanel 你不会!这确实是您可以选择的最糟糕的设计。您正在混合模型和视图(另请参阅 MVC 模式)。您应该创建不同的视图并将这些面板相互嵌套。这是具有图形层次结构的目的(每个子区域绘制其父区域的子区域)。

标签: java swing graphics paintcomponent


【解决方案1】:

在要绘制的实体类(可能是地图播放器等)中有一个draw 方法,该方法接受一个Graphics 对象,因此允许它访问JPanelGraphics 对象并绘制到它,类似:

class GamePanel extends JPanel {

    Entity e=new Entity;

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

        e.draw(g);//call draw method for entity and pass graphics object
    }

}

class Entity {

   //will draw whats necessary to Graphics object
    public void draw(Graphics g) {
        //draw to the graphics object here
    }
}

其他建议:

  • 不要不必要地扩展 JFrame
  • 覆盖 JPanel paintComponent() 而不是 paint()(+1 到垃圾神评论)
  • 应通过 SwingUtilities.invokeLater(..) 块在 Event Dispatch Thread 上创建和操作 Swing 组件。

更新:

正如@GuillaumePolet 所说,更好的游戏设计将实现JPanels 作为大多数游戏实体的父类,请参阅this 类似的答案了解更多信息。

【讨论】:

  • IMO,Entity 也应该是 JComponent 并覆盖 paintComponent 并且应该是 GamePanel 的子项。
  • @GuillaumePolet +1 我想这将取决于 OP 选择的游戏设计,但是是的,这将是一个选项。
  • @GuillaumePolet 或“在图像中绘画”,如 here 所示。这些天,当我打算将组件放在它的顶部(非常非常罕见)或需要 1000 FPS(?)性能(但这看起来像“全屏独占模式”时,我只倾向于扩展自定义绘画的组件方式)。
猜你喜欢
  • 1970-01-01
  • 2013-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多