矩形仅绘制标签在 c# 窗体上传递的部分
Rectangle only paints sections which a label has passed over on c# form
我对我正在编写的用于练习的程序有疑问,该程序在当前状态下允许用户使用箭头键在表单周围移动标签。
我想开始在我的程序中添加一些图形矩形,目前我正在练习在计时器达到 100 时尝试绘制一个简单的矩形。
这是奇怪的部分,矩形只有在标签经过它的一部分时才会绘制,并且只会绘制标签经过的部分。这件事的照片:label passing over rectangle。理想情况下,我想了解为什么会这样,但如果有人能提供解决方案,我也会很高兴!
我会 post 我的整个代码,因为我什至不确定问题可能来自哪一部分。非常抱歉,如果它不整洁,希望有人能从图像中得到一个想法:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
int direction;
int X = 200;
int Y = 200;
Rectangle myRock;
public System.Windows.Forms.Timer aTimer = new System.Windows.Forms.Timer();
public Form1()
{
InitializeComponent();
this.Load += new System.EventHandler(this.Form1_Load);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
this.Click += new System.EventHandler(this.Form1_Click);
}
void worker()
{
for (int i = 0; i < 100000; i++) {
if (label2.InvokeRequired)
{
label2.Invoke((MethodInvoker)delegate
{
label2.Text = i.ToString(); // this is a timer acting as a score keeper
});
Thread.Sleep(100);
}
}
}
public void DrawRectangleRectangle(PaintEventArgs e, Rectangle rect)
{
// Create pen.
Pen blackPen = new Pen(Color.White, 3);
SolidBrush whiteBrush = new SolidBrush(Color.White);
// Create rectangle.
// Draw rectangle to screen.
e.Graphics.DrawRectangle(blackPen, rect);
e.Graphics.FillRectangle(whiteBrush, rect);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_Click(object sender, EventArgs e)
{
Thread newThread = new Thread(worker);
direction = 2;
newThread.Start();
}
private void SetDirection(KeyEventArgs e)
{
if (e.KeyCode == Keys.Down) direction = 4;
else if (e.KeyCode == Keys.Up) direction = 2;
else if (e.KeyCode == Keys.Right) direction = 3;
else if (e.KeyCode == Keys.Left) direction = 1;
}
private void ApplyMovement()
{
Size size = new Size(100,100);
Point position = new Point(100, 100);
while (direction != 0)
{
Application.DoEvents();
if (direction == 1) X--;
else if (direction == 2) Y--;
else if (direction == 3) X++;
else if (direction == 4) Y++;
if (label2.Text == "100") myRock = new Rectangle(position, size);
Thread.Sleep(10);
label1.Location = new Point(X, Y);
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
SetDirection(e);
ApplyMovement();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
int label2Variable = Convert.ToInt32(label2.Text);
if (label2Variable > 100)
{
DrawRectangleRectangle(e, myRock);
}
}
private void label1_Click(object sender, EventArgs e)
{
}
}
}
提前致谢!
发生的情况是 OnPaint()
函数没有被调用,所以您没有重新绘制所有的表单。当 Windows 认为您的表单上的某些内容已更改时,它会向您的应用程序发出重绘命令,要求它重绘全部或部分表单区域,这在您的代码中显示为 Form.OnPaint()
正在触发的方法。
您在这里需要做的是告诉 Windows 您的表单已更改。最简单的方法是调用:
this.Invalidate();
一旦发生变化,可能在 ApplyMovement()
中的循环结束时。
(您也可以调用 this.Refresh()
,这将 Invalidate
整个表单,然后同步重绘它。谢谢@Bradley)
这样,您就告诉 Windows 表单是 "invalid" 并且需要完全重新绘制,因此 Windows 将(间接)调用 OnPaint()
方法。
编辑
对您的应用进行再水化后,我对 ApplyMovement()
方法应用了以下更改:
if (label2.Text == "100") myRock = new Rectangle(position, size);
...改为...
if (label2.Text == "100")
{
myRock = new Rectangle(position, size);
this.Invalidate();
}
现在,当递增标签字段的值达到“100”时,myRock
矩形会立即出现在我的测试中。
了解您的代码从不直接调用 OnPaint()
很重要。您使用 Invalidate()
方法告诉 Windows 本身您的表单的一部分(或全部)已更改并且需要在屏幕上更新。 Windows 将 "call" OnPaint()
方法。
如果您使用这样的 OnPaint()
方法将信息从您的程序绘制到屏幕上,例如 myRock
矩形或一些自定义绘制的文本,那么任何时候该信息更改,您需要调用 Invalidate()
来触发 OnPaint()
.
这是所有常用控件(例如文本框和按钮)在屏幕上自我更新的方式。每当您更改其属性之一时,它们都会在内部调用 Invalidate()
。
一个快速的思考方式是,任何时候你想要调用 OnPaint()
,你调用 Invalidate()
。
希望这对您有所帮助
我对我正在编写的用于练习的程序有疑问,该程序在当前状态下允许用户使用箭头键在表单周围移动标签。
我想开始在我的程序中添加一些图形矩形,目前我正在练习在计时器达到 100 时尝试绘制一个简单的矩形。
这是奇怪的部分,矩形只有在标签经过它的一部分时才会绘制,并且只会绘制标签经过的部分。这件事的照片:label passing over rectangle。理想情况下,我想了解为什么会这样,但如果有人能提供解决方案,我也会很高兴!
我会 post 我的整个代码,因为我什至不确定问题可能来自哪一部分。非常抱歉,如果它不整洁,希望有人能从图像中得到一个想法:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
int direction;
int X = 200;
int Y = 200;
Rectangle myRock;
public System.Windows.Forms.Timer aTimer = new System.Windows.Forms.Timer();
public Form1()
{
InitializeComponent();
this.Load += new System.EventHandler(this.Form1_Load);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
this.Click += new System.EventHandler(this.Form1_Click);
}
void worker()
{
for (int i = 0; i < 100000; i++) {
if (label2.InvokeRequired)
{
label2.Invoke((MethodInvoker)delegate
{
label2.Text = i.ToString(); // this is a timer acting as a score keeper
});
Thread.Sleep(100);
}
}
}
public void DrawRectangleRectangle(PaintEventArgs e, Rectangle rect)
{
// Create pen.
Pen blackPen = new Pen(Color.White, 3);
SolidBrush whiteBrush = new SolidBrush(Color.White);
// Create rectangle.
// Draw rectangle to screen.
e.Graphics.DrawRectangle(blackPen, rect);
e.Graphics.FillRectangle(whiteBrush, rect);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_Click(object sender, EventArgs e)
{
Thread newThread = new Thread(worker);
direction = 2;
newThread.Start();
}
private void SetDirection(KeyEventArgs e)
{
if (e.KeyCode == Keys.Down) direction = 4;
else if (e.KeyCode == Keys.Up) direction = 2;
else if (e.KeyCode == Keys.Right) direction = 3;
else if (e.KeyCode == Keys.Left) direction = 1;
}
private void ApplyMovement()
{
Size size = new Size(100,100);
Point position = new Point(100, 100);
while (direction != 0)
{
Application.DoEvents();
if (direction == 1) X--;
else if (direction == 2) Y--;
else if (direction == 3) X++;
else if (direction == 4) Y++;
if (label2.Text == "100") myRock = new Rectangle(position, size);
Thread.Sleep(10);
label1.Location = new Point(X, Y);
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
SetDirection(e);
ApplyMovement();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
int label2Variable = Convert.ToInt32(label2.Text);
if (label2Variable > 100)
{
DrawRectangleRectangle(e, myRock);
}
}
private void label1_Click(object sender, EventArgs e)
{
}
}
}
提前致谢!
发生的情况是 OnPaint()
函数没有被调用,所以您没有重新绘制所有的表单。当 Windows 认为您的表单上的某些内容已更改时,它会向您的应用程序发出重绘命令,要求它重绘全部或部分表单区域,这在您的代码中显示为 Form.OnPaint()
正在触发的方法。
您在这里需要做的是告诉 Windows 您的表单已更改。最简单的方法是调用:
this.Invalidate();
一旦发生变化,可能在 ApplyMovement()
中的循环结束时。
(您也可以调用 this.Refresh()
,这将 Invalidate
整个表单,然后同步重绘它。谢谢@Bradley)
这样,您就告诉 Windows 表单是 "invalid" 并且需要完全重新绘制,因此 Windows 将(间接)调用 OnPaint()
方法。
编辑
对您的应用进行再水化后,我对 ApplyMovement()
方法应用了以下更改:
if (label2.Text == "100") myRock = new Rectangle(position, size);
...改为...
if (label2.Text == "100")
{
myRock = new Rectangle(position, size);
this.Invalidate();
}
现在,当递增标签字段的值达到“100”时,myRock
矩形会立即出现在我的测试中。
了解您的代码从不直接调用 OnPaint()
很重要。您使用 Invalidate()
方法告诉 Windows 本身您的表单的一部分(或全部)已更改并且需要在屏幕上更新。 Windows 将 "call" OnPaint()
方法。
如果您使用这样的 OnPaint()
方法将信息从您的程序绘制到屏幕上,例如 myRock
矩形或一些自定义绘制的文本,那么任何时候该信息更改,您需要调用 Invalidate()
来触发 OnPaint()
.
这是所有常用控件(例如文本框和按钮)在屏幕上自我更新的方式。每当您更改其属性之一时,它们都会在内部调用 Invalidate()
。
一个快速的思考方式是,任何时候你想要调用 OnPaint()
,你调用 Invalidate()
。
希望这对您有所帮助