绘制圆后如何将其视为控件?- 移动和选择形状 [英] How can I treat the circle as a control after drawing it? - Moving and selecting shapes

查看:19
本文介绍了绘制圆后如何将其视为控件?- 移动和选择形状的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

实际上,点击每个圆圈后我想改变它的颜色,例如,我想让它变成红色,总的来说,我想把它当作控件.

Actually, after clicking on each circle i want its color to be changed, for instance, i want it to turn into red,Overall, i wanna treat it as control.

当我双击图片框时,我知道如何绘制代表图形节点的圆圈.我正在使用以下代码:

i know how to draw the circles that represent the nodes of the graph when i Double click on the picturebox. i'm using the following code:

        public Form1()
    {
        InitializeComponent();

        pictureBox1.Paint += new PaintEventHandler(pic_Paint);
    }

    public Point positionCursor { get; set; }
    private List<Point> points = new List<Point>();
    public int circleNumber { get; set; }

    private void pictureBox1_DoubleClick(object sender, EventArgs e)
    {
        positionCursor = this.PointToClient(new Point(Cursor.Position.X - 25, Cursor.Position.Y - 25));

        points.Add(positionCursor);
        Label lbl = new Label();
        lbl.BackColor = Color.Transparent;
        lbl.Font = new Font("Arial", 7);

        lbl.Size = new Size(20, 15);

        if (circleNumber >= 10)
        {
            lbl.Location = new Point(points[circleNumber].X + 3, points[circleNumber].Y + 6);
        }
        else
        {
            lbl.Location = new Point(points[circleNumber].X + 7, points[circleNumber].Y + 7);
        }
        lbl.Text = circleNumber.ToString();
        pictureBox1.Controls.Add(lbl);
        circleNumber++;
        pictureBox1.Invalidate();
    }

    private void pic_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        g.SmoothingMode = SmoothingMode.AntiAlias;

        using (var pen = new Pen(Color.DimGray, 2))
        {
            foreach (Point pt in points)
            {
                g.FillEllipse(Brushes.White, pt.X, pt.Y, 25, 25);
                g.DrawEllipse(pen, pt.X, pt.Y, 26, 26);
            }
        }
    }

推荐答案

您需要执行命中测试以检查点是否在圆中.作为一个选项,您可以向 GraphicsPath 和使用 IsVisible 方法检查点是否在圆中的路径.

You need to perform a hit-test to check if a point is in a circle. As an option you can add a circle to a GraphicsPath and the use IsVisible method of the path to check if the point is in circle.

例如将 ponit p 作为直径为 d 的圆的左上角位置,您可以检查当前点击的点是否在圆中或以这种方式进行控制:

For example having a ponit p as top-left location of a circle with diameter d, you can check if current clicked point is in the circle or con this way:

var result = false;
using (var path = new GraphicsPath())
{
    path.AddEllipse(p.X, p.Y, d, d);
    result = path.IsVisible(e.Location);
}

<小时>

示例代码

我看到您在此主题中提出了多个问题.所以在这里我分享一些代码来帮助你朝着正确的方向前进.

I see you have asked multiple questions in this topic. So here I share some code to help you to be in right direction.

为填充颜色、选定的填充颜色、圆形大小、边框宽度等定义变量,以便您可以根据需要轻松更改它们.

define variables for fill color, selected fill color, circle size, border width and etc, to be able to change them simply if you need.

List<Rectangle> Shapes = new List<Rectangle>();
int selectedIndex = -1;
Size size = new Size(25, 25);
Color fillColor = Color.White;
Color selectedfillCOlor = Color.Red;
Color borderColor = Color.Gray;
int borderWidth = 2;

双击

此处将圆添加到 Shapes 列表中.将圆形的边界矩形添加到列表中就足够了.

Here add circles to the Shapes list. It's enough to add the bounding rectangle of a circle to the list.

private void pic_MouseDoubleClick(object sender, MouseEventArgs e)
{
    var p = e.Location;
    p.Offset(-size.Width / 2, -size.Height / 2);
    Shapes.Add(new Rectangle(p, size));
    pic.Invalidate();
}

点击

这里执行hit-test来检查点是否在一个圆圈内.检查点击时Ctrl键是否按下,进行选择,然后将找到的索引设置为selectedIndex 绘画时使用.

Here perform hit-test to check if the point is in one of circles.Check if the Ctrl key is down when click, to make selection, then set the found index as selectedIndex to use it when painting.

private void pic_MouseClick(object sender, MouseEventArgs e)
{
    if (ModifierKeys != Keys.Control)
        return;
    selectedIndex = -1;
    for (int i = 0; i < Shapes.Count; i++)
    {
        using (var path = new GraphicsPath())
        {
            path.AddEllipse(Shapes[i]);
            if (path.IsVisible(e.Location))
                selectedIndex = i;
        }
    }
    pic.Invalidate();
}

油漆

将图形对象的SmoothingMode 设置为AntiAlias 以获得更流畅的绘制.然后在 for 循环中绘制形状并注意 selectedIndex 为所选形状使用不同的填充颜色.

Set SmoothingMode of graphics object to AntiAlias to have a more smooth drawing. Then draw shapes in a for loop and pay attention to selectedIndex to use a different fill color for selected shape.

要绘制文本,您不需要使用 label,您只需使用 TextRenderer 类即可绘制文本.

To draw the text, yo don't need to use a label and you can simply draw text using TextRenderer class.

private void pic_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    for (int i = 0; i < Shapes.Count; i++)
    {
        var selected = (selectedIndex == i);
        using (var brush = new SolidBrush(selected ? selectedfillCOlor : fillColor))
            e.Graphics.FillEllipse(brush, Shapes[i]);
        using (var pen = new Pen(borderColor, borderWidth))
            e.Graphics.DrawEllipse(pen, Shapes[i]);
        TextRenderer.DrawText(e.Graphics, (i + 1).ToString(),
                this.Font, Shapes[i], Color.Black,
                TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter);
    }
}

一些注意事项

  • 最好将代码封装在派生自 PictureBox 或派生 Control 的新控件中,并将 DoubleBuffered 设置为 true.

  • It's better to encapsulate codes in a new control derived from PictureBox or derived Controland set DoubleBuffered to true.

Circle 封装在一个 Circle 类中是一个不错的选择,该类执行圆的命中测试和渲染.特别是如果你想稍后移动它们或执行一些其他交互或让每个圆圈都有自己的属性,如颜色等.

It's a good option to encapsulate Circle in a Circle class which performs hit testing and rendering of a circle. Specially if you want to move them later or perform some other interactions or let each circle has it's own properties like color ,etc.

示例圆类

这是一个示例圆类,它可以是一个很好的起点.

Here is a sample circle class which can be a good start point.

public class Circle
{
    private Color selectedFillColor = Color.Red;
    private Color normalFillColor = Color.Red;
    private Color borderColor = Color.Red;
    private int borderWidth = 2;
    public Point Location { get; set; }
    public int Diameter { get; set; }
    public Rectangle Bounds
    {
        get
        {
            return new Rectangle(Location, new Size(Diameter, Diameter));
        }
    }
    public bool HitTest(Point p)
    {
        var result = false;
        using (var path = new GraphicsPath())
        {
            path.AddEllipse(Bounds);
            result = path.IsVisible(p);
        }
        return result;
    }
    public bool Selected { get; set; }
    public void Draw(Graphics g)
    {
        using (var brush = new SolidBrush(
            Selected ? selectedFillColor : normalFillColor))
            g.FillEllipse(brush, Bounds);
        using (var pen = new Pen(borderColor, 2))
            g.DrawEllipse(pen, Bounds);
    }
}

这篇关于绘制圆后如何将其视为控件?- 移动和选择形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆