画程序麻烦

时间:2015-01-27 21:39:35

标签: c# .net winforms

我在c#winforms中制作一个简单的绘画程序。我使用面板作为画布,椭圆作为画笔。当用户单击面板并移动鼠标时,会在面板上绘制椭圆。但是,当用户在鼠标停止时移动鼠标太快时,椭圆将被分段绘制。有没有人知道为什么椭圆是以片段而不是连续的线条绘制的?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DrawApplication
{
public partial class Form1 : Form
{
    public bool flag = false;
    public bool f = false;
    Graphics g;

    public Form1()
    {
        InitializeComponent();
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.UserPaint, true);
    }

    private void mainPanel_Paint(object sender, PaintEventArgs e)
    {     
    }
    int mouseX;
    int mouseY;
    private void mainPanel_MouseDown(object sender, MouseEventArgs e)
    {
        mouseX = e.X;
        mouseY = e.Y;
        flag = true;
    }        
    private void mainPanel_hover(object sender, EventArgs e)
    {

    }
    private void drawEllipse(int x, int y)
    {
        SolidBrush h = new SolidBrush(Color.Black);
        Rectangle rect = new Rectangle(x, y, 10, 10);
        g = mainPanel.CreateGraphics();
        g.FillEllipse(h, rect);
    }
    private void mainPanel_Up(object sender, MouseEventArgs e)
    {
        flag = false;
    }
    private void mainPanel_move(object sender, MouseEventArgs e)
    {
       if(flag){
        drawEllipse(mouseX, mouseY);
      }
    }
  }
}

1 个答案:

答案 0 :(得分:0)

这似乎你有两个不同的问题:

  1. 你没有持久的方式。调用CreateGraphics()并直接渲染到屏幕将不会绘制任何永久性内容。您必须绘制某种类型的Image(例如BitmapMetafile),或保存您想要用于绘图的数据,然后在框架要求时(通过{{1使用 绘制到屏幕上。

  2. 你没有连接点。事实是,当用户移动鼠标时,您不一定会获得鼠标坐标的相邻点。如果鼠标移动得足够快,则报告的两个连续坐标之间的距离可能非常大。所以无论你如何绘制,你的椭圆之间都可能有空格。

  3. 请考虑使用更像这样的代码:

    Paint

    以上只是一个基本的例子。您可以做的一个改进是简单地累积所有点,然后在public partial class Form1 : Form { public bool flag = false; public bool f = false; Bitmap panelImage; Point previousPoint; public Form1() { InitializeComponent(); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.UserPaint, true); panelImage = new Bitmap(mainPanel.Width, mainPanel.Height); } private void mainPanel_Paint(object sender, PaintEventArgs e) { e.Graphics.DrawImage(panelImage, new Point()); } private void mainPanel_MouseDown(object sender, MouseEventArgs e) { previousPoint = e.Location; flag = true; } private void drawLine(Point start, Point end) { using (Graphics g = Graphics.FromImage(mainPanel)) using (Pen pen = new Pen(Colors.Black, 10)) { g.DrawLine(pen, start, end); } } private void mainPanel_Up(object sender, MouseEventArgs e) { flag = false; } private void mainPanel_move(object sender, MouseEventArgs e) { if(flag){ drawLine(previousPoint, e.Location); previousPoint = e.Location; } } } 事件处理程序中使用Graphics.DrawLines()。例如,这可以让您更好地控制线的连接方式。

    另请注意,创建控件时会设置mainPanel_Paint()的大小;如果由于某种原因调整Bitmap的大小,绘图区域仍将是旧的大小。同样,基于点列表的绘图可以很好地解决这个问题。当然,缺点是随着行数的增加,重绘面板所需的时间也会增加。但Panel类可以轻松处理数千行,并且在您开始注意到严重放缓之前,根据您的PC,数十甚至数十万行。