创建一个淡出标签

8

这可能看起来是一个简单的问题...

我正在寻找在C# Winforms中的Label.Opacity属性。

我想要做的事情是有一个方法逐渐淡出一个标签。也许通过一个定时器实现?

由于没有Opacity属性,我试图将其透明度设置为更高的数字,直到它足够高,该项应该是不可见的。但是我似乎无法使其起作用。

目前我有:

public FadeLabel()
{
    MyTimer timer = new MyTimer();
    this.TextChanged += (s, ea) =>
    {
        if (timer.IsActive)
        {
            timer.Reset();
        }
        else
        {
            timer.WaitTime.Miliseconds = 500;
            timer.Start();
            timer.Completed += (a) =>
            {
                int i = 0;
                Timer tm = new Timer();
                tm.Interval = 1;
                tm.Tick += (sa, aea) =>
                {
                    i++;
                    this.ForeColor = Color.FromArgb(i, Color.Black);
                    this.BackColor = Color.FromArgb(i, Color.White);
                    this.Invalidate();
                    if (i == 255)
                    {
                        tm.Stop();
                    }
                };
                tm.Start();
            };
        }
    };
}

请展示一下MyTimer类,如果可以的话。 - Hallaghan
无关紧要。我发现默认情况下无法在WinForms标签上使用透明度。 - Theun Arbeider
顺便提一下,要使标签不可见,只需将其颜色设置为背景颜色即可,无需调整 alpha 通道。 - Daniel Mošmondor
5个回答

13

这是我正在使用的淡出标签的方法:

    label1.Text = "I'm fading out now";
    label1.ForeColor = Color.Black;
    timer1.Start();

    private void timer1_Tick(object sender, EventArgs e)
    {
        int fadingSpeed = 3;
        label1.ForeColor = Color.FromArgb(label1.ForeColor.R + fadingSpeed, label1.ForeColor.G + fadingSpeed, label1.ForeColor.B + fadingSpeed);

        if (label1.ForeColor.R >= this.BackColor.R)
        {
            timer1.Stop();
            label1.ForeColor = this.BackColor;
        }
    }

也许不是最好的解决方案,但我还是一个初学者,所以这就是我能做出的贡献。我将 timer1.Interval 设定为最小值,并调整了 fadingSpeed 直到效果看起来不错。


1
对于不熟悉计时器的人,请确保在 Start() 之前添加以下内容:System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();timer1.Tick += new EventHandler(timer1_Tick); - Automate This

4

我发现创建平滑的淡入淡出效果的一种方法是使用计时器来调整ForeColor RGB变量。这样可以控制持续时间,并使您能够微调从当前ForeColor值到目标值的过渡。

private void timer1_Tick(object sender, EventArgs e)
    {
        // timer interval set to 10 to ensure smooth fading
        // declared int: r = 0, g = 215 and b = 180
        // target values are r = 32, g = 32 and b = 32 to match BackColor
        fade++;
        if (fade >= 500) // arbitrary duration set prior to initiating fade
        {
            if (r < 32) r++; // increase r value with each tick
            if (g > 32) g--; // decrease g value with each tick
            if (b > 32) b--; // decrease b value with each tick
            label1.ForeColor = Color.FromArgb(255, r, g, b);
            if (r == 32 && g == 32 && b == 32) // arrived at target values
            {
                // fade is complete - reset variables for next fade operation
                label1.ForeColor = Color.FromArgb(255, 0, 215, 180);
                label1.Text = "";
                fade = 0;
                r = 0;
                g = 215;
                b = 180;
                timer1.Enabled = false;
            }
        }
    }

3

你的计时器是否阻塞了UI线程?如果是,直到计时器结束后才会显示任何内容。快速修复问题的方法是调用 Application.DoEvents 而不是 this.Invalidate();


实际上,在我的当前代码中,第二个计时器被初始化了,但是代码没有到达“tick”事件。 “MyTimer”类是一个倒计时类。 - Theun Arbeider

1
这是一个更完整和优雅的解决方案:

// Aufruf der Methode aus dem Worker-Thread
private void OnFadeTimerEvent(object sender, ElapsedEventArgs e)
{
    this.Invoke(new Action(() => FadeOutLabel()));
}

private void FadeOutLabel()
{
    if (labelStartHelp.ForeColor.GetBrightness() <= 0.01)
    {
        FadeTimer.Enabled = false;
        labelStartHelp.Visible = false;
        return;
    }
    HslColor hsl = new HslColor(labelStartHelp.ForeColor);
    hsl.L -= 0.002; // Brightness is here lightness
    labelStartHelp.ForeColor = (System.Drawing.Color)hsl.ToRgbColor();
}

使用APC的HslColor类:http://cyotek.com/downloads/view/Cyotek.Windows.Forms.ColorPicker.zip/Cyotek.Windows.Forms.ColorPicker/Cyotek.Windows.Forms.ColorPicker/HslColor.cs 不过不知道许可证。希望你喜欢!

我认为使用“invoke”是一个好主意。我们能否在RGBA颜色中调整Alpha通道,而不是HSL? - Buzz

1
这是我写的内容。它还可以处理不同颜色的标签(例如绿色、红色)。
实例化该类,随时将其附加到标签上。在设置消息和初始前景色之后,调用setColorSteps以及您想要的步骤数。
当您想要运行淡入淡出时,请调用doFade()。
感谢OP提供的计时器循环事件,我在编写此解决方案时使用了它,这对我所需的东西起作用。
/// <summary>
/// Fade a label - Derek Piper 2019
/// </summary>
public class LabelFader
{
    Label label;
    List<ColorStep> colorSteps = new List<ColorStep>();

    public void attachToControl(Label useLabel)
    {
        this.label = useLabel;
    }

    public void setColorSteps(int numSteps)
    {
        if (this.label != null)
        {
            ColorStep start = new ColorStep(this.label.ForeColor);
            ColorStep end = new ColorStep(this.label.BackColor);
            int redIncrement = ((end.R - start.R) / numSteps);
            int greenIncrement = ((end.G - start.G) / numSteps);
            int blueIncrement = ((end.B - start.B) / numSteps);
            this.colorSteps = new List<ColorStep>();
            for (int i = 0; i <= numSteps; i++)
            {
                ColorStep newStep = new ColorStep();
                if (redIncrement > 0)
                {
                    newStep.R = start.R + (i * redIncrement);
                }
                else
                {
                    newStep.R = start.R - (i * redIncrement);
                }
                if (greenIncrement > 0)
                {
                    newStep.G = start.G + (i * greenIncrement);
                }
                else
                {
                    newStep.G = start.G - (i * greenIncrement);
                }
                if (blueIncrement > 0)
                {
                    newStep.B = start.B + (i * blueIncrement);
                }
                else
                {
                    newStep.B = start.B - (i * blueIncrement);
                }
                this.colorSteps.Add(newStep);
            }
        }
    }

    public void doFade(int speedMs = 40)
    {
        Timer tm = new Timer();
        tm.Interval = speedMs;
        int step = 0;
        int end = this.colorSteps.Count;
        if (this.colorSteps.Count > 0)
        {
            tm.Tick += (sa, aea) =>
            {
                ColorStep thisStep = this.colorSteps[step];
                this.label.ForeColor = Color.FromArgb(thisStep.R, thisStep.G, thisStep.B);
                step++;
                if (step >= end)
                {
                    tm.Stop();
                    this.label.Visible = false;
                }
            };
            tm.Start();
        }
    }
}

class ColorStep
{
    public int R = 0;
    public int G = 0;
    public int B = 0;

    public ColorStep()
    {
    }

    public ColorStep(Color from)
    {
        this.setFromColor(from);
    }

    public void setFromColor(Color from)
    {
        this.R = from.R;
        this.G = from.G;
        this.B = from.B;
    }

    public Color getColor()
    {
        return Color.FromArgb(this.R, this.G, this.B);
    }
}

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