Winform 动态 画图 不闪

摘要:
先new个Bitmap,画在Bitmap上,然后再把Bitmap画在界面上。或者根本就没注意要解决的是“动态”的问题。7//8//--------------------------------------------------------------------------------------------------------------------910namespaceHYL11{12usingSystem;13usingSystem.Drawing;14usingSystem.Windows.Forms;1516publicpartialclassPictureBoxEx:PictureBox17{18///19///画图方法20///21privateActiondraw;2223publicPictureBoxEx()24{26this.InitializeComponent();2728//开双缓存(用这种方法,画图不太复杂的话,甚至不开也不闪。。。.Invoke;44}45}46}重点在于要在“OnPaint”执行画图代码,也就是说要用“OnPaint”里的“pe.Graphics”来画。

一、问题:解决winform动态画图闪的问题,网上搜的方法,大部分都是:

  1. “this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);”,甚至直接“this.DoubleBuffered = true;”。
  2. 先 new 个Bitmap,画在Bitmap上,然后再把Bitmap画在界面上。

凡是直接这么给人解答问题的,基本都是属于道听途说,自己没试过的。或者根本就没注意要解决的是“动态”的问题。

二、解决方法:动态画图不闪的方法如下,先上效果图(请忽略鼠标样式,是gif录制软件的效果):

Winform 动态 画图 不闪第1张

三、代码:简单封了个自定义控件,用Action传入画图方法:

1 //--------------------------------------------------------------------------------------------------------------------
2 //<copyright file="PictureBoxEx.cs" company="hyl">
3 //hyl
4 //</copyright>
5 //<summary>
6 //用Action传画图方法。不闪。
7 //</summary>
8 //--------------------------------------------------------------------------------------------------------------------
9 
10 namespaceHYL
11 {
12     usingSystem;
13     usingSystem.Drawing;
14     usingSystem.Windows.Forms;
15 
16     public partial classPictureBoxEx : PictureBox
17 {
18         /// <summary>
19         ///画图方法
20         /// </summary>
21         private Action<Graphics>draw;
22 
23         publicPictureBoxEx()
24 {
26             this.InitializeComponent();
27 
28             //开双缓存(用这种方法,画图不太复杂的话,甚至不开也不闪。。。)
29             this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
30 }
31 
32         public void Rander(Action<Graphics>Draw)
33 {
34             this.Invalidate();
35             this.draw =Draw;
36 }
37 
38         protected override voidOnPaint(PaintEventArgs pe)
39 {
40             base.OnPaint(pe);
41 
42             //画图
43             this.draw?.Invoke(pe.Graphics);
44 }
45 }
46 }

重点在于要在 “OnPaint” 执行画图代码,也就是说要用 “OnPaint” 里的 “pe.Graphics” 来画。

四、调用的方式如下:

1 namespaceHYL
2 {
3     usingSystem;
4     usingSystem.Collections.Generic;
5     usingSystem.Drawing;
6     usingSystem.Linq;
7     usingSystem.Windows.Forms;
8 
9     public partial classForm1 : Form
10 {
11         List<Line> lines = new List<Line>();
12 
13         private boolpainting;
14 
15         publicForm1()
16 {
17             this.InitializeComponent();
18 }
19 
20         private void panel1_MouseDown(objectsender, MouseEventArgs e)
21 {
22             if (e.Button ==MouseButtons.Left)
23 {
24                 //左键确定点
25                 if (this.btnLine.Checked)
26 {
27                     this.lines.Last().Points.Add(new LinePoint { IsTemp = false, Point =e.Location });
28                     this.painting = true;
29 }
30 }
31 
32             if (e.Button ==MouseButtons.Right)
33 {
34                 //右键停止画图
35                 if (this.btnLine.Checked)
36 {
37                     this.ClearEmptyLines();
38 }
39 
40                 this.painting = false;
41                 this.btnLine.Checked = false;
42 }
43 }
44 
45         private voidClearEmptyLines()
46 {
47             this.lines = this.lines.Where(l => l.Points.Count > 1).ToList();
48             if (this.lines.Count > 0)
49 {
50                 var lastLine = this.lines.Last();
51 lastLine.ClearTempPoints();
52 }
53 }
54 
55         private void panel1_MouseMove(objectsender, MouseEventArgs e)
56 {
57             if (this.painting)
58 {
59                 if (this.btnLine.Checked)
60 {
61                     this.PaintingLine(e);
62 }
63 
64                 this.Draw();
65 }
66 }
67 
68         private voidPaintingLine(MouseEventArgs e)
69 {
70             var lastLine = this.lines.Last();
71             var lastPoint =lastLine.Points.Last();
72 
73             if(lastPoint.IsTemp)
74 {
75 lastLine.Points.Remove(lastPoint);
76 }
77 
78             LinePoint newPoint = new LinePoint { IsTemp = true, Point =e.Location };
79 lastLine.Points.Add(newPoint);
80 }
81 
82         /// <summary>
83         ///画图
84         /// </summary>
85         private voidDraw()
86 {
87             Action<Graphics> draw = g =>
88 {
89                     Pen pen = new Pen(Color.Black, 2);
90                     g.SmoothingMode =System.Drawing.Drawing2D.SmoothingMode.HighQuality;
91                     g.PixelOffsetMode =System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
92 
93                     if (this.lines != null)
94 {
95                         foreach (Line line in this.lines)
96 {
97 g.DrawLines(pen, line.GetPoints().ToArray());
98 }
99 }
100 };
101 
102             this.pictureBoxEx1.Rander(draw);
103 }
104 
105         private void btnLine_CheckedChanged(objectsender, EventArgs e)
106 {
107             if (this.btnLine.Checked)
108 {
109                 this.lines.Add(newLine());
110 }
111             else
112 {
113                 this.ClearEmptyLines();
114                 this.painting = false;
115                 this.Draw();
116 }
117 }
118 }
119 
120     public classLine : ShapeElement
121 {
122         publicLine()
123 {
124             this.Points = new List<LinePoint>();
125 }
126 
127         //线里的点
128         public IList<LinePoint> Points { get; set; }
129 
130         //获取Point的集合
131         public IList<Point>GetPoints()
132 {
133             return this.Points.Select(p =>p.Point).ToList();
134 }
135 
136         //清理临时点
137         public voidClearTempPoints()
138 {
139             this.Points = this.Points.Where(p => !p.IsTemp).ToList();
140 }
141 }
142 
143     public classLinePoint
144 {
145         public Point Point { get; set; }
146 
147         //是否临时点
148         public bool IsTemp { get; set; }
149 }
150 }

免责声明:文章转载自《Winform 动态 画图 不闪》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇PAT天梯:L1-019. 谁先倒WPF-生成二维码(条码)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

winform知识

控件相关 1.文本框/label高度 文本框Multiline属性,设为true就可以了。改完高度后再将此属性改回来,要不然多行文本框,按回去就去下一行了。 label的改autoSize属性,设为false就可以了。 2.控件中文字居中 TextAlign属性:MiddleCenter 3.颜色属性 直接输入 #xxxx 4.如何去掉button按钮的...

echarts 地图 动态 展示 结合css+js

echarts地图展示功能非常强大,官网上静态展示的样例非常多了,动态的资料少。研究了下。我眼下实现的通过ajax从server获取数据动态展示地图。 另外,我们有时候希望在地图之上做些自己定义的东西,比方:通知框。或者其它的东西。我们能够通过css图层的方式在地图之上实现。我实现的效果例如以下: 附上源码: <!DOCTYPE html>...

Winform设置开机启动-操作注册表

#region 设置开机运行 /// <summary> /// 设置开机运行 /// </summary> /// <param name="R_startPath">需要运行的程序.exe</param> /// <returns></returns> public static...

antd Tabs组件动态加载组件内容

Tabs的TabPane子组件不支持通过属性传入Component,官方示例的TabPane内容也都只有简单的文本。如果需要在TabPane的内容中动态传入组件,可以利用jsx特性、采用封装高阶组件的方法实现,方法如下: 1、高阶组件定义 class ToTabContent extends React.Component{     constructor...

动态规划法-01背包问题

一 几个概念: 最优化问题:有n个输入,它的解由这n个输入的一个子集组成,这个子集必须满足某些事先给定的条件,这些条件称为约束条件,满足约束条件的解称为问题的可行解。满足约束条件的可行解可能不止一个,为了衡量这些可行解的优劣,事先给出一定的标准,这些标准通常以函数的形式给出,这些标准函数称为目标函数,使目标函数取得极值的可行解成为最优解,这类问题称为最优...

C# WinForm遍历窗体控件的3种方法

C# WinForm遍历窗体控件的3种方法 转 https://www.cnblogs.com/zhaoshujie/p/14638460.html 1.循环遍历 private void GetControls(Control fatherControl) { Control.ControlCollection sonControls = fa...