如何在快速更新值时防止WinForms中的闪烁?

时间:2017-04-30 14:30:17

标签: c# winforms

我有一个简单的Winforms GUI,它在GroupBox中有一个TrackBar,其标题是我用来显示所包含的TrackBar的值:

private void trackBar1_Scroll(object sender, EventArgs e)
{
    UpdateTrackBarPositionText();
}

private void Form1_Load(object sender, EventArgs e)
{
    UpdateTrackBarPositionText();
}

private void UpdateTrackBarPositionText()
{
    groupBox1.Text = ORIGINAL_TRACKBAR_TEXT + qualitySelector.Value.ToString();
}

问题是当擦拭棒时,它和组的标签都会闪烁,特别是在快速擦洗时。对于这样一个简单的操作,CPU使用率也相当高。如何改进此实施?我想实时更新值,而不是在放手后更新,以便用户在选择时看到该值。 DoubleBuffered = true;什么也没做。

编辑: 我在实例化时使用了反射来将GroupBox和条形设置为双缓冲。这有助于Box,但滑块仍然闪烁:(

3 个答案:

答案 0 :(得分:1)

这是计时器的经典用例。让它更新标签,比方说,每秒10次。除此之外真的是一种矫枉过正,因为无论如何都没人能读得那么快。

您可以永久启用计时器,或者(作为优化)您可以在trackBar1_Scroll启用计时器,并在计时器本身中禁用它,如果过去几个滴答的值没有改变。事实上,如果自上次更新后价值没有变化,也不要更新标签(可能会节省一些额外的闪烁)。

答案 1 :(得分:1)

您是否设置了Double Buffering。如果不是从那里开始,那么根据需要采用其他方法。

答案 2 :(得分:1)

这不能解决这个问题,但它会创建一个使用自定义控件的变通方法。

pic

public partial class SliderControl : Control
{
    public event EventHandler ValueChanged;
    public int MinValue { get; set; } 
    public int MaxValue { get; set; }
    public int Value { get; set; }
    public SliderControl()
    {
        InitializeComponent();
        SetStyle(ControlStyles.AllPaintingInWmPaint|ControlStyles.OptimizedDoubleBuffer, true);
        this.MinValue=0;
        this.MaxValue=100;
        this.Value=50;
        this.Text="Value";
    }

    protected override void OnResize(EventArgs e)
    {
        base.OnResize(e);

        SetBoundsCore(Left, Top, Width, 32, BoundsSpecified.Height);
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
        pe.Graphics.DrawRectangle(Pens.Black, 0, 0, Width-1, Height-16);
        using (var gp = new GraphicsPath())
        {
            var rect = new Rectangle(0, 0, Value*(Width-1)/MaxValue-1, Height-16);
            gp.AddRectangle(rect);
            using (var br = new LinearGradientBrush(rect, Color.SteelBlue, Color.LightBlue, LinearGradientMode.Horizontal))
            {
                pe.Graphics.FillPath(br, gp);
                pe.Graphics.DrawPath(Pens.DarkBlue, gp);
            }
        }
        var text = $"{this.Text} = {this.Value}";
        var sz = pe.Graphics.MeasureString(text, SystemFonts.SmallCaptionFont);
        pe.Graphics.DrawString(text, SystemFonts.SmallCaptionFont, Brushes.Black, Width/2-sz.Width/2, Height-16);
    }

    private void SetClickValue(Point click_point)
    {
        int x = (click_point.X+1)*MaxValue/Width;
        this.Value=x;
        this.Refresh();
        this.ValueChanged?.Invoke(this, new EventArgs());
    }

    protected override void OnMouseClick(MouseEventArgs e)
    {
        base.OnMouseClick(e);

        if (e.Button==MouseButtons.Left)
        {
            SetClickValue(e.Location);
        }
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);

        if (e.Button==MouseButtons.Left)
        {
            SetClickValue(e.Location);
        }
    }

}