这是我的绘图代码,用鼠标在图表上绘制自定义行。你能帮我做正确的方法吗?
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事件时,它都会消失。
答案 0 :(得分:7)
试试这个......这是一个笔画绘制方法,非常简单,尽可能接近你自己的代码。斯托克斯是鼠标移动的独立集合。每个鼠标在向下和向上之间移动被记录为笔划,所有笔划都被收集,然后每当触发绘制事件时重绘。这个例子很简单,但可能是一个很好的起点。
请注意,您必须为图表对象添加绘图处理程序。
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());
}
}
}
答案 1 :(得分:1)
您目前的实施有任何问题吗?它是否有效,或者您只是想为已经正常工作的函数更好地编写代码。
我认为你的逻辑看起来很好。但是,我会像这样在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;
}
}
}
通过这种方式,即使万一发生任何例外情况并致电Dispose
,您的笔也会被处置。
但是,您也可以考虑将Pen
作为一个类变量,这样每次移动鼠标时都不必创建和处理它。
答案 2 :(得分:1)
您需要在某处存储您的行。
您需要采取的步骤是:
ArrayList<ArrayList<Point>>
- 其中每个ArrayList<Point>
包含一行中的点列表。new ArrayList<Point>
)paint
中,遍历所有行,并绘制数组中每一行的每个点。如果你没有在某处存放你的线路,它们就会丢失。这有意义吗?
存储线条的另一种方法是使用Canvas
对象,其中绘制的内容的像素图将被记住并自动绘制。如果您不介意不将行数据作为矢量点,并且您可能还想使用图像或颜色,那么这可能是更好的方法。
答案 3 :(得分:0)
我发布了solution一段时间,回顾了如何使用鼠标移动绘制线条。这应该适合你。
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)进行偏移。相应调整。如果调整控件的大小,则需要使用上一个锚点重新绘制线条。