简体   繁体   English

C#:从PictureBox删除Paint事件

[英]C# : Remove Paint Event from PictureBox

Sorry for my bad English. 对不起,我的英语不好。

I have a picturebox where I draw 100000 shapes (but there may be more). 我有一个画框,可在其中绘制100000个形状(但可能还有更多)。 The drawing is made in the Paint Handler of the picturebox. 在图片框的“绘制处理程序”中绘制图形。

The problem is : When I Resize the form (where the picturebox is), use the scrollbar of the panel which contain it, come from another application, ... the paint handler is called... But the paint process takes quite some time and the user must wait until the paint have finished... 问题是:当我调整窗体的大小(图片框所在的位置)时,使用包含该窗体的面板的滚动条(来自另一个应用程序).​​..绘制处理程序被称为...但是绘制过程需要相当长的时间用户必须等到油漆涂完为止。

I tried the folowing : 我尝试了以下方法:

  • Create a bitmap where i draw the shapes 在我绘制形状的地方创建一个位图
  • In the paint handler, i copy the bitmap in the picturebox 在绘画处理程序中,我将位图复制到图片框中

NB : The size and the content of the picturebox can change, so the bitmap must also change. 注意:图片框的大小和内容可以更改,因此位图也必须更改。 The creation of the bitmap + restoration of the bitmap make the application slower than before : 位图的创建+位图的还原使应用程序比以前慢:

Bitmap bmp = new Bitmap(picturebox.Width, picturebox.Height);
// draw in Graphics.FromImage(bmp);
picturebox.Invalidate();
bmp.Dispose();

I also tried with a boolean flag : canRedraw. 我还尝试了一个布尔标志:canRedraw。 I set it true when the content of the picturebox change and then I call picturebox.Invalidate(). 当图片框的内容更改时,将其设置为true,然后调用picturebox.Invalidate()。 In the paint handler, I check if (canRedraw) and if so, I redraw the content (and canRedraw = false), else I make nothing. 在绘制处理程序中,我检查是否(canRedraw),如果是,则重绘内容(并且canRedraw = false),否则我什么也没做。 But with this last solution, when I make something with the form, my picturebox is cleared... 但是使用最后一种解决方案,当我使用表单制作东西时,我的图片框被清除了...

Do you have any idea of how I can make this : 您对我如何做到这一点有任何想法:

If you are a method that change the content of the picturebox then you can redraw the picturebox, else you leave the visual content of the picturebox unchanged . 如果您使用的是更改图片框内容的方法,则可以重新绘制图片框,否则您将图片框的视觉内容保持不变

Can you help me ? 你能帮助我吗 ?

Thank you very much :) 非常感谢你 :)

If you're not using any other functionality of the PictureBox , try replacing it with a UserControl of your own. 如果您没有使用PictureBox任何其他功能,请尝试用您自己的UserControl替换它。 Then take the following steps in your UserControl: 然后在您的UserControl中执行以下步骤:

  1. Set DoubleBuffered property of the control to True . DoubleBuffered属性设置为True
  2. Always check e.ClipRectangle property to get the area that needs to be redrawn. 始终检查e.ClipRectangle属性以获取需要重绘的区域。 Then loop through the collection of your shapes and for each shape, try to figure our whether it intersects with the ClipRectangle . 然后遍历您的形状集合,并为每个形状尝试确定我们是否与ClipRectangle相交。 I don't know what kind of shapes you have, but there are fairly fast implementations available for most shapes, including polygon, that can check whether two polygons intersect or not. 我不知道您使用哪种形状,但是大多数形状(包括多边形)都可以使用非常快速的实现,它可以检查两个多边形是否相交。 A good article about polygons intersection is available in this article , including c# code. 关于多边形交集一篇好文章,请在本文中 ,包括C#代码。 (Note that if your shapes are rectangles, circles or triangles, the intersection problem becomes much easier and faster to compute) (请注意,如果您的形状是矩形,圆形或三角形,则相交问题的计算变得更加容易和快捷)
  3. Paint a shape only if it intersects with ClipRectangle . 仅当形状与ClipRectangle相交时才绘制形状。

Besides streamlining the Paint as dotNet suggest the other way to do it is pretty much what you tried, but you need to do it right: 除了将Paint简化为dotNet建议以外,另一种方法是尝试做的,但是您需要正确地做:

Yes, do draw into a Bitmap but not in the Paint event, which will be called unnecessarily and then still take too much time! 是的, 确实要绘制一个Bitmap不要在“ Paint事件中Paint ,这将被不必要地调用,但是仍然花费太多时间! Instead draw only when you know that your data have changed and need to be redrawn! 相反, 当您知道数据已更改并且需要重绘时才绘制!

You didn't tell us just what you draw but the drawing should be done like this: 您并没有告诉我们您所绘制的内容,但是绘制应该像这样进行:

void drawStuff()
{
    Bitmap bmp = new Bitmap(pictureBox.ClientSize.Width, pictureBox.ClientSize.Height);
    using (Graphics G = Graphics.FromImage(bmp) )
    {
        // do all your drawing stuff here!!

    }
    pictureBox.Image = bmp;
}

Call this function whenever you want the data to be drawn again! 每当您想再次绘制数据时都调用此函数!

Now you can leave the Paint event empty, as the Image if buffered by the System and you can still use the PictureBox.Zoom or Image.Save .. 现在,您可以将Paint事件保留为空,因为Image如果已由系统缓冲,则仍然可以使用PictureBox.ZoomImage.Save .。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM