我很新(阅读3周exp)到C#(一般编程),用html / css和javascript开始,现在用C#开始了。
我正试图在Windows窗体中创建自己的简单'Paint'应用程序。但我遇到了一个问题,只是无法绕过它,不管我读了多少或跟随其他人的代码,我都被卡住了。以下代码工作正常,但在调整应用程序窗口大小时,绘图会消失。
作为一个解决方案,我已经阅读了在panel1_Paint事件中声明Graphics方法,这应该得到解决。这是我的问题。看到最后一个代码示例,我想出了这个(是的,就像我说的,我是新手)并且它没有绘制任何东西。
我只是试图在panel1_Paint事件下重新创建第一个例子,但我想在mouseMove事件期间出现了问题,我无法弄清楚它是什么。
有人可以向我解释我在这里缺少什么,非常感谢。提前谢谢。
[旧代码]
namespace Painter
{
public partial class Form1 : Form
{
Graphics graphics;
Pen pen = new Pen(Color.Black, 1);
Point startingPoint = new Point(0, 0);
Point endPoint = new Point(0, 0);
bool mousePaint = false;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
startingPoint = e.Location;
if (e.Button == MouseButtons.Left)
{
mousePaint = true;
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if(mousePaint == true)
{
endPoint = e.Location;
graphics = panel1.CreateGraphics();
graphics.DrawLine(pen, startingPoint, endPoint);
}
startingPoint = endPoint;
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
mousePaint = false;
}
}
}
[新规范]
namespace Painter
{
public partial class Form1 : Form
{
Pen pen = new Pen(Color.Black, 1);
Point startingPoint = new Point(0, 0);
Point endPoint = new Point(0, 0);
bool mousePaint = false;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics graphics = panel1.CreateGraphics();
if (mousePaint == true)
{
graphics.DrawLine(pen, startingPoint, endPoint);
}
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
startingPoint = e.Location;
if (e.Button == MouseButtons.Left)
{
mousePaint = true;
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if(mousePaint == true)
{
endPoint = e.Location;
}
startingPoint = endPoint;
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
mousePaint = false;
}
}
}
答案 0 :(得分:1)
以下代码可以正常工作,但在调整应用程序窗口大小时,绘图会消失。
这是因为调整应用程序窗口的大小会使面板的一部分无效,从而导致重绘部分。
第二种方法不起作用的原因(标记为 [新代码] 的原因)是因为只有在重绘相关组件时才会调用 Paint 事件。您可以通过在 MouseDown / MouseMove 事件处理程序中强制重绘面板来部分解决此问题,但您仍然会丢失以前绘制的内容。
可能的解决方案是创建 Bitmap 的实例并在那里进行绘制。然后将此位图设置为面板的 BackgroundImage 。您可以找到有关该here的更多信息。当然,如果应用程序窗口缩小或放大,您需要考虑调整大小以及位图应该发生的事情。
以下是我快速整理的一些代码,以帮助您入门:
namespace WinForms_PaintTest
{
public partial class Form1 : Form
{
private Pen pen;
private Bitmap bitmap;
public Form1()
{
InitializeComponent();
this.pen = new Pen(Color.Black, 1);
this.bitmap = new Bitmap(this.panel1.Width, this.panel1.Height);
this.panel1.BackgroundImage = this.bitmap;
}
private void panel1_MouseMove(Object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
using (Graphics g = Graphics.FromImage(this.bitmap))
{
g.DrawRectangle(this.pen, e.Location.X, e.Location.Y, 1, 1);
}
this.panel1.Refresh();
}
}
private void Form1_FormClosed(Object sender, FormClosedEventArgs e)
{
this.pen.Dispose();
this.bitmap.Dispose();
}
}
}
同样关于此:
this.DoubleBuffered = true;
我相信你的意图是在重新绘制相关控件时防止闪烁?如果是这种情况,您需要针对面板设置此属性,而不是针对表单本身。这有点棘手但因为面板的 DoubleBuffered 属性是受保护的所以你需要从面板继承或诉诸于反射。您可以找到更多信息here。
答案 1 :(得分:1)
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics graphics = panel1.CreateGraphics();
这是胡说八道!始终只使用e.Graphics
param中的Paint
对象!
另外:要触发Paint
事件,只要您的绘图数据发生变化,请执行panel1.Invalidate();
!
另外:确保你明白你的mousePaint
旗帜应该控制什么:鼠标绘画(即添加新的形状来绘制)或常规绘画(即以前绘制的所有形状)!?请注意,所有绘图,当前和之前的需要在Paint事件中完成,必要时,即一遍又一遍!
能够这样做:收集所有的shpes&#39; List<T>
..
要Doublebuffer
Panel
,您需要将其子类化。您的代码会为DoubleBuffering
启用Form
,这很好但不会帮助Panel
..
而是简单地使用PictureBox
,这是用于绘图的控件!
DoubleBuffered
Panel
子类就像这样简单:
class DrawPanel : Panel
{
public DrawPanel()
{
DoubleBuffered = true;
}
}