【问题标题】:select two point to Draw a circle选择两点画一个圆
【发布时间】:2016-06-06 05:24:21
【问题描述】:

我正在使用 Visual Studio C# Windows 窗体,我需要帮助来使用鼠标单击绘制一个圆。第一次单击将使我的圆心等于光标位置,第二次单击将给我一个点圆的边界等于光标的第二个位置,到点之间的距离会给我半径..现在我有半径和点..我可以画一个圆..代码不起作用,因为我鼠标点击多少次只能得到一个光标位置

private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        int lastX = Cursor.Position.X;//the first click x cursor position
        int lastY = Cursor.Position.Y;//the first click y cursor  position,         

   //is there any way to reuse the Cursor.Position for different point ??
   int x = Cursor.Position.X;//the second click x cursor position
        int y = Cursor.Position.Y;//the second click y cursor  position
        Graphics g;
       double oradius=Math.Sqrt(((lastX-x)^2) +((lastY-y)^2));
        //double newy = Math.Sqrt(lastY);
       // int newxv = Convert.ToInt32(newx);
        int radius= Convert.ToInt32(oradius);
        g = this.CreateGraphics();

        Rectangle rectangle = new Rectangle();
        PaintEventArgs arg = new PaintEventArgs(g, rectangle);

        DrawCircle(arg, x, y,radius,radius);
    }


    private void DrawCircle(PaintEventArgs e, int x, int y, int width, int height)
    {
        System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Red, 3);
        e.Graphics.DrawEllipse(pen, x - width / 2, y - height / 2, width, height);
    }
}

【问题讨论】:

    标签: c#


    【解决方案1】:

    在开始计算之前,您还需要存储第一次点击。做到这一点的一种方法是创建一个类,它在你传递 x 和 y 坐标时每秒钟简单地抛出一个事件,如下所示:

    public class CircleDrawer
    {
        private int _firstX;
        private int _firstY;
        private int _secondX;
        private int _secondY;
    
        private bool _isSecondClick;
    
        private event EventHandler OnSecondClick;
    
        public void RegisterClick(int x, int y)
        {
               if(_isSecondClick)
               {
                   _secondX = x;
                   _secondY = y;
                   if(OnSecondClick != null) 
                      OnSecondClick(this, null);
               }
               else
               {
                   _firstX = x;
                   _firstY = y;
                   _isSecondClick = true;
               }    
        }
       }
    

    然后您可以在您的代码中简单地调用您的方法:

    private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            int lastX = Cursor.Position.X;//the first click x cursor position
            int lastY = Cursor.Position.Y;//the first click y cursor  position, 
    
            _circleDrawer.RegisterClick(lastX, lastY);
        }
    

    在你的构造函数中:

    public MyForm()
    {
       _circleDrawer = new CircleDrawer();
       _circleDrawer.OnSecondClick += DrawCircle();
    }
    
    public void DrawCircle()
    {
       // Your drawing code
    }
    

    【讨论】:

      【解决方案2】:

      您的 lastXlastY 是局部变量,您在 MouseDown 事件处理程序的开头初始化它们。它们应该是类级别的变量,并且应该在 MouseDown 事件处理程序的末尾填充。
      此外,您应该测试它们是否已经有值,并且只有当它们具有值时才绘制圆圈然后清除它们(以便下一个圆圈有自己的中心)。

      这是对您的代码的改进。请注意,我已将 using 关键字与图形对象和笔一起使用 - 每次使用任何实现 IDisposable 接口的实例时都习惯使用它。

      private void Form1_MouseDown(object sender, MouseEventArgs e)
      {
          if (_lastPosition != Point.Empty)
          {
              var currentPosition = Cursor.Position;
              var oradius = Math.Sqrt(((_lastPosition.X - currentPosition.X) ^ 2) + ((_lastPosition.Y - currentPosition.Y) ^ 2));
              var radius = Convert.ToInt32(oradius);
              using (var g = this.CreateGraphics())
              {
                  var arg = new PaintEventArgs(g, new Rectangle());
                  DrawCircle(arg, currentPosition, radius, radius);
              }
              _lastPosition = Point.Empty;
          }
          else
          {
              _lastPosition = Cursor.Position;
          }
      
      }
      
      
      private void DrawCircle(PaintEventArgs e, Point position, int width, int height)
      {
          using (var pen = new System.Drawing.Pen(System.Drawing.Color.Red, 3))
          {
              e.Graphics.DrawEllipse(pen, position.X - width / 2, position.Y - height / 2, width, height);
          }
      }
      

      注意:此代码可以进一步改进。

      【讨论】:

        【解决方案3】:

        这段代码有很多根本错误,这里有一个完整的工作示例。

            public partial class Form1 : Form
            {
                public Form1()
                {
                    InitializeComponent();
                }
        
                private Point clickCurrent = Point.Empty;
                private Point clickPrev = Point.Empty;
        
                private void Form1_MouseDown(object sender, MouseEventArgs e)
                {
                    clickPrev = clickCurrent;
                    clickCurrent = this.PointToClient(Cursor.Position);
                    if (clickPrev == Point.Empty) return;    
                    Graphics g;
                    double oradius = Math.Sqrt((Math.Pow(clickPrev.X - clickCurrent.X, 2)) + (Math.Pow(clickPrev.Y - clickCurrent.Y, 2)));
                    int radius = Convert.ToInt32(oradius);
                    g = this.CreateGraphics();
                    Rectangle rectangle = new Rectangle();
                    PaintEventArgs arg = new PaintEventArgs(g, rectangle);
                    DrawCircle(arg, clickPrev.X, clickPrev.Y, radius * 2, radius * 2);
                    clickCurrent = Point.Empty;
                }
        
        
                private void DrawCircle(PaintEventArgs e, int x, int y, int width, int height)
                {
                    System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Red, 3);
                    e.Graphics.DrawEllipse(pen, x - width / 2, y - height / 2, width, height);
                }
            }
        

        【讨论】:

        • 谢谢大家,这是完美的答案
        • 有一个问题,当我重新调整窗口大小时,圆圈消失了!
        • 这样做是因为在调整大小时会重新绘制表单。为了正确处理这些内容,您需要了解 Windows 窗体上的图形、Paint 事件等如何工作并应用这种理解。在线查看一些教程/资源,例如:c-sharpcorner.com/uploadfile/TheButler/…
        • @user6425922 将此代码放入该表单的 formLoad 事件中 this.paint = (snd1 ,evt1) = { drawCirle(x,y , width , height ); };
        【解决方案4】:
                private int _firstX;
                private int _firstY;
                private int _secondX;
                private int _secondY;
        
                private bool _isSecondClick;
        
        
            private void Form1_MouseDown(object sender, MouseEventArgs e)
            {
                if (_isSecondClick)
                {
                    _secondX = Cursor.Position.X;
                    _secondY = Cursor.Position.Y;
                    var radious1 = Math.Pow(_firstX - _secondX, 2);
                    var radious2 = Math.Pow(_firstY - _secondY, 2);
        
                    var radious = Math.Sqrt(radious1 + radious2);
                    Graphics g = this.CreateGraphics();
        
                    Rectangle rectangle = new Rectangle();
                    PaintEventArgs arg = new PaintEventArgs(g, rectangle);
                    DrawCircle(arg, _secondX, _secondY, radious, radious);
                }
                else
                {
                    _firstX = Cursor.Position.X;
                    _firstY = Cursor.Position.Y;
                    _isSecondClick = true;
                }    
            }
        
            private void DrawCircle(PaintEventArgs arg, int x, int y, double width, double height)
            {
                System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Red, 3);
                var xL = Convert.ToInt32(x - width / 2);
                var yL = Convert.ToInt32(y - height / 2);
                var hL = Convert.ToInt32(height);
                var wL = Convert.ToInt32(width);
                arg.Graphics.DrawEllipse(pen, xL, yL, wL, hL);
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-24
          • 2015-05-04
          • 1970-01-01
          • 2021-11-09
          • 1970-01-01
          • 2014-02-19
          相关资源
          最近更新 更多