【问题标题】:Label back color change as ready state. VB.NET将背面颜色更改标记为就绪状态。 VB.NET
【发布时间】:2017-05-03 08:04:36
【问题描述】:

我有一个 Windows 窗体应用程序,我想创建两个状态的“进程”指示器。 我想使用标签来指示子或函数何时运行,背景颜色(绿色、红色)和显示的文本(“OK”、“...”)。

这是下面的简化代码。 名为“Label1”的“指标”标签控件。 我有一些类似于“GridRefresh”的函数和subs。

在 sub 的开头我想将 Label 设置为红色,最后我想将其设置为绿色。

我的问题是,标签永远不会变成红色。 例如GridRefresh 运行 500-1000 毫秒。 我尝试在If Then Else 中设置 2000 毫秒的睡眠时间,但没有任何改变。

Sub GridRefresh()
    ReadySwitch(False)

    '--do something
    ....

    ReadySwitch(True)
End Sub


Sub ReadySwitch(ready As Boolean)

    If ready Then
        Label1.BackColor = Color.LightGreen
        Label1.Text = "OK"
    Else
        Label1.BackColor = Color.Red
        Label1.Text = "..."
    End If

End Sub

我也尝试过多线程,但效果相同。

Sub GridRefresh()
    ReadySwitch(False)

    '--do something
    ....

    ReadySwitch(True)
End Sub


Sub ReadySwitch(ready As Boolean)
    LabelReadyCall(ready)
End Sub

Public t1 As System.Threading.Thread
Sub LabelReadyCall(ByVal ready As Boolean)
    t1 = New System.Threading.Thread(AddressOf Me.LabelReadyExecute)
    t1.Start(ready)
End Sub


Private Delegate Sub LabelReadyDelegate(ByVal ready As Boolean)

Sub LabelReadyExecute(ByVal ready As Boolean)
    If Label1.InvokeRequired Then
        Debug.Print("InvokeRequired - state: " & ready )
        Label1.BeginInvoke(New LabelReadyDelegate(AddressOf LabelReadyExecute), New Object() {ready})
    Else
        If ready Then

            Label1.BackColor = Color.LightGreen
            Label1.Text = "OK"
        Else
            Label1.BackColor = Color.Red
            Label1.Text = "..."
        End If
        Debug.Print("LabelChange - state: " & ready )
        Debug.Print("LabelChange - color: " & Label1.BackColor )
    End If
End Sub

在这种情况下,输出窗口的内容是这样的:

InvokeRequired - state: False
InvokeRequired - state: True
LabelChange - state: False
LabelChange - color: Red
LabelChange - state: True
LabelChange - color: LightGreen

我做错了什么?

【问题讨论】:

  • 如果你使用多线程,你需要一个invoke,否则在更改状态后在单个线程中尝试使用:Application.DoEvents()

标签: vb.net multithreading label


【解决方案1】:

对于多线程,您可以尝试以下方法:

Delegate Sub SetLabel1TextInvoker(ByVal TextToDisplay As String, ByVal colour As Color)
Public Sub SetLabel1Text(ByVal TextToDisplay As String, ByVal colour As Color)
    If Label1.InvokeRequired Then
        Label1.Invoke(New SetLabel1TextInvoker(AddressOf SetLabel1Text), New Object() {TextToDisplay, colour})
    Else
        Label1.Text = TextToDisplay
        Label1.BackColor = colour
    End If
End Sub

然后在您的 ReadySwitch 函数中执行以下操作:

Sub ReadySwitch(ready As Boolean)
    If ready = true Then
        SetLabel1Text("Ok", Color.DarkGreen)
    Else
        SetLabel1Text(". . .", Color.DarkRed)
    End If
End Sub

如果您在单线程应用程序中,您可以尝试使用:

Application.DoEvents()

这将强制应用程序在标签上显示更新。最好的方法仍然是使用多线程操作,但如果您是初学者,这个解决方案可能会更简单

【讨论】:

  • 谢谢你的尝试,但结果相同:/
  • 我不得不说我是一个初学者,所以多线程对我来说是新的。我必须在某个地方结束线程或什么?
  • 当你运行我的代码时到底有什么问题?我在我的软件中使用它来更新标签,同时浏览数千个文件,它可以工作。只需输入我给您的代码,然后添加ReadySwitch(False) 和您的子目录的开头和最后的ReadySwitch(True)。但这仅在您的子程序位于后台工作人员之类的新线程中时才有效。如果您只有一个线程,请在 ReadySwitch 中的 SetLabel1Text 之后添加:Application.DoEvents()
  • Application.DoEvents() 不应使用! @nobre :如果你需要使用它,那你就做错了。
  • @VisualVincent 这就是为什么我说它建议使用多线程而不是它更清洁和更安全。
猜你喜欢
  • 1970-01-01
  • 2017-08-16
  • 2015-09-26
  • 1970-01-01
  • 2021-07-10
  • 1970-01-01
  • 2019-11-20
  • 2016-10-16
  • 1970-01-01
相关资源
最近更新 更多