【问题标题】:How to draw a single line using MouseMove Event如何使用 MouseMove 事件绘制一条线
【发布时间】:2011-04-12 11:09:12
【问题描述】:

我正在尝试使用OnMouseMove() 事件绘制一条线。我的问题是每次我移动鼠标都会留下痕迹。我尝试使用刷新方法,但是当我停止移动鼠标时,线条消失了。我不想画线OnPaint();,只想画线OnMouseMove()

编辑:我使用的是透明面板(cp.ExStyle |= 0x20;),所以我不能使用graphics.Clear()BackColor()

这是没有Refresh() 的示例图片:

这是我的代码:

private void panel1_MouseMove(object sender, MouseEventArgs e)
{  
   Graphics g = panel1.CreateGraphics();

   g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
   using (var p = new Pen(Color.Black, 3))
   {
      p.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
      p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;

      g.DrawLine(p, st, e.Location);
   }
   Thread.Sleep(30);
   Invalidate();
   //this.Refresh();

   g.Dispose();
}

问候

【问题讨论】:

标签: c# winforms events graphics gdi


【解决方案1】:

以下内容对我有用。基本上跟踪绘制的最后一条线并使用面板的背景颜色在其上绘制(提供清除它的效果)。

   public partial class Form1 : Form
   {
      public Form1()
      {
         InitializeComponent();
      }

      private const int PEN_WIDTH = 3;
      private const LineCap START_CAP = LineCap.ArrowAnchor;
      private const LineCap END_CAP = LineCap.ArrowAnchor;
      Point mAnchorPoint = new Point(10, 10);
      Point mPreviousPoint = Point.Empty;

      private void panel1_MouseMove(object sender, MouseEventArgs e)
      {
         using (Graphics g = panel1.CreateGraphics())
         {
            // Clear last line drawn
            using (Pen clear_pen = new Pen(panel1.BackColor, PEN_WIDTH))
            {
               clear_pen.StartCap = START_CAP;
               clear_pen.EndCap = END_CAP;
               g.DrawLine(clear_pen, mAnchorPoint, mPreviousPoint);
            }

            // Update previous point
            mPreviousPoint = e.Location;

            // Draw the new line
            using (Pen draw_pen = new Pen(Color.Black, PEN_WIDTH))
            {
               draw_pen.StartCap = START_CAP;
               draw_pen.EndCap = END_CAP;
               g.DrawLine(draw_pen, mAnchorPoint, e.Location);
            }
         }
      }
   }

如果面板的背景颜色设置为透明,则需要将panel1.BackColor 更改为panel1.Parent.BackColor

如果透明面板不起作用,您可以使用DrawReversibleLine 功能(虽然这不允许更改线条的颜色或粗细,但即使面板也不会出现绘图/擦除问题是透明的:

  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);
  }

【讨论】:

  • 啊,是的,这可以正常工作。但我使用的是透明面板(CreateParams.ExStyle |= 0x20;)。
  • 我刚看到你的 cmets。你可以使用panel1.Parent.BackColor
  • panel1 的父级是表单。透明面板闪烁为白色。当我使用panel1.Parent.BackColor
  • @Rye - 用不同的方法更新了我的答案
  • @SwDev 哦!是的drawreversible线。我忘了。等我试试。
【解决方案2】:

另一种在C#中用鼠标画线的简单方法:

public partial class Form1 : Form
{
    Options_c o = new Options_c();

    public Form1()
    {
        InitializeComponent();
    }

    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        o.Allow = false;

    }

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        o.Allow = true;
        o.X = e.X;
        o.Y = e.Y;
    }

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (o.Allow == true)
        {
            Graphics g = pictureBox1.CreateGraphics();
            Pen p1 = new Pen(o.color, 5);
            g.DrawLine(p1, o.X,o.Y, e.X, e.Y);
            o.X = e.X;
            o.Y = e.Y;
        }
    }
}

class Options_c
{
    public Boolean Allow = false;
    public Int32 X;
    public Int32 Y;
    public Color color = Color.Bisque;
}

【讨论】:

  • 欢迎来到 Stack Overflow!不要只发布一段代码,请解释为什么这段代码可以解决所提出的问题。没有解释,这不是答案。
  • 你必须处理 g 和 pen。
【解决方案3】:

之后

g.DrawLine(p, st, e.Location); 

放:

st = e.Location;

这样能解决问题吗?

【讨论】:

  • 不,它只是创建新行。
  • 哦,对了。我以为你想像铅笔一样画画。我现在看到您希望有一个起点,并且能够移动终点,让它在起点和新终点之间只重画一条线。
【解决方案4】:

线消失的问题是面板重绘时,线没有重绘。您真正需要的是在鼠标在面板上移动时更新线段的端点并使面板无效。当然,这意味着您确实处理了面板上的Paint 事件。

这里的代码,没有事件处理程序注册:

Point endPoint;

private void panel1_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

    using (var p = new Pen(Color.Black, 3))
    {
        p.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
        p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;

        g.DrawLine(p, st, endPoint);
    }

    Thread.Sleep(30);
}

private void panel1_MouseMove(object sender, MouseEventArgs e)
{
    endPoint = e.Location;
    panel1.Invalidate();
}

【讨论】:

  • g.Clear() 很好。但是我忘记在其中包含我使用 CreateParams 覆盖面板用户控件的内容。所以面板设置为透明。这就是为什么我不能使用 g.Clear();
  • @Rye:好的。但是为什么不能处理Paint 事件呢?这是最简单的方法。
  • @Rye:你能解释一下这是什么意思吗?
  • 我有一个透明面板。它位于图像(例如图片框)上方,该图像包含线条图。我只想在MouseMove() 事件上使用绘图线测量图纸。
【解决方案5】:

好的,我明白了!如果你必须在两个地理点之间画一条线 定位到这两个位置,然后你必须使用 这种形状的覆盖类...我的代码是:

在 Main Activity 中也写下这段代码:

          public void onCreate(Bundle savedInstanceState)
        {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);

         mapView = (MapView) findViewById(R.id.mapView1);            
         mapView.setBuiltInZoomControls(true);
        mapOverlays = mapView.getOverlays();//it get the mapview all overlays...

         mc = mapView.getController();
        mc.setZoom(13);
        GeoPoint p = new GeoPoint(34159000,73220000);//starting point Abbottabad    
        GeoPoint p1 = new GeoPoint(41159000,43220000);//starting point Abbottabad   
         List<Overlay> mapOverlays2 ;
            mapOverlays2 = mapView.getOverlays();
             projection = mapView.getProjection();  
             myoverlay = new MarkerOverlay(p,p1);
            mapOverlays2.add(myoverlay);//*/

     }


    class MarkerOverlay extends Overlay
    { 
               GeoPoint p,p1;
       private GeoPoint pa;
       public MarkerOverlay(GeoPoint p,GeoPoint p1)
         {  
                     this.p = p;
             this.p1=p1;
            Toast.makeText(GoogleMapShowActivity.this, "point value is "+p +"-->"+p1, Toast.LENGTH_LONG).show();

         }

         public void draw(Canvas canvas, MapView mapView,boolean shadow)//), long when)
         {
            super.draw(canvas, mapView, shadow);                   

            Paint mPaint = new Paint(); 
         mPaint.setDither(true);    
         mPaint.setColor(Color.RED);    
         mPaint.setStyle(Paint.Style.FILL_AND_STROKE);  
         mPaint.setStrokeJoin(Paint.Join.ROUND);    
         mPaint.setStrokeCap(Paint.Cap.ROUND);  
         mPaint.setStrokeWidth(4); 

         GeoPoint gP1 = new GeoPoint(p.getLatitudeE6(),p.getLongitudeE6());//starting point Abbottabad  
         GeoPoint gP2 = new GeoPoint(p1.getLatitudeE6(),p1.getLongitudeE6());//(33695043,73050000);//End point Islamabad            


         Point p1 = new Point();    
         Point p2 = new Point();
         Path path1 = new Path();               
         projection.toPixels(gP1, p1);  //changing the latitude into the screen pixels.
         projection.toPixels(gP2, p2);  
        path1.moveTo(p1.x, p1.y);//Moving to Abbottabad location
         path1.lineTo(p2.x,p2.y);//Path till Islamabad  
      canvas.drawPath(path1, mPaint);//Actually drawing the path from Abbottabad to Islamabad

         }

         //--------------------------//
        public boolean onTouchEvent(MotionEvent event, MapView mapView) 
          {
            location_touch++;//this is called two times before executing other codes in thsi method(), 
            // Toast.makeText(GoogleMapShowActivity.this, "this is mmmm"+location_touch, Toast.LENGTH_LONG).show();
               if (event.getAction() == 1)
               {

                 // Toast.makeText(GoogleMapShowActivity.this, "this is me ..."+location_touch, Toast.LENGTH_LONG).show();
                  GeoPoint p = mapView.getProjection().fromPixels((int) event.getX(), (int) event.getY());

                           if((location_touch%2)!=0)
                            {
                                location_touch=0;
                                Toast.makeText(GoogleMapShowActivity.this, "VALUE 2..."+location_touch+"gp is "+p+",,"+p1, Toast.LENGTH_LONG).show();
                                mapView.getOverlays().add(new MarkerOverlay(p,pa));
                                mapView.invalidate();

                            }
                           else //if((location_touch==0 ))
                            {
                              pa=p;
                                Toast.makeText(GoogleMapShowActivity.this, "VALUE 1.."+location_touch+",,,"+p1, Toast.LENGTH_LONG).show();
                                location_touch++;


                            }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-06
    • 2021-04-26
    • 2022-11-12
    • 1970-01-01
    • 2014-04-11
    • 2010-09-29
    • 2017-07-02
    • 2020-11-09
    相关资源
    最近更新 更多