简体   繁体   中英

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.

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. 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. MSDN topics like Overriding the OnPaint Method and Custom Control Painting and Rendering provide some detail on the right way to do this. 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).

Anyway…

This is the basic sequence for drawing in Forms code:

  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

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.

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. 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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