【问题标题】:calling draw rect does nothing sometimes调用 draw rect 有时什么都不做
【发布时间】:2020-06-17 09:17:57
【问题描述】:

我有一个 c# 表单,我想用它来绘制一个在屏幕上连续移动的框

为了实现这个移动框,我有以下功能。

    public void draw_forever() {
        int counter = 0;
        while (1 < 2) {
            counter += 1;
            Debug.WriteLine("yo");
            draw_rect(this, 0, 0, this.Width, this.Height, 1); // create a white box to clear the screen 
            draw_rect(this, counter, 150, 20, 20,0); // create a black box that moves accross the screen 
            if (counter > this.Width) { counter = 0; } // reset the box 
        }
    }

它会打印“yo”,但不会对表单进行任何更改

在这里我初始化我的表单,调用我的函数并在屏幕上绘制 1 个框。

    public Form1()
    {
        InitializeComponent();
        draw_rect(this, 50, 150, 20, 20, 0); // draw a first black box
        this.Shown += (s, e) =>
        {
            Task.Run(() =>
            {
                draw_forever();
            }
        );};}

我画的 1 个盒子就是你所看到的全部。所以我们可以看到它永远不会用白框清除屏幕

将下面的代码复制并粘贴到一个空白的c#表单中以快速复制我所做的事情

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

namespace draw_forev
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            draw_rect(this, 50, 150, 20, 20, 0); // draw a first black box
            this.Shown += (s, e) =>
            {
                Task.Run(() =>
                {
                    draw_forever();
                }
            );
            };
        }
        public static void draw_rect(Form form, int x, int y, int width, int height, int colournum) // this function draws a block
        {
            Color thecolour;
            if (colournum == 0) { thecolour = Color.Black; }
            if (colournum == 1) { thecolour = Color.White; }
            form.Paint += OnPaint;
            void OnPaint(object sender, PaintEventArgs e)
            {
                if (colournum == 0)
                {
                    using (var Pen1 = new Pen(Color.Black, 9))
                    {
                        e.Graphics.DrawRectangle(Pen1, x, y, width, height);
                    }
                }
                if (colournum == 1)
                {
                    using (var Pen1 = new Pen(Color.White, 9))
                    {
                        Rectangle rect = new Rectangle(x, y, width, height);
                        e.Graphics.DrawRectangle(Pen1, rect);
                    }
                }
            }
        }

        public void draw_forever() {
            int counter = 0;
            while (1 < 2) {
                counter += 1;
                Debug.WriteLine("yo");
                draw_rect(this, 0, 0, this.Width, this.Height, 1); // create a white box to clear the screen 
                draw_rect(this, counter, 150, 20, 20,0); // create a black box that moves accross the screen 
                if (counter > this.Width) { counter = 0; } // reset the box 
            }
        }


    }
}

【问题讨论】:

  • 这还能编译吗?你必须全部重写。为简单起见:订阅 Paint 事件一次,添加一个 Timer(间隔最大 55 毫秒),在其 Tick 事件中,将值添加到 Rectangle 的位置(你永远不会这样做)然后调用this.Invalidate()。顺便说一句,您不需要每次都用相同的颜色填充表单的 ClientArea,只需在设计器中设置 BackColor。删除Task.Run(),改为启动定时器。
  • 您需要在draw_forever(); 中调用this.refresh(); 才能重新绘制表格。由于您正在创建一个新线程,因此您将获得一个例外。所以你需要一种方法来调用它,因为你不会在 creating thread 上调用它
  • 我停在draw_forever()。其余的完全错误,不可读,并且您发布它的方式无法编译(看起来您每次调用该方法时都在订阅 Paint 事件,OnPaint 看起来它在另一个没有 Lambda 的方法中,它不能是本地函数等等)。试试我描述的。
  • @Paul Sütterlin 是吗?那么,void OnPaint 只是被视为本地函数,但不能。编译器不会测试您编写的内容的逻辑。这种方法从根本上就是错误的。
  • @Paul Sütterlin 它可能看起来正在工作。但事实并非如此。 OP 很快就会发现(当应用程序开始崩溃时没有明显原因)。

标签: c# winforms graphics


【解决方案1】:

我对您的代码做了一些更改:

首先,我将draw_forever 方法设为异步,因此您可以使用await Task.Delay(55)。如果您不使用它,您将看不到任何内容,因为您的表单会不断自我更新。

然后,您必须更新 draw_rect 方法。您只是在绘制矩形的轮廓,这不会清除屏幕。另外,我建议您将整数 colournum 替换为实际的 Color 参数。这使得draw_rect 方法更简单,代码更易读。

第三个变化是你必须更新表单。使用this.Refresh() 确保显示所有更改。

这是新代码:

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

namespace draw_forev
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            draw_rect(this, 50, 150, 20, 20, Color.Black, false); // draw a first black box
            this.Shown += (s, e) =>
            {
                Task.Run(() =>
                {
                    draw_forever();
                }
            );
            };
        }
        public static void draw_rect(Form form, int x, int y, int width, int height, Color colour, bool fill) // this function draws a block
        {
            form.Paint += OnPaint;
            void OnPaint(object sender, PaintEventArgs e)
            {
                if (fill)
                {
                    e.Graphics.FillRectangle(new SolidBrush(colour), x, y, width, height);
                }
                else
                {
                    e.Graphics.DrawRectangle(new Pen(colour, 9), x, y, width, height);
                }
            }
        }

        public async void draw_forever()
        {
            int counter = 0;
            while (1 < 2)
            {
                counter += 1;
                Debug.WriteLine("yo " + counter);
                draw_rect(this, 0, 0, this.Width, this.Height, Color.White, true); // create a white box to clear the screen 
                draw_rect(this, counter, 150, 20, 20, Color.Black, false); // create a black box that moves accross the screen 
                this.Invoke(new MethodInvoker(this.Refresh));
                if (counter > this.Width)
                { counter = 0; } // reset the box 
                await Task.Delay(55);
            }
        }


    }
}

尽管这段代码有效,但它根本没有效率。您应该只订阅一次 OnPaint 事件。

【讨论】:

  • 这可能是我的下一个任务
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 2015-11-10
  • 2017-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多