首页 > 解决方案 > Java:图像、图形和面板

问题描述

我正在尝试通过 Java 制作动画,但无法理解 DoubleBufferImage 和 DoubleBufferGraphics。我了解 update()、render() 和 paint() 序列。但是,在每个方法中,我无法理解它是如何绘制的。这是代码。

  1. gameUpdate() // 我将跳过更新部分,因为我首先需要了解背景。

  2. 游戏渲染()

    private void gameRender() {
        if (DoubleBufferImage == null) {
            System.out.println("The Image is null: Error occurence");
            DoubleBufferImage = createImage(P_WIDTH - 15, P_HEIGHT - 15);
        }
    
        DoubleBufferGraphic = DoubleBufferImage.getGraphics();
    
        DoubleBufferGraphic.setColor(Color.LIGHT_GRAY);
        DoubleBufferGraphic.fillRect(0, 0, P_WIDTH, P_HEIGHT);
    
        DoubleBufferGraphic.setColor(Color.BLUE);
        DoubleBufferGraphic.setFont(font);
        DoubleBufferGraphic.drawString("Average FPS/UPS: " + 
                df.format(averageFPS) + df.format(averageUPS), 10, 10);
    }
    
  3. 画()

    public void paintScreen() {
        Graphics g;     
        try {           
            g = this.getGraphics();
            if ((g != null) && (DoubleBufferImage != null)) {               
                g.drawImage(DoubleBufferImage, 0, 0, null);         
            }           
            Toolkit.getDefaultToolkit().sync();     
        } catch (Exception e) {         
            System.out.println("Graphics context error: " + e);     
        }   
    }
    

还有从 Jpanel 覆盖的 paintComponent 方法。

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (DoubleBufferImage != null) {
        g.drawImage(DoubleBufferImage, 0, 0, null);
    }
}

这是我的问题。运行是更新->渲染->和绘画但是从渲染中可以看出,他们使用图形来绘制。但这都是在 DoubleBufferImage 中绘制的吗?Image 实例是否类似于面板实例?我的意思是,它只是可添加到框架中吗?由于这是双缓冲系统,所以我想知道哪些方法是直接绘制的,哪些是预先绘制的方法。最后在运行中,没有任何代码表明我们制作的图像或图形将被添加到面板中。我只想知道绘制 BufferedImage 的时间。请帮忙!我无法上传整个代码,所以我不确定你们是否能理解:(

标签: javaswing

解决方案


好的,所以你似乎在反对一些错误信息和误解。也许您应该首先在画笔类型的 GUI 中查看诸如 paintComponent() 与 paint() 以及 JPanel 与 Canvas 之类的东西

在 AWT/Swing 中,至少有两种执行自定义绘画的方式,每种方式各有利弊。

您可以使用paintComponent,它是 Swing 使用的绘画系统的“钩子”。Swing 使用“被动”渲染系统。这意味着您无法控制何时绘制某些东西,绘制系统会做出这些决定,然后(间接)调用paintComponent组件的,以便您可以执行更新。

另一种机制 ( BufferStrategy) 使用“主动”渲染系统,它可以让您完全控制绘画发生的时间。

作为一般规则,你不能混合它们。Swing 有自己的绘画系统,不能很好地与BufferStrategy.

但这不会回答你的问题,或者不会直接回答

让我们尝试分解它

gameRender

private void gameRender() {
    if (DoubleBufferImage == null) {
        System.out.println("The Image is null: Error occurence");
        DoubleBufferImage = createImage(P_WIDTH - 15, P_HEIGHT - 15);
    }

    DoubleBufferGraphic = DoubleBufferImage.getGraphics();

    DoubleBufferGraphic.setColor(Color.LIGHT_GRAY);
    DoubleBufferGraphic.fillRect(0, 0, P_WIDTH, P_HEIGHT);

    DoubleBufferGraphic.setColor(Color.BLUE);
    DoubleBufferGraphic.setFont(font);
    DoubleBufferGraphic.drawString("Average FPS/UPS: " + 
            df.format(averageFPS) + df.format(averageUPS), 10, 10);
}

此时,DoubleBufferImage 似乎是 a BufferedImage,所以当gameRender被调用时,它会检查缓冲区是否存在并根据需要创建它。DoubleBufferImage然后它获取s上下文的引用Graphics并准备渲染,清除之前绘制的内容。

快速概览Graphics

Graphics是底层渲染管道顶部的抽象层,通常使用 OpenGL 或 DirectX 来实现,具体取决于系统。它提供了一个公共层,可以在该层上以独立于系统的方式执行图形操作

paintScreen

public void paintScreen() {
    Graphics g;     
    try {           
        g = this.getGraphics();
        if ((g != null) && (DoubleBufferImage != null)) {               
            g.drawImage(DoubleBufferImage, 0, 0, null);         
        }           
        Toolkit.getDefaultToolkit().sync();     
    } catch (Exception e) {         
        System.out.println("Graphics context error: " + e);     
    }   
}

这让我很担心,因为我没有上下文,但this.getGraphics()似乎正在参考组件的Graphics上下文并绘制DoubleBufferImage它。

这是危险的,也是不明智的。getGraphics返回组件上次绘制时的快照,可以在再次绘制组件时随时绘制。

您应该尽早摆脱这种方法。

paintComponent

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (DoubleBufferImage != null) {
        g.drawImage(DoubleBufferImage, 0, 0, null);
    }
}

如上所述,paintComponent这是挂钩到 Swing 油漆系统的首选方法。所有这一切都是描绘DoubleBufferImage它,尽管它实际上应该阅读g.drawImage(DoubleBufferImage, 0, 0, this);

那么,这一切在做什么呢?

基本上,在 Swing 中执行双缓冲是不明智的尝试……默认情况下它已经是双缓冲的。

但是,正如您从渲染中看到的那样,他们使用图形进行绘制。但这都是在 DoubleBufferImage 中绘制的吗?Image 实例是否类似于面板实例?

不,组件是一个对象,它具有许多属性。它的工作之一是绘制它的状态,这是通过各种绘制方法完成的,它传递一个Graphics附加到本机对等点的上下文,最终将呈现到屏幕(或打印机)。

ABufferedImage就是这样,一个图像。Graphics上下文只是一种简单的方法,您可以通过它来绘制它。然后可以将其保存到文件中,或者像这里的情况一样,将其绘制到组件(通过它的Graphics)上下文中。

正如我上面所说,Graphics只是一个抽象层,它允许您对多个不同的目的地、屏幕、打印机、图像等执行绘画操作......

我的意思是,它只是可添加到框架中吗?

不,它不是基于组件的类

由于这是双缓冲系统,所以我想知道哪些方法是直接绘制的,哪些是预先绘制的方法。

paintComponent并且(不明智的)paintScreen将图像直接绘制到组件上,最终将由绘制子系统渲染到屏幕上。

进一步阅读...


推荐阅读