简体   繁体   中英

Drawing a single line in different Color

I am trying to draw a line which can be broken into different segments (in C# winforms).

Each segment will then be of a different colour and also display a name on it.

What I've done right now is:

 int startXPosition = 100;
 int startYPosition = 50;
 int numSegment = 5;
 int endXPosition = startXPosition;
 int endYPosition = this.Height / numSegment;

 Pen blackPen = new Pen(Color.Black, 5);
 e.Graphics.DrawLine(blackPen, new       Point(startXPosition, startYPosition), new      Point(endXPosition, endYPosition));

This will allow me to draw a line base on the form's height / 5 (the number of segment) using black color.

How do I continue from here such that I am able to draw the rest of the segment (4) in which it will be in different colour?

How can i do it in such a way that I won't need to define the colour and the code can auto assign a color to each different segment?

Well this can be easily solved by linear algebra ( http://en.wikipedia.org/wiki/Linear_algebra )

You need to represent your start and end in vector form in terms of

start + (end - start) * n, where n is [0..1]

As you are not using vectors here you will need to split x and y separately

Your start position is start , which is equal to n=0, your final position (of the fifth segment) is end , which is equivalent of n = 1. Every position in between is a fraction of n .

Now you need to draw 5 lines, where we will use the formula above

  1. Draw from n = 0 to n = 1/5
  2. Draw from n = 1/5 to n = 2/5
  3. Draw from n = 2/5 to n = 3/5
  4. ..
  5. Draw from n = 4/5 to n = 5/5 (=1)

Each with a different color

If segments are connected, then you can represent the whole figure as an array of points. First point is connected to second, second to third, etc.

If you need to have Color 's, then you can either have it as a separate array, or as a part of segment type (which makes more sense to make, the more parameters you need).

According to your requirements, it is enough in your case to define array of Color 's and the line somehow (possible by using y=kx+b expression or by starting/ending point). Then, when drawing, you can split the line in segments (by using geometry formulas) and draw each with its own color.

To example,

Color[] colors = new Color[] {Color.Red, Color.Black, Color.Green, Color.Blue, Color.Purple};
var k = 1;
var b = 0; // y = x, diagonal line

for(int i = 0; i < colors.Lengh; i++)
{
    // calculate line coords
    var y1 = this.Height / colors.Length * i;
    var x1 = (y1 - b) / k;  // x = (y - b) / k
    var y2 = this.Height / colors.Length * (i + 1);
    var x2 = (y2 - b) / k;

    using(var pen = new Pen(colors[i]))
        e.Graphics.DrawLine(pen, (int)x1, (int)y1, (int)x2, (int)y2);
}

Note, this is not accurate, because you have to use ClientRectangle reduced by 1 point (and not form Height ). Otherwise you will draw on non-client area (which is not a problem, but you will not see there anything drawn).

It's a trivial task to get k and b for a given starting/ending point of the line, not going to post it here.

This should do for you, I comments the code best I could, feel free to ask questions about what I did.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;

    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            Bitmap buffer;  //used to draw the lines and txt on first then make the Forms     Background image = buffer
            public Form1()
            {
                InitializeComponent();
                //set the buffer to the same size as the form
                buffer = new Bitmap(Width, Height);

                //calls the method below
                DrawLines(100,50,5,Graphics.FromImage(buffer));

                //sets the background image to = buffer
            BackgroundImage = buffer; 

        }

        public void DrawLines(int startX, int startY, int segments, Graphics g)
        {
            // this needs to be looked at since it pushes the lines off the screen
            //perhaps you need to indicate a total line length then use it here instead of this.Height

            //int TotalLength=500;
            //int segmentLength = TotalLength / segments; 

            int segmentLength=this.Height/segments; 

            //I have created a array containing 5 Colors, this way I can reference them from within the For Loop below
            //You can use whichever colors you wish

            Color[] Colors = new Color[] { Color.Black, Color.Red,Color.Orange,Color.Yellow,Color.Green };

            //Loop through each of the segments

            for (int y = 0; y < segments; y++)
            {
                //the using statements ensures your new p is disposed of properly when you are finished.  You could also use
                // Pens.Red, or Pens.Black, which do not need to be disposed of instead of creating a new one
                using (Pen p= new Pen(Colors[y]))
                    g.DrawLine(p,new Point(startX,startY+(y*segmentLength)),new Point(startX,startY+((y+1)*segmentLength)));
                //same thing for Pens also applies to Brush...  Brushes.Red, Brushes.Black etc...
                using (Brush b = new SolidBrush(Colors[y]))
                    g.DrawString(Colors[y].Name, Font, b, new Point(startX + 5, startY + (y * segmentLength) + (segmentLength / 2)));
            }
        }
    }
}

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