【问题标题】:Canvas fillRect() not filling defined canvas画布fillRect()没有填充定义的画布
【发布时间】:2013-01-20 02:39:10
【问题描述】:

我正在扩展 Canvas 并将其添加到 JFrame。我知道 AWT 和 Swing 不应该混合使用,并且首选在 JPanel 上绘图,但我正在尝试遵循游戏引擎教程,我想坚持下去,因为到目前为止我已经开始工作了。 CanvasminimumSizemaximumSizeprefferedSize 设置为550, 400 的尺寸。当我进行绘图调用graphics.draw(0,0,550,400) 时,它并没有按应有的方式填满整个屏幕。我将绘图调用更改为graphics.draw(0,0,560,410),本质上添加了 10px 并填满了整个屏幕。怎么了?

顺便说一句:graphics.draw(10,10,550,400 准确地从角落开始绘制矩形,所以我认为 JFrame 不是问题。

Launcher类里面的主要调用

    public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            game.setMinimumSize(DIMENSIONS);
            game.setMaximumSize(DIMENSIONS);
            game.setPreferredSize(DIMENSIONS);

            game.frame = new JFrame(NAME);
            game.frame.setLayout(new BorderLayout());
            game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            game.frame.add(game, BorderLayout.CENTER);
            game.frame.pack();

            game.frame.setResizable(false);
            game.frame.setLocationRelativeTo(null);
            game.frame.setVisible(true);

            Logger.log(TAG, "Game starting");
            game.start();
        }
    });
}

draw call,Launcher.HEIGHTWIDTH550,400

    public void draw(float deltaTime, Graphics2D graphics) {
    graphics.setColor(Color.BLACK);
    graphics.fillRect(0, 0, 550, 400);
    graphics.setColor(Color.DARK_GRAY);
    graphics.fillRect(0, 0, 150, 40);
    graphics.fillRect(0, Launcher.HEIGHT - 100, Launcher.WIDTH, 100);
    graphics.setColor(Color.LIGHT_GRAY);
    graphics.fillRect(125, Launcher.HEIGHT - 100, 100, 350);
}

扩展的Canvas

public abstract class Game extends Canvas implements Runnable {
private static final String TAG = "Game";

public JFrame frame;
public JPanel panel;
public boolean isApplet = false;

private boolean gameRunning = false;

BufferStrategy bufferStrategy;

private Screen screen;
private Thread renderThread;

public synchronized void start() {
    // Canvas
    setBounds(0, 0, 550, 400);
    setIgnoreRepaint(true);
    createBufferStrategy(2);
    bufferStrategy = getBufferStrategy();

    // Screen, Handlers, ETC
    screen = getStartScreen();

    // Threads
    renderThread = new Thread(this, Launcher.NAME + "_main");
    renderThread.start();
    gameRunning = true;
}

@Override
public void run() {
    long startTime = System.nanoTime();

    while (gameRunning) {
        float deltaTime = (System.nanoTime() - startTime) / 1000000000.0f;
        startTime = System.nanoTime();

        screen.update(deltaTime);

        Graphics2D graphics = (Graphics2D) bufferStrategy.getDrawGraphics();

        screen.draw(deltaTime, graphics);

        graphics.dispose();
        bufferStrategy.show();

        // FPS Counter

        // FPS Capper
    }
}
}

要求的 SSCCE

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class Game extends Canvas implements Runnable {

    public static final int WIDTH = 550;
    public static final int HEIGHT = 400;
    public static final Dimension DIMENSIONS = new Dimension(WIDTH, HEIGHT);

    public static final String NAME = "SSCCE";

    public boolean gameRunning = false;

    public JFrame frame;
    public BufferStrategy bufferStrategy;

    public static void main (String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Game game = new Game();
                game.setMinimumSize(DIMENSIONS);
                game.setMaximumSize(DIMENSIONS);
                game.setPreferredSize(DIMENSIONS);

                game.frame = new JFrame(NAME);
                game.frame.setLayout(new BorderLayout());
                game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                game.frame.add(game, BorderLayout.CENTER);
                game.frame.pack();

                game.frame.setResizable(false);
                game.frame.setLocationRelativeTo(null);
                game.frame.setVisible(true);

                System.out.println("Game started");
                game.start();
            }
        });
    }

    public synchronized void start() {
        setSize(550, 400);
        setBounds(0, 0, 550, 400);
        setIgnoreRepaint(true);
        createBufferStrategy(2);
        bufferStrategy = getBufferStrategy();

        // Threads
        Thread renderThread = new Thread(this, NAME + "_main");
        renderThread.start();
        gameRunning = true;
    }

    @Override
    public void run() {
        while (gameRunning) {
            Graphics2D graphics = (Graphics2D) bufferStrategy.getDrawGraphics();

            graphics.setColor(Color.BLACK);
            graphics.fillRect(0, 0, WIDTH, HEIGHT);

            graphics.dispose();
            bufferStrategy.show();
        }
    }

}

至于我关注的 Java 2D 游戏教程是一个网络系列。尽管如此,链接是以下click here。我修改了很多代码。

为 MadProgrammer 修改

    import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class Game extends Canvas implements Runnable {

    public static final int WIDTH = 550;
    public static final int HEIGHT = 400;
    public static final Dimension DIMENSIONS = new Dimension(WIDTH, HEIGHT);

    public static final String NAME = "SSCCE";

    public boolean gameRunning = false;

    public JFrame frame;
    public BufferStrategy bufferStrategy;

    public static void main (String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Game game = new Game();
                game.setMinimumSize(DIMENSIONS);
                game.setMaximumSize(DIMENSIONS);
                game.setPreferredSize(DIMENSIONS);

                game.frame = new JFrame(NAME);
                game.frame.setLayout(new BorderLayout());
                game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                game.frame.add(game, BorderLayout.CENTER);
                game.frame.pack();

                game.frame.setResizable(false);
                game.frame.setLocationRelativeTo(null);
                game.frame.setVisible(true);

                System.out.println("Game started");
                game.start();
            }
        });
    }

    public synchronized void start() {
        setSize(550, 400);
        setBounds(0, 0, 550, 400);
        setIgnoreRepaint(true);
        createBufferStrategy(2);
        bufferStrategy = getBufferStrategy();

        // Threads
        Thread renderThread = new Thread(this, NAME + "_main");
        renderThread.start();
        gameRunning = true;
    }

    @Override
    public void run() {
        while (gameRunning) {
            Graphics2D graphics = (Graphics2D) bufferStrategy.getDrawGraphics();

            graphics.setColor(Color.RED);
            // Using getWidth()
            graphics.fillRect(0, 0, getWidth(), getHeight());
            graphics.setColor(Color.GREEN);
            // Using WIDTH which was used to set the size of the canvas
            graphics.fillRect(5, 5, WIDTH, HEIGHT);

            graphics.dispose();
            bufferStrategy.show();

            try {
                Thread.sleep(60);
            } catch (InterruptedException ex) {
            }
        }
    }

}

【问题讨论】:

  • 你能发布一些你目前拥有的代码吗?
  • 你能显示一些代码吗?如果没有布局管理器,单独设置 minimumSizemaximumSizeprefferedSize 是不够的 - 要设置实际大小,请使用 setSize()
  • 你的 LayoutManager 可能会改变 Canvas 的大小。发布构建 gui 的代码。
  • 代码贴出,感谢大家的回复!
  • 如需尽快获得更好的帮助,请发帖SSCCE

标签: java swing awt java-2d


【解决方案1】:

您提供的示例运行良好。我稍微修改了一下,演示一下getWidth/height的用法

public void run() {
    while (gameRunning) {
        Graphics2D graphics = (Graphics2D) bufferStrategy.getDrawGraphics();

        graphics.setColor(Color.RED);
        graphics.fillRect(0, 0, getWidth(), getHeight());
        graphics.setColor(Color.GREEN);
        int width = getWidth() - 50;
        int height = getHeight() - 50;
        graphics.fillRect(25, 25, width, height);
        graphics.setColor(Color.BLACK);
        FontMetrics fm = graphics.getFontMetrics();
        graphics.drawString("Frame Size: " + frame.getWidth() + "x" + frame.getHeight(), 0, fm.getAscent());
        graphics.drawString("Canvas Size: " + getWidth() + "x" + getHeight(), 0, fm.getAscent() + fm.getHeight());

        graphics.dispose();
        bufferStrategy.show();
        try {
            Thread.sleep(60);
        } catch (InterruptedException ex) {
        }
    }
}

【讨论】:

  • 我编辑了我的问题,请编译它以了解我的意思。我不明白为什么getWidth 会给我一个比WIDTH 高10px 的值,我用于画布尺寸、边界和大小。我还将 JFrame 设置为不可调整大小。我知道getWidth 会给我更准确的尺寸,但最终我想做的是让WIDTHgetWidth 共享相似的值。
  • 框架总是比画布大。框架有边框。这是确保您是从 Canvas 而不是框架创建缓冲区策略的重要方式。
  • 对,但我将 Canvas 设置为这些尺寸而不是框架。框架没有尺寸,只是拉伸以适应画布。
  • @synjunked 从您更新的示例中,我仍然没有问题。确保当您在 Canvas 而不是框架上调用 getWidth/Height 时。
  • 啊,我想这是在静态宽度上使用getWidth 的完美示例。不同的操作系统有不同的功能。感谢您的示例!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-08
  • 2018-11-30
  • 1970-01-01
相关资源
最近更新 更多