简体   繁体   English

如何在绘制的面板上绘制其他内容?

[英]How to paint additional things on a drawn panel?

I'm reading a lot about C# drawing and reading MSDN tutorial on GDI+ using Graphics handlers. 我正在阅读许多有关C#绘图的内容,并使用图形处理程序阅读了有关GDI +的MSDN教程。

I want to be able to paint a graph, which nodes I have in a list but I can't use auto-placing, I need the nodes to be in a specified place and have specific appearance and so on, changing over time, that's why I stopped looking for graph libraries. 我希望能够绘制一个图表,列表中有哪些节点,但是我不能使用自动放置,我需要将这些节点放在指定的位置并具有特定的外观,依此类推,随着时间的推移而变化为什么我停止寻找图形库。

It all works great when painted for the first time but when I want something painted after something else happens in the code (not after clicking the control), I can't do it. 初次绘制时,一切都很好,但是当我想要在代码中发生其他事情之后(而不是单击控件后)进行绘制时,我无法做到。 For example: 例如:

if (somethingHappens) {
  // repaint the panel adding some things
}

All I got is either nothing new happens or my earlier painting disappears. 我所得到的不是新的事情发生,就是我先前的绘画消失了。

I found some examples on OnPaint overriding and drawings disappearing when minimalized. 我发现一些有关OnPaint覆盖的示例,并且在最小化时图形消失了。 When I need to paint something additional when something happens in an application, do I have to override it or is it completely different? 当我在应用程序中发生某些事情时需要额外绘画时,我是否必须重写它或它完全不同?

I looked for another Q&A that would include the information you need. 我正在寻找另一个包含您所需信息的问答。 Frankly, it's a fundamental question, how to properly deal with drawing a Forms control. 坦白地说,这是一个基本问题,如何正确处理绘制Forms控件。 MSDN topics like Overriding the OnPaint Method and Custom Control Painting and Rendering provide some detail on the right way to do this. MSDN主题(如覆盖OnPaint方法自定义控件绘画和渲染)提供了一些有关执行此操作的正确方法的详细信息。 But I'm surprised I wasn't able to find any StackOverflow Q&A that at least addresses this basic question directly (there are many which address it tangentially of course). 但是令我惊讶的是,我没有找到任何至少可以直接解决这个基本问题的StackOverflow问答(当然,有很多解决方法都是切线的)。

Anyway… 无论如何…

This is the basic sequence for drawing in Forms code: 这是在Forms代码中绘制的基本顺序:

  1. Generate some data to be drawn 生成一些要绘制的数据
  2. Invalidate the control where the data will be drawn 使将在其中绘制数据的控件无效
  3. Handle the Paint event by actually drawing that data 通过实际绘制数据来处理Paint事件

Repeat the above as necessary, ie any time the data changes (such as "something happens", as in your question) you move back to step #1, adding whatever new data you want to your existing collection of data, then invalidating the control, and finally responding to the Paint event in your event handler. 根据需要重复上述操作,即,只要数据发生更改(例如出现问题,例如出现问题),您就返回到步骤1,将所需的新数据添加到现有数据集中,然后使控件无效,最后在事件处理程序中响应Paint事件。

In the case of drawing a graph, this might look something like this: 在绘制图形时,可能看起来像这样:

private List<Point> _points = new List<Point>();

void AddPoint(Point point)
{
    _points.Add(point);
    panel1.Invalidate();
}

void panel1_Paint(object sender, PaintEventArgs e)
{
    if (_points.Count < 2)
    {
        return;
    }

    Point previousPoint = _points[0];

    for (int i = 1; i < _points.Count; i++)
    {
        currentPoint = _points[i];

        e.Graphics.DrawLine(Pens.Black, previousPoint, currentPoint);
        previousPoint = currentPoint;
    }
}

Note that the panel1_Paint() event is an event handler. 请注意, panel1_Paint()事件是一个事件处理程序。 Normally you would create this via the Designer by selecting the Panel object, switching to the "Events" list in the "Properties" window for the control, and double-clicking in the edit field for the Paint event. 通常,您可以通过选择Panel对象,通过选择“ Panel对象,在控件的“属性”窗口中切换到“事件”列表,然后双击Paint事件的编辑字段,来创建此控件。

That is of course the simplest example. 那当然是最简单的例子。 You can add things like updating the data in a batched manner (ie don't invalidate the control until you've added a group of points), use different colors or line styles to draw, draw other elements of the graph like axes, ticks, legend, etc. The above is simply meant to illustrate the basic technique. 您可以添加诸如以批处理方式更新数据之类的东西(即在添加一组点之前不要使控件无效),使用不同的颜色或线条样式进行绘制,绘制图形的其他元素(例如轴,刻度) ,图例等。以上只是为了说明基本技术。

One final note: depending on how many points in your graph you need to draw, the above may or may not be fast enough. 最后一点:根据需要在图形中绘制多少个点,上述步骤可能足够快,也可能不够快。 It should be fine up to thousands of points or so, but if you start getting to tens or hundreds of thousands or more, you'll probably find that it's useful to cache the drawing into a bitmap and draw just the bitmap. 最多可以达到数千个点,但是如果您开始达到成千上万个,甚至更多,您可能会发现将图形缓存到位图中并仅绘制位图很有用。 But that's a whole separate question. 但这是一个完全独立的问题。 First, you need to make sure you understand the Forms drawing model and are using it correctly. 首先,您需要确保您了解Forms绘图模型并正确使用它。

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

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