您好基于此处的主题:How to create a jpg image dynamically in memory with .NET?
我有这个方法:
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;
但这并没有解决问题
---------------------- update ------------------
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)经常被触发(有时几十次)。
答案 0 :(得分:3)
事件处理程序都在应用程序的主线程中运行,因此在处理上一个事件的方法完成之前,不可能启动处理事件的方法。
如果遇到闪烁,则不是因为事件处理程序重叠。
答案 1 :(得分:1)
您可以尝试重写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);
}
}
答案 2 :(得分:1)
为了避免自绘控件的闪烁,你可以DoubleBuffer表单/控件的绘图。 将其添加到构造函数:
this.SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.DoubleBuffer,true);