我的应用中有一系列标签 -
Label[] labels = new Label[8];
我想按顺序更改循环内的那些背景颜色
private void btnPrepare_Click(object sender, EventArgs e)
{
Application.DoEvents();
for (int i = 0; i < 8; i++)
{
labels[i].BackColor = System.Drawing.Color.Red;
System.Threading.Thread.Sleep(2000);
}
}
但所有变化都是一起出现的,而不是按顺序出现。
任何帮助?
答案 0 :(得分:6)
这样(快速修正):
private void btnPrepare_Click(object sender, EventArgs e) {
//DONE: foreach - no magic numbers (8)
foreach (var lbl in labels) {
lbl.BackColor = System.Drawing.Color.Red;
lbl.Update(); // <- Update == force label repainting
System.Threading.Thread.Sleep(2000);
}
}
Application.DoEvents()
evil :它会翻译所有事件,例如,表格关闭,当你想要时画。
更好的方法是使用Task
代替Thread
:
// async: we're going to put await in the method
private async void btnPrepare_Click(object sender, EventArgs e) {
//DONE: foreach - no magic numbers (8)
foreach (var lbl in labels) {
lbl.BackColor = System.Drawing.Color.Red;
// await: No need in force repainting, messages translating etc.
await Task.Delay(2000);
}
}
答案 1 :(得分:1)
使用Control.Update()
方法,这将使控件重绘其客户区域内的无效区域。
有两种方法可以重新绘制表单及其内容:
您可以使用Invalidate()
方法使用Update()
方法的其中一个重载。
您可以调用Refresh()
方法,该方法强制控件重绘自身及其所有子项。这相当于将Invalidate()
方法设置为true
并将其与Update()
一起使用。
Invalidate()
方法控制绘制或重新绘制的内容。 Update()
方法控制绘画或重新绘制的时间。如果您同时使用Invalidate()
和Update()
方法而不是调用Refresh()
,那么重新绘制的内容取决于您使用的Invalidate()
超载量。 Update()
方法仅强制控件立即绘制,但Invalidate()
方法控制调用Update()
方法时绘制的内容。
private void btnPrepare_Click(object sender, EventArgs e)
{
for (int i = 0; i < 8; i++)
{
labels[i].BackColor = System.Drawing.Color.Red;
labels[i].Update();
System.Threading.Thread.Sleep(2000);
}
}
private void btnPrepare_Click(object sender, EventArgs e)
{
for (int i = 0; i < 8; i++)
{
labels[i].BackColor = System.Drawing.Color.Red;
labels[i].Refresh();
System.Threading.Thread.Sleep(2000);
}
}
如果您使用Application.DoEvents()
方法(不太可能),它将处理当前在邮件队列中的所有Windows messages。
运行Windows窗体应用程序时,它会创建新窗体,然后等待事件处理。每次表单处理事件时,它都会处理与该事件相关的所有代码。所有其他事件在队列中等待。当您的代码处理事件时,您的应用程序不会响应。例如,如果在顶部拖动另一个窗口,窗口不会重新绘制。
如果您在代码中调用DoEvents()
,您的应用程序可以处理其他事件。在您的示例中,将DoEvents()
添加到您的代码中,以便在另一次迭代到来时重新绘制表单。如果从代码中删除DoEvents()
,则表单将在循环结束前重新显示。
但是,与Refresh()
和Update()
方法不同,它会处理所有事件(甚至是不必要的事件)。
作为补充 - 我想添加this answer,简要(尽可能)说明为什么DoEvents()
危险 供使用。