如何等待onPaint完成绘制(C#)
本文关键字:绘制 onPaint 等待 何等待 | 更新日期: 2023-09-27 17:58:19
Hi基于这里的线程:如何使用.NET在内存中动态创建jpg图像?
我有这样的方法:
int maxVal = 50;
int maxXCells = r.Next(maxVal);
int maxYCells = r.Next(maxVal);
int cellXPosition = r.Next(maxVal);
int cellYPosition = r.Next(maxVal);
int boxSize = 10;
Graphics fg = this.CreateGraphics();
using (var bmp = new System.Drawing.Bitmap(maxXCells * boxSize + 1, maxYCells * boxSize + 1))
{
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.Yellow);
Pen pen = new Pen(Color.Black);
pen.Width = 1;
//Draw red rectangle to go behind cross
Rectangle rect = new Rectangle(boxSize * (cellXPosition - 1), boxSize * (cellYPosition - 1), boxSize, boxSize);
g.FillRectangle(new SolidBrush(Color.Red), rect);
//Draw cross
g.DrawLine(pen, boxSize * (cellXPosition - 1), boxSize * (cellYPosition - 1), boxSize * cellXPosition, boxSize * cellYPosition);
g.DrawLine(pen, boxSize * (cellXPosition - 1), boxSize * cellYPosition, boxSize * cellXPosition, boxSize * (cellYPosition - 1));
//Draw horizontal lines
for (int i = 0; i <= maxXCells; i++)
{
g.DrawLine(pen, (i * boxSize), 0, i * boxSize, boxSize * maxYCells);
}
//Draw vertical lines
for (int i = 0; i <= maxYCells; i++)
{
g.DrawLine(pen, 0, (i * boxSize), boxSize * maxXCells, i * boxSize);
}
}
fg.DrawImage(bmp, 0, 0);
fg.Dispose();
}
它根据随机事件触发(可能在一秒钟内多次)。我应该怎么做,只在当前绘图完成后绘制新图像?目前,我可以看到,如果运行此方法的事件的启动速度比绘图完成的速度快,屏幕就会闪烁。在上一次绘图完成之前避免绘图的常见解决方案是什么?
这就是我在OnPaint方法中包含的内容:
protected override void OnPaint(System.Windows.Forms.PaintEventArgs pe)
{
finishedInvalidating = false;
fg = this.CreateGraphics();
lock (bmp)
{
fg.DrawImage(bmp, 0, 0);
}
fg.Dispose();
finishedInvalidating = true;
但这并不能解决的问题
----------------------更新------------------
public partial class LadderFrm : Form
{
Bitmap bmp;
int numCols = 3;
int colWidth = 100;
int numRows = 30;
int rowHeight = 20;
bool finishedInvalidating = false;
decimal lastprice;
public LadderFrm()
{
bmp = new System.Drawing.Bitmap(numCols * colWidth + 1, numRows * rowHeight + 1);
prepareLadderGraphics();
}
// prepare initial ladder background
private void prepareLadderGraphics()
{
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.LightGray);
Pen pen = new Pen(Color.Black);
pen.Width = 1;
// drawCells
for (int i = 0; i < numCols; i++)
{
for (int j = 0; j < numRows; j++)
{
Rectangle rect = new Rectangle(i * colWidth, j * rowHeight, colWidth, rowHeight);
g.DrawRectangle(pen, rect);
}
}
g.Dispose();
}
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs pe)
{
Graphics fg = this.CreateGraphics();
lock (fg)
{
lock (bmp)
{
fg.DrawImage(bmp, 0, 0);
}
}
fg.Dispose();
}
public void OrderBookUpdateFn(OrderBookEvent orderBookEvent)
{
if (lastprice != orderBookEvent.ValuationAskPrice)
{
lastprice = orderBookEvent.ValuationAskPrice;
lock (bmp)
{
using (Graphics g = Graphics.FromImage(bmp))
{
Pen pen = new Pen(Color.Black);
pen.Width = 1;
for (int i = 0; i < numRows; i++)
{
Rectangle rect = new Rectangle(colWidth + 1, i*rowHeight + 1, colWidth - 1, rowHeight - 1);
g.FillRectangle(new SolidBrush(Color.LightGray), rect);
g.DrawString(lastPrice.ToString(), new Font(FontFamily.GenericSansSerif, 10), new SolidBrush(Color.Black), new Point(colWidth + 1, i*rowHeight + 1));
}
g.Dispose();
}
this.Invalidate(new Rectangle(0, 0, 1, 1));
}
}
}
上面的代码工作得很好,但我不确定它是否正确。这只是为了测试目的。方法OrderBookUpdateFn(OrderBookEvent OrderBookEvent)经常被激发(有时每秒数十次)。
事件处理程序都在应用程序的主线程中运行,因此不可能在处理前一个事件的方法完成之前启动处理事件的方法。
如果您遇到闪烁,这不是因为重叠的事件处理程序。
为了避免自绘制控件的闪烁,您可以对窗体/控件的绘图进行DoubleBuffer。将其添加到构造函数:
this.SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.DoubleBuffer,true);
的一些防闪烁技术
您可以尝试重写OnPaint方法,调用base。OnPaint();然后再手工绘画。
protected override void OnPaint(PaintEventArgs e)
{
// call base
base.OnPaint(e);
// Do your stuff after the rest has been painted
if(this.picture != null && this.pictureLocation != Point.Empty)
{
e.Graphics.DrawImage(this.picture, this.pictureLocation);
}
}