前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Java AWT 图形界面编程】Canvas 组件中使用 Graphics 绘图 ④ ( AWT 绘图窗口闪烁问题 )

【Java AWT 图形界面编程】Canvas 组件中使用 Graphics 绘图 ④ ( AWT 绘图窗口闪烁问题 )

作者头像
韩曙亮
发布2023-03-30 18:47:46
7680
发布2023-03-30 18:47:46
举报

文章目录

画图的过程是有时间消耗的 , 先清屏 , 再画图 , 清屏到画图完毕之前 界面是空白的 , 这是闪烁产生的原因 ;

引入一个图片缓冲区 , 绘制的时候向缓冲区绘制 , 然后直接将缓冲区同步到画布上 , 这样就避免了界面空白情况 , 保证始终界面上有内容 ;

这就是双缓冲机制的原理 ;

一、AWT 绘图窗口闪烁问题


使用 Graphics 第一次绘图 完成后 , 如果在循环中 持续调用 Canvas#repaint() 函数刷新界面 , 代码如下 :

代码语言:javascript
复制
import java.awt.*;

public class HelloAWT {
    public static void main(String[] args) throws InterruptedException {
        // Frame 默认的布局管理器就是 BorderLayout
        Frame frame = new Frame("AWT 界面编程");

        MyCanvas myCanvas = new MyCanvas();
        frame.add(myCanvas);

        // 自动设置 Frame 窗口合适的大小
        frame.setBounds(0, 0, 300, 300);
        frame.setVisible(true);

        while (true) {
            Thread.sleep(1000);
            myCanvas.repaint();
        }
    }

    static class MyCanvas extends Canvas {
        @Override
        public void paint(Graphics g) {
            // 绘制图形
            g.setColor(Color.BLACK);

            // 绘制线段
            g.drawLine(10, 10, 100, 10);

            // 绘制矩形
            g.drawRect(10, 15, 200, 50);

            // 绘制圆形
            g.drawOval(50, 100, 100, 100);
        }
    }
}

此时就会发现 AWT 界面中一直在闪烁 ; 每次刷新都闪烁一次 ;

在这里插入图片描述
在这里插入图片描述

参考 【Java AWT 图形界面编程】Canvas 组件中使用 Graphics 绘图 ① ( AWT 绘图线程 | Component 绘图函数 ) 博客中的绘图过程分析 ,

调用 Canvas#repaint 函数 后 , 首先将组件隐藏 , 然后调用 Canvas#update 函数 ;

调用 Canvas#update 函数 后 , 首先会清除组件中的内容 , 然后调用 Canvas#paint 函数重新进行绘制 ;

在这里插入图片描述
在这里插入图片描述

Canvas#update 函数原型如下 :

代码语言:javascript
复制
    public void update(Graphics g) {
        g.clearRect(0, 0, width, height);
        paint(g);
    }

清除组件内容调用的是 Canvas#clearRect 函数 ;

调用 Canvas#repaint 函数时 , 会先将屏幕清空 , 然后再重新调用 Canvas#paint 函数进行绘制 , 此时就造成了界面闪烁的现象 ;

为了避免上述闪烁的情况 , 也就是绘制过程中 , 不出现 屏幕清空 的情况 ;

这里 引入 双缓冲 机制 , 建立一个 图片缓冲区 , 用于缓存图片 , 绘制时绘制到图片缓冲区 , 绘制完毕后再将整张图片绘制到界面中 , 这样界面中就不会出现 清空的情况 , 始终都有内容显示 , 这样就避免了图片闪烁的情况 ;

上述主要是 修改 自定义 Canvas 画布组件的 void update(Graphics g) 函数 , 按照如下进行修改 , 即可避免出现窗口闪烁的问题 ;

代码语言:javascript
复制
        /**
         * 图片缓冲区
         */
        private Image mBufferedImage = null;
        public void update(Graphics g) {
            if(mBufferedImage == null) {
                // 如果缓冲区没有创建, 则创建图片缓冲区
                mBufferedImage = this.createImage(getWidth(), getHeight());
            }
            // 获取图片的绘图对象
            Graphics buffer = mBufferedImage.getGraphics();
            // 向缓冲区中绘制图片
            paint(buffer);
            // 将缓冲区中的图片绘制到窗口界面中
            g.drawImage(mBufferedImage, 0, 0, null);
        }

二、完整代码示例


代码示例 :

代码语言:javascript
复制
import java.awt.*;

public class HelloAWT {
    public static void main(String[] args) throws InterruptedException {
        // Frame 默认的布局管理器就是 BorderLayout
        Frame frame = new Frame("AWT 界面编程");

        MyCanvas myCanvas = new MyCanvas();
        frame.add(myCanvas);

        // 自动设置 Frame 窗口合适的大小
        frame.setBounds(0, 0, 300, 300);
        frame.setVisible(true);

        while (true) {
            Thread.sleep(1000);
            myCanvas.repaint();
        }
    }

    static class MyCanvas extends Canvas {
        @Override
        public void paint(Graphics g) {
            // 绘制图形
            g.setColor(Color.BLACK);

            // 绘制线段
            g.drawLine(10, 10, 100, 10);

            // 绘制矩形
            g.drawRect(10, 15, 200, 50);

            // 绘制圆形
            g.drawOval(50, 100, 100, 100);
        }

        /**
         * 图片缓冲区
         */
        private Image mBufferedImage = null;
        public void update(Graphics g) {
            if(mBufferedImage == null) {
                // 如果缓冲区没有创建, 则创建图片缓冲区
                mBufferedImage = this.createImage(getWidth(), getHeight());
            }
            // 获取图片的绘图对象
            Graphics buffer = mBufferedImage.getGraphics();
            // 向缓冲区中绘制图片
            paint(buffer);
            // 将缓冲区中的图片绘制到窗口界面中
            g.drawImage(mBufferedImage, 0, 0, null);
        }
    }
}

执行结果 :

在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-01-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、AWT 绘图窗口闪烁问题
  • 二、完整代码示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档