【问题标题】:How to force Form2.label1.Text appear immediately when Form2.Show()?Form2.Show()时如何强制Form2.label1.Text立即出现?
【发布时间】:2012-12-08 14:40:04
【问题描述】:

我有这个代码:

namespace TuyenTk
{
    public partial class Form1 : Form
    {
        Form2 _form2 = new Form2("");
        public Form1()
        {
            InitializeComponent();
            _form2.Show();
            int i = 0;
            while (i < 5)
            {
                _form2.label1.Text = "" + i;
                Thread.Sleep(500);
                i++;
            }
        }
    }

    public class Form2 : Form
    {
        public System.Windows.Forms.Label label1;
        public System.ComponentModel.Container components = null;

        public Form2()
        {
            InitializeComponent();
        }
        private void InitializeComponent(string t)
        {
            this.label1 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.Location = new System.Drawing.Point(5, 5);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(290, 100);
            this.label1.TabIndex = 0;
            this.label1.Text = t;
            // 
            // Form2
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(300, 100);
            this.ControlBox = false;
            this.Controls.Add(this.label1);
            this.Name = "Form2";
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
            this.ShowInTaskbar = false;
            this.ResumeLayout(false);    
        }
    }
}

Form1运行时显示Form2,但Form2.label1背景为白色,没有文字。
2.5 秒后,Form2.label1.Text = 4。所以 i 的值 0、1、2、3 不会出现。我该如何解决?非常感谢。

【问题讨论】:

  • 添加 _form2.label1.Update();将是一种解决方法。不要写这样的代码,休眠 UI 线程总是是个坏主意。

标签: c# forms label delay show


【解决方案1】:

您想要做的(定期更新标签)是通过使用 Timer 组件来实现的(您可以将它从 ToolBox 拖放到您的表单上)。

public partial class Form1 : Form
{
   Form2 _form2 = new Form2("");
   Timer _timer;
   int _counter;

   public Form1()
   {
       InitializeComponent();          
       _form2.Show();

       if (components == null)
           components = new System.ComponentModel.Container();
       _timer = new Timer(components); // required for correct disposing

       _timer.Interval = 500;
       _timer.Tick += timer_Tick;
       _timer.Start();
   }

   private void timer_Tick(object sender, EventArgs e)
   {
       if (_counter < 5)
       {
          _form2.label1.Text = _counter.ToString();
          _counter++;
          return;
       }

       _timer.Stop();
   }

在其他表单上创建公共控件也不是一个好主意 - 如果您确实需要更新 form2 上的某些值,那么最好在 Form2 类中声明公共方法/属性,这将更新标签:

public partial class Form2 : Form
{
     public int Value
     {             
         set { label1.Text = value.ToString(); }
     }
}

还可以考虑将计时器移至 Form2(让此表单自行更新)。

【讨论】:

  • 使用工具箱是个好建议。代码不是,如果您像这样创建一个计时器,则需要处置一个计时器。用户关闭表单后它会一直滴答作响。
  • @HansPassant 我的错,添加了停止计时器的条件。
  • 当用户在计数器到达 5 之前关闭表单时它不会起作用。你真的必须处理它。仅建议他在表单上放置一个 Timer 组件以便自动完成,从而帮助他跌入成功的陷阱。
  • 好吧,我们可以订阅Closed 事件并在那里停止计时器。或者我们可以使用组件创建计时器(但在我们应该检查当前表单是否存在组件之前)。实际上最好由设计师创建组件。
【解决方案2】:

如果您在 UI 线程中调用 Thread.Sleep(500);,则 GUI 将不负责任。这就是为什么你得到你的 Fomr2.label1 的背景白色。我建议你移动你的代码

while (i < 5)
{
   _form2.label1.Text = "" + i;
   Thread.Sleep(500);
   i++;
}

到另一个线程。你可以参考这个link来完成你的目标。

【讨论】:

  • 大多数时候你看到有人试图在 UI 应用程序中使用Thread.Sleep,这意味着他们应该使用Timer,而不是明确地启动后台线程只是为了进行阻塞等待。
  • 这是一个不负责任的答案。您不能在工作线程中分配 Text 属性。
  • @Servy 感谢您提醒我在这种情况下可以使用Timer。 :)
  • @Hans Passant 我在答案末尾提供了一个链接,介绍了在另一个线程中更新 UI 的方法。我认为这会有所帮助。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-21
  • 1970-01-01
  • 2020-10-13
相关资源
最近更新 更多