C#图片闪烁
Graphics g = Graphics.FromImage(bufferimage);
g.SmoothingMode = SmoothingMode.HighQuality; //高质量
g.PixelOffsetMode = PixelOffsetMode.HighQuality; //高像素偏移质量
{
{
drawobject.Draw(g);
if (drawobject.TrackerState == config.Module.Core.TrackerState.Selected
&& this.CurrentOperator == Enum.Operator.Transfrom)//仅当编辑节点操作时显示图元热点
{
drawobject.DrawTracker(g);
}
}
}
{
tg.DrawImage(bufferimage, 0, 0); //把画布贴到画面上
}
BufferedGraphics myBuffer = currentContext.Allocate(e.Graphics, e.ClipRectangle);
Graphics g = myBuffer.Graphics;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
g.Clear(this.BackColor);
foreach (IShape drawobject in doc.drawObjectList)
{
if (rect.IntersectsWith(drawobject.Rect))
{
drawobject.Draw(g);
if (drawobject.TrackerState == config.Module.Core.TrackerState.Selected
&& this.CurrentOperator == Enum.Operator.Transfrom)//仅当编辑节点操作时显示图元热点
{
drawobject.DrawTracker(g);
}
}
}
g.Dispose();
myBuffer.Dispose();//释放资源
或者:
Bitmap bmp = new Bitmap(600, 600);
2、获取这块内存画布的Graphics引用:
Graphics g = Graphics.FromImage(bmp);
3、在这块内存画布上绘图:
g.FillEllipse(brush, i * 10, j * 10, 10, 10);
4、将内存画布画到窗口中
this.CreateGraphics().DrawImage(bmp, 0, 0);
还有的方式
在构造函数中加如下代码
代码一:
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲
代码二:
this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
this.UpdateStyles();
=============================================================================================
使用 GDI+ 双缓冲 解决绘图闪烁问题
现在的问题是很多人不知道怎么怎么使用GDI+ 双缓冲
public partial class Form1 : Form
{
//记录矩形位置的变量
Point p = Point .Empty ;
Point location = new Point(0, 0);
int x = 0;
int y = 0;
public Form1()
{
InitializeComponent();
//采用双缓冲技术的控件必需的设置
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.FillRectangle(Brushes.Black, x, y, 200, 200);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right) return;
p = e.Location;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right) return;
location.X += e.X - p.X;
location.Y += e.Y - p.Y;
p = Point.Empty;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (p == Point.Empty) return;
x = e.X - p.X + location.X;
y = e.Y - p.Y + location.Y;
this.Invalidate(true);//触发Paint事件
}
}
这个简单的例子实现了用鼠标拖动窗口中矩形,利用双缓冲技术使动画过程不会产生闪烁.
在这个例子上我犯的错误:
在 OnPaint(PaintEventArgs e)中,我使用下面两种方法获取graphics 对象
Graphics g = this.CreateGraphics();
Graphics g = Graphics.FromHwnd(this.Handle);
这都使双缓冲失效.
获得graphics 对象还有两种方法是
Graphics g = Graphics.FromImage(image); //后面将用此方法实现双缓冲
Graphics g = e.Graphics; //这是唯一好使的方法
上面是在Form窗口直接绘制图形,那么如何在控件上(比如Panel)利用双缓冲技术绘图呢?
在窗口窗创建一个Panel , 并修改一下代码
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.FillRectangle(Brushes.Black, x, y, 200, 200);
}
运行后发现拖动在panel1上绘制的图形依然有闪烁,那么是不是应该这样设置
panel1.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);//这样并不行,
因为SetStyle()在Panel类中不是public方法
使用从Panel类继承的MyPanel类 的构造函数中设置双缓冲
public class MyPanel:Panel
{
public MyPanel()
{
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
}
}
不管怎么说这个方法的确好用,不过注意以后你使用的是MyPanel类,而不是Panel.
把自己定义MyPanel从工具栏里拖到窗口上和Panle一样使用.
注意:在控件上绘制就必须设置该控件的DoubleBuffer,而不是Form的DoubleBuffer.
在此之前我采用自己的方法实现双缓冲而不是控件自身的DoubleBuffer
先在内存里绘制图形,包括清除旧画面和绘制新画面,然后将内存的图形绘制到屏幕上
public void Draw(System.Windows.Forms.Panel _panel, float _x, float _y)
{
Graphics g = Graphics.FromHwnd(_panel.Handle);
try{
//在内存创建一块和panel一大小的区域
Bitmap bitmap = new Bitmap(_panel.ClientSize.Width, _panel.ClientSize.Height);
using (Graphics buffer = Graphics.FromImage(bitmap))
{
//buffer中绘图
buffer.Clear(_panel.BackColor); //用背景色填充画面
buffer.Transform = matrix;
buffer.DrawImage(source, _x/Scale , _y/Scale ); //绘制新画面
//屏幕绘图
g.DrawImage(bitmap, 0, 0); //将buffer绘制到屏幕上
}
}
finally
{
g.Dispose();
}
}
使用上面方法不需要任何设置.
总结一下
与绘图有关的ControlStyles
enum ControlStyles{
AllPainingInWmPaint, //将绘制阶段折叠入Paint事件
DoubleBuffer, //直到Paint返回,再显示绘制对象
UserPaint, //用于自身有着特别绘制的控件
Opaque, //忽略OnPaintBackground,Paint事件绘制整个区域
ResizeRedraw,//当调整控件大小时使整个工作区无效
SupportsTransparentBackColor,//模拟透明控件
...
}
1.在OnPaint(PaintEventArgs e)或Paint中 使用e获取graphics,我之所以费了很大周折就是因为在网上找到一篇实现双缓冲文章介绍,不要使用e获取graphics,而用this.CreateGraphics(),还有的文章介绍了奇怪的方法居然最终也好使.
2.在继承了Form和control 的控件上利用双缓冲绘制的时候,可以在控件的构造函数里设置双缓冲属性,而在窗口Form 里设置doublebuffer,只针对窗口的绘制起作用.
3.使用自己的方法,双缓冲的原理都是一样的.
示例:
private void DrawRectBackImage()
{
Graphics g = Graphics.FromHwnd(_currentChart.Handle);
try
{
//在内存创建一块和panel一大小的区域
Bitmap bitmap = new Bitmap(_currentChart.ClientSize.Width, _currentChart.ClientSize.Height);
using (Graphics buffer = Graphics.FromImage(bitmap))
{
buffer.Transform =new Matrix();
//要画的背景图片
buffer.DrawImage(curChartImage, _currentChart.ClientRectangle);
//背景图片上的内容
DrawFitAdjustRect(buffer);
//屏幕绘图
g.DrawImage(bitmap, 0, 0); //将buffer绘制到屏幕上
}
}
finally
{
g.Dispose();
}
}
C#图片闪烁的更多相关文章
- WPF之路二: button添加背景图片点击后图片闪烁问题
在为button添加背景图片的时候,点击后发现图片闪烁,我们仔细观察,其实Button不仅仅只是在点击后会闪烁,在其通过点击或按Tab键获得焦点后都会闪烁,而通过点击其他按钮或通过按Tab键让Butt ...
- openLayers 4 canvas图例绘制,canvas循环添加图片,解决图片闪烁问题
一.问题来源: 接触Openlayers 一段时间了,最近做了一个农业产业系统,项目中涉及到产业图例,最后考虑用canvas来绘制图例图像.当中带图片的图例移动时,图片会实现闪烁留白情况.闪烁是因为绘 ...
- RecyclerView加载更多用notifyDataSetChanged()刷新图片闪烁
首先来看看对比ListView看一下RecyclerView的Adapter主要增加了哪些方法: notifyItemChanged(int position) 更新列表position位置上的数据可 ...
- MFC绘制图片闪烁详解
用MFC如何高效地绘图 显示图形如何避免闪烁,如何提高显示效率是问得比较多的问题. 而且多数人认为MFC的绘图函数效率很低,总是想寻求其它的解决方案. MFC的 ...
- css样式hover图片闪烁问题
主要是ie8及ie8以下版本浏览器会出现此问题, 问题核心是因为hover选择器没有缓存即将要替换的图片, 所以导致替换期间有一个极其短暂的空白期. 解决方案: 采用 background-posit ...
- Android 图片闪烁(延迟切换)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=&q ...
- android图片闪烁或帧动画
remote_recording_transition.xml 文件 <?xml version="1.0" encoding="utf-8"?> ...
- 【android】TabLayout文字闪烁问题
安卓MD设计提供了一个非常酷炫的效果,TabLayout拿来做选项卡时非常合适的,但是在实际使用中发现22.2.1版本号的TabLayout在ViewPager滑动的时候会出现闪烁现象. 解决方法:在 ...
- CSS+JS实现兼容性很好的无限级下拉菜单
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DT ...
随机推荐
- 浏览器的HTML页面展示
当你输入一个url链接发生了什么? 下面的图是上篇文章的改造版本 电脑浏览器输入百度 打开台式电脑或者笔记本中的浏览器(IE,谷歌,360等),访问百度http://www.baidu.com,此时发 ...
- python 网络爬虫(二)
一.编写第一个网络爬虫 为了抓取网站,我们需要下载含有感兴趣的网页,该过程一般被称为爬取(crawling).爬取一个网站有多种方法,而选择哪种方法更加合适,则取决于目标网站的结构. 首先探讨如何安全 ...
- python之函数名称空间,作用域,嵌套函数
目录 嵌套函数 定义 名称空间的三大类(只存变量名) 名称空间加载顺序 变量名的查找顺序为 作用域 嵌套函数 定义 函数内部定义的函数,无法在函数外部使用内部定义的函数. def f1(): def ...
- 1_02_MSSQL课程_T_SQL语句_手动创建数据库和表
1. 基本的DML SQL脚本 ->简单的查询: Select 列名 From 表明 where 条件表达式 ->插入数据: Insert Into 表名(列名1,列名2,列名3..... ...
- [Android]ListView中分割线的设置
1.在布局文件中ListView元素中通过属性设置 android:divider="#fffff" 分割线颜色 android:dividerHeight="1px& ...
- jumperserver安装
参照官网地址进行安装 https://jumpserver.readthedocs.io/zh/master/setup_by_centos.html 在安装的时候踩了一个坑 Python 模块安装中 ...
- ObjectMapper : can only instantiate non-static inner class by using default, no-argument constructor
Label_t lTrain = new ObjectMapper().readValue(s, Label_t.class); 因为Label_t是内部类,需要 1.static 2.无参构造函数
- 吴裕雄--天生自然JAVAIO操作学习笔记:内存操作流、管道流与打印流操作
import java.io.* ; class Send implements Runnable{ // 线程类 private PipedOutputStream pos = null ; // ...
- firewalld学习-zone的使用和配置
原文地址:http://www.excelib.com/article/290/show zone文件标签名词解释 target:目标,这个前面学生也已经给大家介绍过了,可以理解为默认行为,有四个可选 ...
- 我的Grunt之旅-序章
时间:2018-03-05 13:52 事件:安装Grunt 相关网址: grunt官网:https://gruntjs.com node.js下载地址 :https://nodejs.org/en ...