如何从另一个 event/class 调用不对整个面板无效的方法
How to call Invalidate not for the whole panel from another event/class
我有一个看起来像这样的绘画事件:
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);
}
我有一个来自串行端口的数据流,每次收到数据时我都想让 rec2 无效,但不是整个表单。我能够在我的 Datareceived 事件中使整个表单无效:
panel1.Invalidate();
但是我不知道如何才能使我的 rec2 无效,因为如果你一直使用数据流使整个表单无效,它会疯狂地闪烁,而且看起来真的不太好。
Invalidate()
有一个重载版本 Rectangle
你想使它失效:
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);
}
在您的绘画事件处理程序中,您必须首先检查无效区域是否与您要写入的每个对象相交(示例很简单,因为您使用的是矩形并且没有缓慢的扩展填充)。
实际上,您正在为每个绘制操作创建一个新的 Pen
,这会对您的代码性能造成更大的影响。这是您必须绝对避免的事情:膨胀 必须重用本机资源。最终代码可能类似于:
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);
}
现在您的代码稍微优化了,但它可能仍然会闪烁。为避免这种情况,您必须为面板启用双缓冲。从 Panel
派生出你自己的 class 并添加到它的构造函数中:
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
这也可能是重构您的代码并在单独的 class 中移动一些绘制逻辑(但不是面板本身)的好机会。请参阅 MSDN 了解您可能需要使用的其他标志(例如 AllPaintingInWmPaint
)。
最后说明:您对坐标进行了硬编码,这不是一个好的做法,除非您有一个固定大小的面板(有或没有滚动),因为它不会随着未来的变化而很好地缩放,并且在许多情况下可能会被破坏(一旦您的代码变得比虚构的示例稍微复杂一些)。
我有一个看起来像这样的绘画事件:
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);
}
我有一个来自串行端口的数据流,每次收到数据时我都想让 rec2 无效,但不是整个表单。我能够在我的 Datareceived 事件中使整个表单无效:
panel1.Invalidate();
但是我不知道如何才能使我的 rec2 无效,因为如果你一直使用数据流使整个表单无效,它会疯狂地闪烁,而且看起来真的不太好。
Invalidate()
有一个重载版本 Rectangle
你想使它失效:
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);
}
在您的绘画事件处理程序中,您必须首先检查无效区域是否与您要写入的每个对象相交(示例很简单,因为您使用的是矩形并且没有缓慢的扩展填充)。
实际上,您正在为每个绘制操作创建一个新的 Pen
,这会对您的代码性能造成更大的影响。这是您必须绝对避免的事情:膨胀 必须重用本机资源。最终代码可能类似于:
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);
}
现在您的代码稍微优化了,但它可能仍然会闪烁。为避免这种情况,您必须为面板启用双缓冲。从 Panel
派生出你自己的 class 并添加到它的构造函数中:
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
这也可能是重构您的代码并在单独的 class 中移动一些绘制逻辑(但不是面板本身)的好机会。请参阅 MSDN 了解您可能需要使用的其他标志(例如 AllPaintingInWmPaint
)。
最后说明:您对坐标进行了硬编码,这不是一个好的做法,除非您有一个固定大小的面板(有或没有滚动),因为它不会随着未来的变化而很好地缩放,并且在许多情况下可能会被破坏(一旦您的代码变得比虚构的示例稍微复杂一些)。