在C#中用鼠标画线的正确方法是什么

发布于 2024-10-01 18:59:37 字数 1200 浏览 7 评论 0 原文

这是我的绘图代码,用于用鼠标在图表上绘制自定义线条。你能帮我以正确的方式做吗?

namespace Grafi
    {
        public partial class Form1 : Form
        {

            bool isDrawing = false;
            Point prevPoint;

            public Form1()
            {
                InitializeComponent();
            }

            private void chartTemperature_MouseDown(object sender, MouseEventArgs e)
            {
                isDrawing = true;
                prevPoint = e.Location;
            }

            private void chartTemperature_MouseMove(object sender, MouseEventArgs e)
            {
                Pen p = new Pen(Color.Red, 2); 
                if (isDrawing)
                {
                    Graphics g = chartTemperature.CreateGraphics();    
                    g.DrawLine(p, prevPoint, e.Location);
                    prevPoint = e.Location;

                    numOfMouseEvents = 0;              
                }
                p.Dispose();
            }

            private void chartTemperature_MouseUp(object sender, MouseEventArgs e)
            {
                isDrawing = false;
            }
        }
    }

问题是,当我调整表格大小时,我的线条消失了。每当引发 onPaint 事件时它就会消失。

This is my drawing code to draw a custom line with mouse onto a Chart. Can you please help me to do it proper way ?

namespace Grafi
    {
        public partial class Form1 : Form
        {

            bool isDrawing = false;
            Point prevPoint;

            public Form1()
            {
                InitializeComponent();
            }

            private void chartTemperature_MouseDown(object sender, MouseEventArgs e)
            {
                isDrawing = true;
                prevPoint = e.Location;
            }

            private void chartTemperature_MouseMove(object sender, MouseEventArgs e)
            {
                Pen p = new Pen(Color.Red, 2); 
                if (isDrawing)
                {
                    Graphics g = chartTemperature.CreateGraphics();    
                    g.DrawLine(p, prevPoint, e.Location);
                    prevPoint = e.Location;

                    numOfMouseEvents = 0;              
                }
                p.Dispose();
            }

            private void chartTemperature_MouseUp(object sender, MouseEventArgs e)
            {
                isDrawing = false;
            }
        }
    }

Problem is that when I resize form my line disappers. It disappers whenever onPaint event is raised.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

是伱的 2024-10-08 18:59:37

试试这个...这是一种笔画绘制方法,实现非常简单并且尽可能接近您自己的代码。斯托克斯是鼠标运动的单独集合。鼠标在向下和向上之间的每次移动都会记录为一次笔划,所有笔划都会被收集,然后在触发绘画事件时重新绘制。这个例子很简单,但可能是一个很好的起点。

请注意,您必须为图表对象添加绘制处理程序。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace Grafi
{
    public partial class Form1 : Form
    {
        bool isDrawing;
        // our collection of strokes for drawing
        List<List<Point>> _strokes = new List<List<Point>>();
        // the current stroke being drawn
        List<Point> _currStroke;
        // our pen
        Pen _pen = new Pen(Color.Red, 2); 

        public Form1()
        {
            InitializeComponent();
        }

        private void chartTemperature_MouseDown(object sender, MouseEventArgs e)
        {
            isDrawing = true;
            // mouse is down, starting new stroke
            _currStroke = new List<Point>();
            // add the initial point to the new stroke
            _currStroke.Add(e.Location);
            // add the new stroke collection to our strokes collection
            _strokes.Add(_currStroke);
        }

        private void chartTemperature_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDrawing)
            {
                // record stroke point if we're in drawing mode
                _currStroke.Add(e.Location);
                Refresh(); // refresh the drawing to see the latest section
            }
        }

        private void chartTemperature_MouseUp(object sender, MouseEventArgs e)
        {
            isDrawing = false;
        }

        private void chartTemperature_Paint(object sender, PaintEventArgs e)
        {
            // now handle and redraw our strokes on the paint event
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            foreach (List<Point> stroke in _strokes.Where(x => x.Count > 1))
                e.Graphics.DrawLines(_pen, stroke.ToArray());
        }
    }
}

Try this... It is a stroke drawing method, implemented very simply and as close to your own code as possible. Stokes are individual collections of mouse movements. Every mouse move between down and up is recorded as a stroke, all the strokes are collected and then redrawn whenever the paint event is fired. This example is simple but could be a good starting point.

Note that you will have to add the paint handler for your chart object.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace Grafi
{
    public partial class Form1 : Form
    {
        bool isDrawing;
        // our collection of strokes for drawing
        List<List<Point>> _strokes = new List<List<Point>>();
        // the current stroke being drawn
        List<Point> _currStroke;
        // our pen
        Pen _pen = new Pen(Color.Red, 2); 

        public Form1()
        {
            InitializeComponent();
        }

        private void chartTemperature_MouseDown(object sender, MouseEventArgs e)
        {
            isDrawing = true;
            // mouse is down, starting new stroke
            _currStroke = new List<Point>();
            // add the initial point to the new stroke
            _currStroke.Add(e.Location);
            // add the new stroke collection to our strokes collection
            _strokes.Add(_currStroke);
        }

        private void chartTemperature_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDrawing)
            {
                // record stroke point if we're in drawing mode
                _currStroke.Add(e.Location);
                Refresh(); // refresh the drawing to see the latest section
            }
        }

        private void chartTemperature_MouseUp(object sender, MouseEventArgs e)
        {
            isDrawing = false;
        }

        private void chartTemperature_Paint(object sender, PaintEventArgs e)
        {
            // now handle and redraw our strokes on the paint event
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            foreach (List<Point> stroke in _strokes.Where(x => x.Count > 1))
                e.Graphics.DrawLines(_pen, stroke.ToArray());
        }
    }
}
弃爱 2024-10-08 18:59:37

您当前的实施有什么问题吗?它是否有效,或者您只是想让代码更好地适应已经工作的功能。

我觉得你的逻辑看起来很好。但是,我会像这样向 Pen 添加一个 using 子句:

private void chartTemperature_MouseMove(object sender, MouseEventArgs e)
{
  using( Pen p = new Pen(Color.Red, 2)){
    if (isDrawing)
    {
      Graphics g = chartTemperature.CreateGraphics();    
      g.DrawLine(p, prevPoint, e.Location);
      prevPoint = e.Location;

      numOfMouseEvents = 0;              
    }
  }
}

这样,即使在创建 Pen 和调用 Dispose 后发生任何异常,您的 Pen 也会被释放。

但是,您也可以考虑将 Pen 设为类变量,这样您就不必在每次移动鼠标时创建和处置它。

Do you have any problems with your current implementation? Does it work, or do you just want to make the code better for an already working function.

I think you logic looks just fine. However, I would add a using clause to the Pen like this:

private void chartTemperature_MouseMove(object sender, MouseEventArgs e)
{
  using( Pen p = new Pen(Color.Red, 2)){
    if (isDrawing)
    {
      Graphics g = chartTemperature.CreateGraphics();    
      g.DrawLine(p, prevPoint, e.Location);
      prevPoint = e.Location;

      numOfMouseEvents = 0;              
    }
  }
}

This way your Pen will be disposed even in case of any exceptions occuring after it's creation and your call to Dispose.

However, you can also think of making the Pen a class variable so you don't have to create and dispose it each time you move the mouse.

二智少女 2024-10-08 18:59:37

您需要将线路存储在某个地方。

您需要采取的步骤是:

  1. 在主类中创建一个位置来存储您的点,例如 。一个 ArrayList> - 其中每个 ArrayList 包含一行中的点列表。
  2. 等待 mousedown 事件,并在行列表末尾创建一个新行的数组(例如 new ArrayList
  3. 等待 mousemoved 事件,并向最后一行添加一个点每当拖动鼠标时,都会在您的列表中出现。要求在此处更新您的窗口。
  4. 在您的 paint 中,迭代所有线,并绘制数组中每条线的每个点。
  5. 要清除绘图,只需将数组替换为空白列表,然后更新窗口即可。

如果您不将线路存储在某个地方,它们就会丢失。这有道理吗?

存储线条的另一种方法是使用 Canvas 对象,其中所绘制内容的像素图会被记住并自动绘制。如果您不介意不将线数据作为矢量点,并且您可能还想使用图像或颜色,那么这可能是更好的方法。

You need to store your line somewhere.

The steps you need to take are:

  1. Create somewhere to store your points in the main class, e.g . an ArrayList<ArrayList<Point>> - where each ArrayList<Point> contains the list of points in one line.
  2. wait for mousedown events, and create an array for a new line (e.g a new ArrayList<Point>) at the end of the list of lines
  3. wait for mousemoved events, and add a point to the last line in your list, whenever the mouse is dragged. ask to update your window here.
  4. in your paint, iterate through all lines, and draw each point of each line in the array.
  5. to clear the drawing, simply replace array with a blank list, and update the window.

If you don't store your lines somewhere, they will be lost. Does this make sense?

The other way of storing lines is by using a Canvas object, where the pixel-map of what is drawn is remembered and automatically drawn. If you don't mind not having your line data as vector points, and you might also want to use images or colours, then this might be a better approach.

纵性 2024-10-08 18:59:37

我不久前发布了一个解决方案,介绍了如何使用鼠标移动画一条线。这应该对你有用。

  Point mAnchorPoint = new Point(200, 200);
  Point mPreviousPoint = Point.Empty;

  private void panel1_MouseMove(object sender, MouseEventArgs e)
  {
     if (mPreviousPoint != Point.Empty)
     {
        // Clear last line drawn
        ControlPaint.DrawReversibleLine(PointToScreen(mAnchorPoint), PointToScreen(mPreviousPoint), Color.Pink);
     }

     // Update previous point
     mPreviousPoint = e.Location;
     mPreviousPoint.Offset(myPanel1.Location);

     // Draw the new line
     ControlPaint.DrawReversibleLine(PointToScreen(mAnchorPoint), PointToScreen(mPreviousPoint), Color.Pink);
  }

基本上你能做的就是每次鼠标移动时画一条线。如果有上一条线并且您仍在移动鼠标,请擦除该线并绘制新线。请注意,此示例基于特定 Panel(本示例中为 myPanel1)进行偏移。相应地进行调整。如果调整控件的大小,则需要使用锚点上一个点重新绘制线条。

I posted a solution a while back on how to draw a line using mouse movements. This should work for you.

  Point mAnchorPoint = new Point(200, 200);
  Point mPreviousPoint = Point.Empty;

  private void panel1_MouseMove(object sender, MouseEventArgs e)
  {
     if (mPreviousPoint != Point.Empty)
     {
        // Clear last line drawn
        ControlPaint.DrawReversibleLine(PointToScreen(mAnchorPoint), PointToScreen(mPreviousPoint), Color.Pink);
     }

     // Update previous point
     mPreviousPoint = e.Location;
     mPreviousPoint.Offset(myPanel1.Location);

     // Draw the new line
     ControlPaint.DrawReversibleLine(PointToScreen(mAnchorPoint), PointToScreen(mPreviousPoint), Color.Pink);
  }

Basically what you can do is draw a line every time the mouse moves. If there was a previous line and youre still moving the mouse, erase the line and draw the new one. Note that this example offsets based on a specific Panel (myPanel1 in this example). Adjust accordingly. If you resize the control, you will need to redraw the line using the anchor point previous point.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文