Rectangle仅绘制标签在c#表单上传递的部分

时间:2018-01-30 16:54:58

标签: c# forms rectangles onpaint

我对我正在为练习编写的程序有疑问,该程序在当前状态下允许用户使用箭头键在表单周围移动标签。

我想开始在我的程序中添加一些图形矩形,并且我正在练习当计时器达到100时尝试绘制一个简单的矩形。

这里是奇怪的部分,矩形只在标签经过部分区域后绘制,并且只绘制标签经过的部分。发生这种情况的图片:label passing over rectangle。理想情况下,我想了解为什么会这样,但如果有人能提供解决方案,我也会非常高兴!

我会发布我的整个代码,因为我甚至不确定问题可能来自哪个部分。非常抱歉,如果它不整洁,希望有人会从图像中得到一个想法:

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)
    {

    }

}      

}

提前致谢!

1 个答案:

答案 0 :(得分:0)

发生的事情是OnPaint()函数未被调用,因此您不会重新绘制所有表单。当Windows认为表单上的内容发生了变化时,它会向您的应用程序发出重绘命令,要求它重新绘制表单区域的全部或部分,该区域在代码中显示为Form.OnPaint()方法被解雇了。

您需要做的是告诉Windows您的表单已更改。最简单的方法是致电:

this.Invalidate();

一旦某些内容发生了变化,可能会在ApplyMovement()的循环结束时发生。

(您也可以调用this.Refresh()Invalidate整个表单,然后对其进行同步重绘。感谢@Bradley

这样,你告诉Windows该表单是&#34;无效&#34;并且需要完全重新绘制,因此Windows将(间接)调用OnPaint()方法。

修改

重新水化您的应用后,我对ApplyMovement()方法应用了以下更改:

if (label2.Text == "100") myRock = new Rectangle(position, size);

......改为......

if (label2.Text == "100")
{
    myRock = new Rectangle(position, size);
    this.Invalidate();
}

现在,当递增标签字段的值达到&#34; 100&#34;时,myRock矩形会立即显示在我的测试中。

了解您的代码永远不会直接调用OnPaint()非常重要。您使用Invalidate()方法告诉Windows自己表单的一部分(或全部)已更改并需要在屏幕上更新。 Windows然后会打电话给#34; OnPaint()方法。

如果你正在使用这样的OnPaint()方法将程序中的信息绘制到屏幕上,例如myRock矩形或某些自定义绘制文本,那么任何时候该信息更改时,您需要致电Invalidate()以触发OnPaint()

所有常用控件(如文本框和按钮)自动更新到屏幕的方式。只要您更改其中一个属性,他们就会在内部调用Invalidate()

快速思考问题的方法是,只要您想要OnPaint()被调用,就可以致电Invalidate()

希望这有帮助