如何在表单上实现一个闪烁的标签

19
我有一个表单,显示消息队列和消息数量,这些消息数量可以更改。实际上,当消息数量增加时,我希望闪烁标签(队列长度),以改善表单的可用性。 我应该实现自定义控件并使用额外的线程或计时器来更改标签的颜色吗?有人实现了这样的功能吗?实现这种行为的最佳解决方案是什么(资源和性能降级最少)?
解决方案: 在表单组件中使用计时器,可以限制每秒钟的动画次数并实现淡出效果,以外部控件背景颜色为基础。

8
我讨厌闪烁的文字,永远不会原谅Netscape。 - David Heffernan
1
@David:闪烁比跑马灯的废话要好,至少如此。我有些同事正在拼命试图将跑马灯重新引入iPhone/iPad应用程序——我想他们在90年代还没有出生。 - MusiGenesis
@David Heffernan 有其他选择吗? - garik
@Igor的另一种选择是不眨眼! - David Heffernan
2
闪烁文本在我恶作剧同事的成功中起到了关键作用。如果我没有使用这项技术,影响将会大大降低。 - Jason
显示剩余2条评论
8个回答

34

以下内容使用asyncawait进行闪烁:

private async void Blink(){
    while (true){
        await Task.Delay(500);
        label1.BackColor = label1.BackColor == Color.Red ? Color.Green : Color.Red;
    }
}

1
你的处理方式是什么来终止这个进程? - Baz Guvenkaya
你可以在循环_continueBlink内添加一个布尔变量的检查,只要它为真就继续循环,否则离开循环。然后你可以在其他地方将其设置为false以退出闪烁循环。 - IdontCareAboutReputationPoints

29

我知道这是一个非常老的帖子,但是任何想要找到比布尔解决方案更加多功能的人可能会从以下内容中受益: 输入图像描述

using System.Diagnostics;
using System.Threading.Tasks;

private async void SoftBlink(Control ctrl, Color c1, Color c2, short CycleTime_ms, bool BkClr)
{
    var sw = new Stopwatch(); sw.Start();
    short halfCycle = (short)Math.Round(CycleTime_ms * 0.5);
    while (true)
    {
        await Task.Delay(1);
        var n = sw.ElapsedMilliseconds % CycleTime_ms;
        var per = (double)Math.Abs(n - halfCycle) / halfCycle;
        var red = (short)Math.Round((c2.R - c1.R) * per) + c1.R;
        var grn = (short)Math.Round((c2.G - c1.G) * per) + c1.G;
        var blw = (short)Math.Round((c2.B - c1.B) * per) + c1.B;
        var clr = Color.FromArgb(red, grn, blw);
        if (BkClr) ctrl.BackColor = clr; else ctrl.ForeColor = clr;
    }
}

你可以这样调用:

SoftBlink(lblWarning, Color.FromArgb(30, 30, 30), Color.Red,2000,false);
SoftBlink(lblSoftBlink, Color.FromArgb(30, 30, 30), Color.Green, 2000,true);

这一直是我的首选解决方案。 - Harold_Finch
你能提供.NET 1.1的示例吗?我想将其放入遗留项目中。此外,这适用于任何前景色和背景色吗? - Willy
我使用.NET 3.5,而不是async/await,使用此解决方案https://dev59.com/x2Eh5IYBdhLWcg3wrU8N#42587193,但它的效果不太好。 - prototype0815
不,我明白了!它使用的是WaitNMilliseconds(),而不是WaitNSeconds()。 - prototype0815

14
Timer timer = new Timer();
timer.Interval = 500;
timer.Enabled = false;

timer.Start();

if( messagesNum > oldMessagesNum)
  timer.Tick += new EventHandler( timer_Tick );
else
  timer.Tick -= timer_Tick;

void timer_Tick( object sender, EventArgs e )
{
   if(messageLabel.BackColor == Color.Black)
      messageLabel.BackColor = Color.Red;
   else
      messageLabel.BackColor = Color.Black;
}

以下是一个非常简单的实现,可在表单内部使用。您也可以使用相同的代码创建自定义控件,并将 Timer.Start() 放置在该控件的方法中。


4
创建自己的UserControl,继承于Label而不是直接继承Control。添加StartBlinking方法,在其中启动一个Timer对象,其Tick事件改变标签的样式(每次更改BackgroundColor和ForegroundColor属性以创建闪烁效果)。
您还可以添加StopBlinking方法来关闭它,或者在5秒后让您的Timer自行停止。

3
您可以创建自定义组件和事件来开始闪烁--我认为这是一个好的解决方案。您可以使用计时器实现闪烁。

3

你能使用动态的 .gif 图片来代替(或许作为数字的背景)吗?这会让它看起来像老式的网页,但这可能有效。


1
-1 是因为负面评价是避免使用可怕的黑客技巧的好方法。 :) - MusiGenesis
1
@MusiGenesis 这是个人观点 :P - vlad
由多人共享,黑客技巧只应作为最后的手段使用。 - Security Hound
3
@Ramhoud,我猜您可能没有理解我的意思。我在争论的是,我的解决方案不是一种黑客行为。它可以正确地解决“将注意力集中到屏幕的这个部分”的问题。 - vlad

0

你可以在这里使用 Timer 类。 这是我实现的内容。 在 Button_click 事件上标签颜色闪烁。

//click event on the button to change the color of the label
public void buttonColor_Click(object sender, EventArgs e)
        {
            Timer timer = new Timer();
            timer.Interval = 500;// Timer with 500 milliseconds
            timer.Enabled = false;

            timer.Start();

            timer.Tick += new EventHandler(timer_Tick);
        }

       void timer_Tick(object sender, EventArgs e)
    {
        //label text changes from 'Not Connected' to 'Verifying'
        if (labelFirst.BackColor == Color.Red)
        {
            labelFirst.BackColor = Color.Green;
            labelFirst.Text = "Verifying";
        }

        //label text changes from 'Verifying' to 'Connected'
        else if (labelFirst.BackColor == Color.Green)
        {
            labelFirst.BackColor = Color.Green;
            labelFirst.Text = "Connected";
        }

        //initial Condition (will execute)
        else
        {
            labelFirst.BackColor = Color.Red;
            labelFirst.Text = "Not Connected";
        }
    }

0

这就是我最终的做法

public partial class MemberDisplay : Form
{
    public string Input;
    public int MASS_STOP = 1;

    public MemberDisplay(string msg)
    {
        InitializeComponent();
        State_Entry();
        Input = msg;
    }

    public void State_Entry()
    {
        this.SpecialFocus.Select();
        this.lbl_TimerTest.Hide();
    }

    private async void RunBlinkyTest(string msg)
    {
        while (msg == "GO" && (MASS_STOP == 0))
        {
            await Task.Delay(500);
            
            lbl_TimerTest.ForeColor =
                lbl_TimerTest.ForeColor == Color.Red ?
                    Color.Black :
                    Color.Red;

            if (msg == "STOP" && (MASS_STOP == 1)) { return; }
        }
    }

    private void btn_TimeTest_Click(object sender, EventArgs e)
    {
        if (btn_TimeTest.Text == "GO")
        {
            this.lbl_TimerTest.Show();
            MASS_STOP = 0;
            RunBlinkyTest("GO");
            btn_TimeTest.Text = "STOP";
            return;
        }

        if (btn_TimeTest.Text == "STOP")
        {
            MASS_STOP = 1;
            RunBlinkyTest("STOP");
            this.lbl_TimerTest.ForeColor = Color.Black;
            this.lbl_TimerTest.Hide();
            btn_TimeTest.Text = "GO";
            return;
        }
    }
}

请在您的代码中添加一些解释。现在没有人能够学习到您的答案,只会将一些未知的代码复制并粘贴到他们的应用程序中。并且请注意代码格式化 :) - Hille

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接