Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 474|回复: 0

C#中利用双缓冲技术解决绘图闪屏问题。

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-22 09:28:55 | 显示全部楼层 |阅读模式

      这段时间在做一个小型游戏,在界面显示的时候用到了一些图形。一开始涉及到的图形全都用控件的背景图片代替了。这样游戏运行的时候存在的一个很大的问题是游戏运行很慢。小组成员费尽周折,即将放弃,每一个成员都愁眉苦脸。我这心里也挺心酸的。。。

      好的废话不多说了。为了改善游戏的运行效果,把原来控件的方式全都改成绘图的方式,即用C#中DrawImage()方法进行绘图,可以改善游戏运行慢的问题。然后开始测试DrawImage()方法的使用。图片倒是出来了,而且也可以移动了,但是致命的问题出现了。就是图片在移动的时候(实质上是图片的重绘)出现了闪屏的问题。

      为了解决这个问题,在网上找了很多资料,参考了很多书,能解决闪屏问题的解决方法就是利用C#中提供的一种双缓冲技术。

      但是网上或书上没有一个能够通过一个简单的例子直接让我明白如何使用双缓冲技术的。花了好几个小时的时间,最终还是自己琢磨出来了。分享给大家。同时也把我的这个简单的测试小例子供大家学习,如何快速应用双缓冲技术解决问题。

    1.首先建立一个工程,在窗口中添加一个按钮。当点击这个按钮式就开始显示图片的移动。

    2.双缓冲我采用的方法是:

      先建立一个虚拟画布,并在Form1()的方法中加入

         SetStyle(ControlStyles.UserPaint, true);
                SetStyle(ControlStyles.AllPaintingInWmPaint,
    true); // 禁止擦除背景.
                SetStyle(ControlStyles.DoubleBuffer, true);

      

    private Graphics g;
            Bitmap bmp = new Bitmap(600, 600);//这里是创建一个画布
            Graphics g1;
            private int x=0;
            public Form1()
            {
                
                SetStyle(ControlStyles.UserPaint, true);
                SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
                SetStyle(ControlStyles.DoubleBuffer, true);
                g1 = Graphics.FromImage(bmp);//这里是在画布上建立一个Graphics对象,为了在画布上画图形
                
                
                InitializeComponent();
                
            }

     

    然后通过单击按钮事件,在画布上显示图片并将画布显示到窗口

    //button1的单击处理事件
            private void button1_Click(object sender, EventArgs e)
            {
                
                //g1.DrawEllipse(new Pen(System.Drawing.Color.Red), 10, 10, 100, 100);
                g1.DrawImage(Image.FromFile("E:/down.png"), x, 10);//这是在画布上绘制图形
               this.CreateGraphics().DrawImage(bmp, 0, 0);//这句是将图形显示到窗口上
                timer1.Enabled = true;
               // g.Dispose();
            }

    最后在通过timer控件使图片不断移动,代码如下:

    private void timer1_Tick(object sender, EventArgs e)
            {
                
                x++;//这是一个全局变量,用来改变图片的横坐标
                g1.Clear(Form1.DefaultBackColor);//这是清除画布中前一个图片
                g1.DrawImage(Image.FromFile("E:/down.png"), x, 10);//重绘新的图片,此时位置较之前的地方横坐标加1了
                this.CreateGraphics().DrawImage(bmp, 0, 0);//再次显示到窗口上,没有闪动
            }

    如没有加SetStyle(ControlStyles.UserPaint, true);
                SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
                SetStyle(ControlStyles.DoubleBuffer, true);代码,将会出现屏幕闪动。

    下面给出完整的代码:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace ttest
    {
        public partial class Form1 : Form
        {
            private Graphics g;
            Bitmap bmp = new Bitmap(600, 600);//这里是创建一个画布
            Graphics g1;
            private int x=0;
            public Form1()
            {
                
                SetStyle(ControlStyles.UserPaint, true);
                SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
                SetStyle(ControlStyles.DoubleBuffer, true);
                g1 = Graphics.FromImage(bmp);
                
                InitializeComponent();
                
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                
               // g1 = this.CreateGraphics();
                
            }
            //button1的单击处理事件
            private void button1_Click(object sender, EventArgs e)
            {
                
                //g1.DrawEllipse(new Pen(System.Drawing.Color.Red), 10, 10, 100, 100);
                g1.DrawImage(Image.FromFile("E:/down.png"), x, 10);//这是在画布上绘制图形
               this.CreateGraphics().DrawImage(bmp, 0, 0);//这句是将图形显示到窗口上
                timer1.Enabled = true;
               // g.Dispose();
            }
    
            private void timer1_Tick(object sender, EventArgs e)
            {
                
                x++;//这是一个全局变量,用来改变图片的横坐标
                g1.Clear(Form1.DefaultBackColor);//这是清除画布中前一个图片
                g1.DrawImage(Image.FromFile("E:/down.png"), x, 10);//重绘新的图片,此时位置较之前的地方横坐标加1了
                this.CreateGraphics().DrawImage(bmp, 0, 0);//再次显示到窗口上,没有闪动
            }
    
            
    
           
        }
    }

    弄了一下午,终于解决闪屏问题了。。。

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-23 07:28 , Processed in 0.060178 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表