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 ...
随机推荐
- C#中集合接口关系笔记
IEnumerable IEnumerable接口是所有集合类型的祖宗接口,其作用相当于Object类型之于其它类型.如果某个类型实现了IEnumerable接口,就意味着它可以被迭代访问,也就可以称 ...
- Spring和SpringMVC的直接
1.Spring的常用注解 2.SpringMVC的常用注解
- java并发初探ConcurrentHashMap
java并发初探ConcurrentHashMap Doug Lea在java并发上创造了不可磨灭的功劳,ConcurrentHashMap体现这位大师的非凡能力. 1.8中ConcurrentHas ...
- easyui学习索引页
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>复 ...
- JavaSwing标准对话框
package test001; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import jav ...
- Day3-B-Round Marriage CodeForces-981F
It's marriage season in Ringland! Ringland has a form of a circle's boundary of length LL. There are ...
- 隐患写法flag.equals("true")带来的空指针异常
分类:2008-06-04 12:47 467人阅读 评论(0) 收藏 举报 linuxjava测试 昨天,有同事A对同事B写的程序进行测试时,出现错误,看控制台信息,发现抛出了空指针异常. 调查结果 ...
- 二 配置数据字典&异步查询客户
数据字典: 字典表和客户表的关系 配置字典表 配置客户表 Spring管理映射文件 1 字典表和客户表的关系 2 配置字典表 3 配置客户表 4 Spring管理映射文件 异步查询客户: 页面加载 ...
- python-python基础5(模块)
一.模块介绍 定义:本质上就是.py结尾的python文件.模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用 ...
- MyISAM与InnoDB 的区别
1. 事务:InnoDB支持,MyISAM不支持,在InnoDB中每一条SQL语句都会默认封装成事务自动提交,然而这样会影响速度,因此最好把多条SQL语句放在begin和commit之间组成一个事务: ...