首页 > 解决方案 > 画布未绘制到 JFrame

问题描述

我一直在寻找答案,多次重写我的代码,仍然没有。本质上,我试图绘制一个只包含一个简单矩形的 JFrame,但每次在 Frame 中什么都没有显示 - 它只是空白。

package com.Graphics;

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

public class GraphicsMain {

    public static void main(String[] args) {

        GraphicsMain myGraphics = new GraphicsMain();

        myGraphics.createDisplay();

    }

    void createDisplay(){

        int width = 500;
        int height = 500;
        String title = "TestFrame";
        Graphics g;

        Canvas myCanvas = new Canvas();
        JFrame myFrame = new JFrame(title);

        myFrame.setVisible(true);
        myFrame.setResizable(false);
        myFrame.setSize(width, height);
        myFrame.setLocationRelativeTo(null);
        myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        myCanvas.setPreferredSize(new Dimension(500, 500));
        myCanvas.setMaximumSize(new Dimension(500, 500));
        myCanvas.setMinimumSize(new Dimension(500, 500));

        myFrame.add(myCanvas);
        myFrame.pack();

        myCanvas.createBufferStrategy(2);

        BufferStrategy bs = myCanvas.getBufferStrategy();

        g = bs.getDrawGraphics();

        g.setColor(Color.red);
        g.fillRect(10, 50, 50, 70);

        bs.show();
        g.dispose();
    }
}

我意识到这里的约定很糟糕——这只是我对图形的一种练习。通常我会把它分成单独的类等。非常感谢任何帮助。谢谢你。

标签: javaswinggraphicsawt

解决方案


BufferStrategy是一种低级绘画机制,可让您完全控制绘画过程。有了这种“力量”,您需要准备好管理一些复杂性

JavaDocsBufferStrategy 和 BufferCapabilities提供了一些关于如何管理 API 的优秀示例。

API 是易变的,这意味着您需要进行多次检查以确保您所绘制的内容已正确传递到渲染管道/硬件,否则您需要再次重复绘制过程。这是您可能遇到问题的地方。

您还需要记住,虽然setVisible立即返回,但这并不意味着窗口在屏幕上可见或已完全实现(附加到本机对等点),这也会影响何时BufferStrategy准备好绘制。

例如...

例子

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;

public class Test extends Canvas implements Runnable {

    private static final long serialVersionUID = 1L;

    public static int WIDTH = 200;
    public static int HEIGHT = 200;

    private Thread thread;
    private boolean running = false;

    public Test() {
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(WIDTH, HEIGHT);
    }

    public synchronized void start() {
        running = true;
        thread = new Thread(this, "Display");
        thread.start();

    }

    public synchronized void stop() {
        running = false;
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void run() {
        while (running) {
            update();
            render();

            // Control frame rate
            try {
                Thread.sleep(5);
            } catch (InterruptedException ex) {
            }
        }

    }

    public void update() {
        // Make changes to the model which need to be painted
    }

    public void render() {
        BufferStrategy bs = getBufferStrategy();
        if (bs == null) {
            createBufferStrategy(3);
            return;
        }

        do {
            do {
                Graphics2D g = (Graphics2D) bs.getDrawGraphics();
                // You MUST clear the page before painting, bad things
                // happen otherwise
                g.setColor(Color.WHITE);
                g.fillRect(0, 0, getWidth(), getHeight());
                g.setColor(Color.red);
                g.fillRect(10, 50, 50, 70);
                g.dispose();
            } while (bs.contentsRestored());
            bs.show();
        } while (bs.contentsLost());
    }

    public static void main(String[] args) {
        Test test = new Test();
        JFrame frame = new JFrame();
        frame.add(test);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        test.start();

    }

}

现在,这个例子还有一个“主循环”的基本概念,它负责提供基线,您可以从中生成动态内容并渲染它。但是您可以简单地尝试调用render一个窗口可见

正如我所说,BufferStrategy它是一个低级 API,它功能强大、灵活且管理复杂。

一个更简单的解决方案可能是通过 Swing 进行自定义绘画路线。有关更多详细信息,请参阅在 AWT 和 Swing中执行自定义绘画和绘画。Swing 组件提供自动双缓冲,并且为您完成了绘制调度(尽管您确实需要使用诸如运行绘制通道之类的东西)repaint


推荐阅读