Java 画布未绘制到JFrame

Java 画布未绘制到JFrame,java,swing,graphics,awt,Java,Swing,Graphics,Awt,我一直在寻找这个问题的答案,多次重新编写代码,仍然一无所获。本质上,我试图绘制一个只包含一个简单矩形的JFrame,但每次框架中都没有显示任何内容—它只是空白 package com.Graphics; import java.awt.*; import java.awt.image.*; import javax.swing.*; public class GraphicsMain { public static void main(String[] args) {

我一直在寻找这个问题的答案,多次重新编写代码,仍然一无所获。本质上,我试图绘制一个只包含一个简单矩形的JFrame,但每次框架中都没有显示任何内容—它只是空白

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();
    }
}

我意识到这里的惯例很糟糕——这只是我对图形的一种练习。通常情况下,我会把它分成不同的类等。任何帮助都是非常感谢的。谢谢。

BufferStrategy
是一种低级绘画机制,可将绘画过程的完全控制权交给您。伴随着这种“力量”而来的是一些你需要准备好管理的复杂性

并提供了许多关于必须如何管理API的优秀示例

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

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

例如

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

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


一个更简单的解决方案可能是通过Swing进行自定义绘制。有关更多详细信息,请参阅和。Swing组件提供自动双缓冲,绘制计划为您完成(尽管您确实需要使用
重新绘制
之类的方法来运行绘制过程)

@ElarbiMohamedAymen请不要建议只从代码中删除所有空行的编辑。这会严重损害可读性,在本例中,代码格式(缩进)存在一个实际问题,您没有费心解决这个问题。另请参见。您应该使用
JPanel
,重写
paintComponent(Graphics gc)
方法,并在其中绘制矩形。感谢程序员的帮助。我想我有一些关于这个API的研究要做。。。哈哈,这只是一个简单的问题,关于为什么一个人必须像上面那样做?我在上面发布的方法中基本上完成了所有这些,但显然排除了线程和各种方法。只是不明白为什么要这样做。再次感谢您的帮助:)@Matthew您没有做的是检查缓冲区的内容是否已成功传递到渲染管道(即缓冲区是否在绘制过程中无效)-请参阅
render
方法中的double
do while
循环。正如我所说,仅仅因为您调用了
setVisible
,并不意味着窗口(在屏幕上)是可见的,也不意味着它已经准备好进行绘制了。好的,您在消息的开头也这么说。不知怎么错过了。最后一个问题,为什么会发生这样的事情?为什么缓冲区的内容不能成功通过?@Matthew视频卡的内存是共享的且“不稳定的”,这意味着视频卡可以决定将其从您手中拿走(或做其他事情),因为
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();

    }

}