使用缓冲策略绘制图形对象

时间:2017-11-19 13:40:17

标签: java swing canvas graphics buffer

我已经制作了一个带有画布的JFrame,我想在画布上画画。在稍后的日期,画布将每秒更新许多次,所以我使用缓冲策略。这是代码:

package mainPackage;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;

public class TickPainter {
    //just some presets for a window.
    public static JFrame makeWindow(String title, int width, int height) {
        JFrame mainWindow = new JFrame();
        mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainWindow.setSize(width, height);
        mainWindow.setVisible(true);
        mainWindow.setLocationRelativeTo(null);
        mainWindow.setTitle(title);

        return mainWindow;      
    }

    public static void main(String[] args) {

        JFrame mainWindow = makeWindow("Practice", 800, 600);
        Canvas mainCanvas = new Canvas();
        mainWindow.add(mainCanvas);
        mainCanvas.setSize(mainWindow.getWidth(), mainWindow.getHeight());
        mainCanvas.setBackground(Color.white);
        mainCanvas.createBufferStrategy(3);
        BufferStrategy bufferStrat = mainCanvas.getBufferStrategy();

        Graphics g = bufferStrat.getDrawGraphics();
        g.setColor(Color.black);
        g.fillRect(250, 250, 250, 250);
        g.dispose();
        bufferStrat.show();
    }
}

程序没有按照预期绘制黑色矩形,我觉得我错过了一些非常明显的东西而且我无法看到它。目前该程序只是制作一个空白的白色画布。我觉得问题的一部分是缓冲区只是通过框架,矩形比我看到的更快,但是没有框架可以加载,所以我不知道它为什么这样做

1 个答案:

答案 0 :(得分:1)

BufferStrategy有许多初始要求,必须满足这些要求才能呈现。此外,由于其工作方式的性质,您可能需要多次重复绘制阶段才能实际接受硬件层。

我建议浏览JavaDocstutorial,它们提供了宝贵的示例,说明您如何使用BufferStrategy

以下示例使用Canvas作为基本组件,并在自定义Thread中设置呈现循环。它非常基础,但展示了您需要实施的基本概念......

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Test {

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

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                TestCanvas canvas = new TestCanvas();

                JFrame frame = new JFrame();
                frame.add(canvas);
                frame.setTitle("Test");
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                canvas.start();
            }
        });
    }

    public class TestCanvas extends Canvas {

        private Thread thread;
        private AtomicBoolean keepRendering = new AtomicBoolean(true);

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

        public void stop() {
            if (thread != null) {
                keepRendering.set(false);
                try {
                    thread.join();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }

        public void start() {
            if (thread != null) {
                stop();
            }

            keepRendering.set(true);
            thread = new Thread(new Runnable() {
                @Override
                public void run() {

                    createBufferStrategy(3);

                    do {
                        BufferStrategy bs = getBufferStrategy();
                        while (bs == null) {
                            System.out.println("get buffer");
                            bs = getBufferStrategy();
                        }
                        do {
                            // The following loop ensures that the contents of the drawing buffer
                            // are consistent in case the underlying surface was recreated
                            do {
                                // Get a new graphics context every time through the loop
                                // to make sure the strategy is validated
                                System.out.println("draw");
                                Graphics graphics = bs.getDrawGraphics();

                                // Render to graphics
                                // ...
                                graphics.setColor(Color.RED);
                                graphics.fillRect(0, 0, 100, 100);
                                // Dispose the graphics
                                graphics.dispose();

                                // Repeat the rendering if the drawing buffer contents
                                // were restored
                            } while (bs.contentsRestored());

                            System.out.println("show");
                            // Display the buffer
                            bs.show();

                            // Repeat the rendering if the drawing buffer was lost
                        } while (bs.contentsLost());
                        System.out.println("done");
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException ex) {
                            ex.printStackTrace();
                        }
                    } while (keepRendering.get());
                }
            });
            thread.start();
        }

    }

}

请记住,BufferStrategy的目的是让你完全控制绘画过程,因此它在通常由AWT和Swing实现的正常绘画过程之外工作

"稍后画布将每秒更新多次,因此我正在使用缓冲策略" - 在进入"直接到硬件"解决方案,我考虑使用Swing Timer和正常的绘画过程来看看它的运作情况