C# 如何从另一个事件/类为整个面板调用Invalidate not
我有一个绘画活动,看起来像这样:C# 如何从另一个事件/类为整个面板调用Invalidate not,c#,panel,invalidation,C#,Panel,Invalidation,我有一个绘画活动,看起来像这样: private void panel1_Paint(object sender, PaintEventArgs e) { Rectangle rec = new Rectangle(2, 2, 820, 620); Pen pi = new Pen(Color.Black, 2); e.Graphics.DrawRectangle(pi, rec); Rectangle rec2 = new Rectangle(Convert.
private void panel1_Paint(object sender, PaintEventArgs e)
{
Rectangle rec = new Rectangle(2, 2, 820, 620);
Pen pi = new Pen(Color.Black, 2);
e.Graphics.DrawRectangle(pi, rec);
Rectangle rec2 = new Rectangle(Convert.ToInt32((410 + 2500 * GlobaleVariablen.IstWerte[0])), Convert.ToInt32(310 + 1875 * GlobaleVariablen.IstWerte[1]), 2, 2);
e.Graphics.DrawRectangle(pi,rec2);
}
我有一个来自serialport的数据流,每次我收到数据时,我都想使rec2失效,但不是使整个表单失效。在我的Datareceived事件中,我可以通过以下方式使整个表单无效:
panel1.Invalidate();
但是,我不知道如何才能使它只使我的rec2无效,因为如果您一直使用数据流使整个表单无效,它会疯狂地闪烁,看起来真的不太好。invalidate()
有一个重载版本,其中包含矩形
,您想使其无效:
panel1.Invalidate(GetRect2());
其中GetRect2()
(请选择一个更好的名称)类似于:
static Rectangle GetRect2() {
int x Convert.ToInt32((410 + 2500 * GlobaleVariablen.IstWerte[0]));
int y = Convert.ToInt32(310 + 1875 * GlobaleVariablen.IstWerte[1]);
return new Rectangle(x, y, 2, 2);
}
在绘制事件处理程序中,首先必须检查无效区域是否与要写入的每个对象相交(示例很简单,因为您使用的是矩形,并且填充速度不慢)
对代码性能影响更大的是,您正在为每个绘制操作创建一个新的画笔。这是您必须绝对避免的:必须重用扩展的本地资源。最终代码可能类似于:
private Pen _pen = new Pen(Color.Black, 2);
private void panel1_Paint(object sender, PaintEventArgs e)
{
var rec = new Rectangle(2, 2, 820, 620);
if (e.ClipRectangle.IntersectsWith(rec))
e.Graphics.DrawRectangle(_pen, rec);
var rec2 = GetRect2();
if (e.ClipRectangle.IntersectsWith(rec2))
e.Graphics.DrawRectangle(pi, rec2);
}
现在,您的代码稍微优化了一些,但仍可能会闪烁。为了避免这种情况,必须为面板启用双缓冲。从面板
派生您自己的类,并添加其构造函数:
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
这也可能是一个很好的机会来重构代码,并在一个单独的类中移动一些绘制逻辑(但不是面板本身)。请参阅MSDN以了解可能需要使用的其他标志(例如allpaintingwmpaint
)
最后一点注意:您需要硬编码坐标,除非您有一个固定大小的面板(带或不带滚动),否则这不是一个好的做法,因为它不能很好地适应未来的更改,并且在许多情况下可能会被破坏(只要您的代码比虚构的示例稍微复杂一点)