Jef*_*eff 10 .net c# system.drawing winforms
我正在研究一种绘图程序,但是在绘制橡皮带线时移动鼠标光标时出现闪烁问题.我希望你能帮助我删除那条闪烁的行,这里是代码:
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 GraphicsTest
{
public partial class Form1 : Form
{
int xFirst, yFirst;
Bitmap bm = new Bitmap(1000, 1000);
Graphics bmG;
Graphics xG;
Pen pen = new Pen(Color.Black, 1);
bool draw = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bmG = Graphics.FromImage(bm);
xG = this.CreateGraphics();
bmG.Clear(Color.White);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
xFirst = e.X;
yFirst = e.Y;
draw = true;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
bmG.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
draw = false;
xG.DrawImage(bm, 0, 0);
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (draw)
{
xG.DrawImage(bm, 0, 0);
xG.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
xG.DrawImage(bm, 0, 0);
}
}
}
Run Code Online (Sandbox Code Playgroud)
Ron*_*lic 25
首先不要使用,CreateGraphics()
除非你绝对必须.将事件处理程序绑定到OnPaint
并Invalidate()
在要刷新曲面时调用.
如果你不想让它闪烁,你需要双重缓冲你的绘图表面.最简单的方法是将表单的DoubleBuffered
属性设置为True.
如果你计划扩展它来绘制PictureBox控件,我强烈建议你.PictureBox默认为双缓冲,允许您更简单地控制绘图区域.
在代码中:
public partial class Form1 : Form
{
int xFirst, yFirst;
Bitmap bm = new Bitmap(1000, 1000);
Graphics bmG;
Pen pen = new Pen(Color.Black, 1);
bool draw = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bmG = Graphics.FromImage(bm);
bmG.Clear(Color.White);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
xFirst = e.X;
yFirst = e.Y;
draw = true;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
bmG.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
draw = false;
Invalidate();
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (draw)
{
Invalidate();
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (draw) {
e.Graphics.DrawImage(bm, 0, 0);
e.Graphics.DrawLine(pen, xFirst, yFirst, e.X, e.Y);
} else {
e.Graphics.DrawImage(bm, 0, 0);
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
另一个问题是,您正在创建一个私有Pen
成员.笔(和Brushes,以及许多GDI +对象)表示需要处理的非托管对象的句柄,否则您的程序将泄漏.将它们包装在using
语句中(首选和异常安全的方式)或者在表单的Dispose
方法中明确地处理它们.
或者在System.Drawing中,您可以访问一些不需要(也不应该)处置的预构建的笔和画笔.使用它们像:
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (draw) {
e.Graphics.DrawImage(bm, 0, 0);
e.Graphics.DrawLine(Pens.Black, xFirst, yFirst, e.X, e.Y);
} else {
e.Graphics.DrawImage(bm, 0, 0);
}
}
Run Code Online (Sandbox Code Playgroud)
它闪烁的原因是你正在绘制背景(立即显示在屏幕上,擦掉线条),然后叠加线条.因此,线条不断消失和出现,呈现闪烁的显示.
对此的最佳解决方案称为双缓冲.你所做的是将整个图像绘制到"屏幕外"位图,并在完成时仅在屏幕上显示.因为您只显示完成的图像,所以没有闪烁效果.您应该能够设置this.DoubleBuffered = true以使WinForms为您完成所有艰苦的工作.
注意:你不应该真的在绘图处理程序之外绘图 - 理想情况下,你应该Invalidate()需要重绘的区域,然后你的绘图处理程序将重绘该区域(根据需要重叠任何线条等).
归档时间: |
|
查看次数: |
29439 次 |
最近记录: |