我在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);
}
}
}
}
答案 0 :(得分:0)
这似乎你有两个不同的问题:
你没有持久的方式。调用CreateGraphics()
并直接渲染到屏幕将不会绘制任何永久性内容。您必须绘制某种类型的Image
(例如Bitmap
或Metafile
),或保存您想要用于绘图的数据,然后在框架要求时(通过{{1使用 绘制到屏幕上。
你没有连接点。事实是,当用户移动鼠标时,您不一定会获得鼠标坐标的相邻点。如果鼠标移动得足够快,则报告的两个连续坐标之间的距离可能非常大。所以无论你如何绘制,你的椭圆之间都可能有空格。
请考虑使用更像这样的代码:
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,数十甚至数十万行。