winforms标签闪烁

发布于 2024-09-25 10:49:12 字数 5477 浏览 1 评论 0原文

我的标签控件有一个问题,它闪烁得很厉害。

下面是一些重现该问题的代码。

怎么解决这个问题呢?

更新:前一种情况(表单直接包含标签)的解决方案是使 form.DoubleBuffered = true。但这不是一个通用的解决方案。例如,如果标签位于 SplitContainer 内,我该怎么办?这是我的真实案例。

更新的代码:

DoubleBufferedLabel.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace FlickerLabelTest
{
    public class DoubleBufferedLabel : Label
    {
        public DoubleBufferedLabel()
        {
            DoubleBuffered = true;
        }
    }
}

DoubleBufferedSplitContainer.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace FlickerLabelTest
{
    public class DoubleBufferedSplitContainer : SplitContainer
    {
        public DoubleBufferedSplitContainer()
        {
            DoubleBuffered = true;
        }
    }
}

Form1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace FlickerLabelTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            label1.Text += "0";
        }
    }
}

Form1.Designer.cs:

namespace FlickerLabelTest
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.timer1 = new System.Windows.Forms.Timer(this.components);
            this.label1 = new FlickerLabelTest.DoubleBufferedLabel();
            this.splitContainer1 = new DoubleBufferedSplitContainer();
            this.splitContainer1.Panel2.SuspendLayout();
            this.splitContainer1.SuspendLayout();
            this.SuspendLayout();
            // 
            // timer1
            // 
            this.timer1.Enabled = true;
            this.timer1.Interval = 1;
            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
            // 
            // label1
            // 
            this.label1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.label1.Location = new System.Drawing.Point(0, 0);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(186, 262);
            this.label1.TabIndex = 0;
            this.label1.Text = "label1";
            // 
            // splitContainer1
            // 
            this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.splitContainer1.Location = new System.Drawing.Point(0, 0);
            this.splitContainer1.Name = "splitContainer1";
            // 
            // splitContainer1.Panel2
            // 
            this.splitContainer1.Panel2.Controls.Add(this.label1);
            this.splitContainer1.Size = new System.Drawing.Size(284, 262);
            this.splitContainer1.SplitterDistance = 94;
            this.splitContainer1.TabIndex = 1;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 262);
            this.Controls.Add(this.splitContainer1);
            this.DoubleBuffered = true;
            this.Name = "Form1";
            this.Text = "Form1";
            this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
            this.splitContainer1.Panel2.ResumeLayout(false);
            this.splitContainer1.ResumeLayout(false);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.Timer timer1;
        private DoubleBufferedLabel label1;
        private DoubleBufferedSplitContainer splitContainer1;
    }
}

Program.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace FlickerLabelTest
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

I have a problem with the Label control that is terribly flickering.

Below is some code to reproduce the problem.

How to solve this?

UPDATE: The solution for the previous case (a Form contains a Label directly) was to make the form.DoubleBuffered = true. But this is not a generic solution. For example, what should I do in the case of label inside a SplitContainer? this is my real case.

UPDATED CODE:

DoubleBufferedLabel.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace FlickerLabelTest
{
    public class DoubleBufferedLabel : Label
    {
        public DoubleBufferedLabel()
        {
            DoubleBuffered = true;
        }
    }
}

DoubleBufferedSplitContainer.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace FlickerLabelTest
{
    public class DoubleBufferedSplitContainer : SplitContainer
    {
        public DoubleBufferedSplitContainer()
        {
            DoubleBuffered = true;
        }
    }
}

Form1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace FlickerLabelTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            label1.Text += "0";
        }
    }
}

Form1.Designer.cs:

namespace FlickerLabelTest
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.timer1 = new System.Windows.Forms.Timer(this.components);
            this.label1 = new FlickerLabelTest.DoubleBufferedLabel();
            this.splitContainer1 = new DoubleBufferedSplitContainer();
            this.splitContainer1.Panel2.SuspendLayout();
            this.splitContainer1.SuspendLayout();
            this.SuspendLayout();
            // 
            // timer1
            // 
            this.timer1.Enabled = true;
            this.timer1.Interval = 1;
            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
            // 
            // label1
            // 
            this.label1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.label1.Location = new System.Drawing.Point(0, 0);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(186, 262);
            this.label1.TabIndex = 0;
            this.label1.Text = "label1";
            // 
            // splitContainer1
            // 
            this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.splitContainer1.Location = new System.Drawing.Point(0, 0);
            this.splitContainer1.Name = "splitContainer1";
            // 
            // splitContainer1.Panel2
            // 
            this.splitContainer1.Panel2.Controls.Add(this.label1);
            this.splitContainer1.Size = new System.Drawing.Size(284, 262);
            this.splitContainer1.SplitterDistance = 94;
            this.splitContainer1.TabIndex = 1;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 262);
            this.Controls.Add(this.splitContainer1);
            this.DoubleBuffered = true;
            this.Name = "Form1";
            this.Text = "Form1";
            this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
            this.splitContainer1.Panel2.ResumeLayout(false);
            this.splitContainer1.ResumeLayout(false);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.Timer timer1;
        private DoubleBufferedLabel label1;
        private DoubleBufferedSplitContainer splitContainer1;
    }
}

Program.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace FlickerLabelTest
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

(り薆情海 2024-10-02 10:49:12

问题出在对接上。如果将 Label.DockFill 更改为 None,请手动设置标签大小以填充分割面板,然后将其锚定在所有侧面,都不会闪烁。

如果您想查看闪烁的原因,当 Dock 仍设置为 Fill 时,请覆盖 DoubleBufferedLabel 中的 OnResize code> 类,启动应用程序,并在运行时在 OnResize 中设置断点。添加一个针对 Size 的监视,您将看到它在设计时和运行时大小之间翻转。

我尝试在您的示例中使用常规的 SplitContainerLabel,在表单上将 DoubleBuffer 设置为 False,然后它如果我将 Label 上的 Dock 设置为 None,则不会闪烁。

The problem is with the docking. If you change the Label.Dock from Fill to None, manually set the size of the label to fill the split panel and then anchor it on all sides, it won't flicker.

If you want to see the cause of the flicker, while Dock is still set to Fill, override OnResize in your DoubleBufferedLabel class, start the application, and while it is running set a breakpoint in OnResize. Add a watch for the Size and you'll see it flipping between its design time and runtime sizes.

I tried using a regular SplitContainer and Label in your example, set DoubleBuffer to False on the form, and it did not flicker if I left Dock set to None on the Label.

沐歌 2024-10-02 10:49:12

将其粘贴到表单代码中以帮助 Dock 布局计算:

    protected override void OnLoad(EventArgs e) {
        label1.Size = this.ClientSize;
        base.OnLoad(e);
    }

Paste this into your form code to help the Dock layout calculations:

    protected override void OnLoad(EventArgs e) {
        label1.Size = this.ClientSize;
        base.OnLoad(e);
    }
暖风昔人 2024-10-02 10:49:12

我想您正在寻找这个: http://msdn.microsoft.com /en-us/library/3t7htc9c.aspx

示例:

class Form1 : Form
{
   public Form1() {
      this.DoubleBuffered = true;
   }
}

I think you're looking for this: http://msdn.microsoft.com/en-us/library/3t7htc9c.aspx

example:

class Form1 : Form
{
   public Form1() {
      this.DoubleBuffered = true;
   }
}
不爱素颜 2024-10-02 10:49:12

这并不是真正的答案,但为什么您要每毫秒更新标签?
如果您的意思是 1 秒,则必须将间隔设置为 1000。

您可以通过给表单时间来重绘自身并使用更大的间隔来解决此问题。

更新: 事实证明,将 DoubleBuffered 设置为 true 可以解决问题。感谢 csharptest.net 指出这一点,并DxCK 纠正我。

Not really an answer, but why would you want to update your label each millisecond?
If you meant 1 second, you'd have to set your interval to 1000.

You can solve this by giving the form time to redraw itself and using a larger interval.

Update: turned out, setting DoubleBuffered to true solves the problem. Thanks for csharptest.net for pointing this out and DxCK for correcting me.

倒带 2024-10-02 10:49:12

在表单上激活双缓冲将解决该问题。但这实际上是一个昂贵的解决方案。如果您只是将以下内容添加到表单中:

 SetStyle(ControlStyles.AllPaintingInWmPaint, true);

闪烁也会结束。

Windows 操作系统的默认行为是首先让所有窗口绘制其背景,然后再让它们进行实际绘制。这是从以前开始的,当时画字母实际上需要相当多的时间。该标志告诉它立即折叠背景绘画和常规绘画(对于同一窗口)。

真正的双缓冲可以保留用于您实际自己绘画的情况(当您重写 OnPaint 时)。

Activating Double Buffering on the form will fix the problem. But that is actually an expensive solution. If you just add the following to the form:

 SetStyle(ControlStyles.AllPaintingInWmPaint, true);

the flicker will be over too.

The default behavior of the Windows OS it to first let all windows paint their background, and later, let them do actual painting. This is from the old days, when painting letters actually took considerable amount of time. This flag tells it to fold the background paint and the regular paint (for the same window) immediately after each other.

Real Double buffering can be reserved for the cases where you actually do painting yourself (when you override OnPaint).

谈下烟灰 2024-10-02 10:49:12

停止将计时器设置为 1ms。不严重的是,你在这里看到的是,唱片公司试图跟上它的变化,但未能做到这一点,因为它们太频繁了。因此,可能的解决方案是:

  • 选择一种不经常更改标签的方法
  • 激活表单上的双缓冲

Stop setting timers to 1ms. No seriously, what you see here is that the Label tries to keep up with it's changes, but fails to do so because they're to frequent. So possible solutions are:

  • Choose a way to change the Label less often
  • Activate Double-Buffering on the Form
喜你已久 2024-10-02 10:49:12

为什么不通过异步委托运行标签更新函数?或者使用 System.Threading 命名空间来实现不同的风格。

另外,正如我前面的人提到的,如果将表单上的 DoubleBuffer 属性设置为 true(但这不是灵丹妙药),这将很有用。

Why not run your label update function via an asynchronous delegate? Or use System.Threading namespace for a different flavor.

Also, as people before me mentioned, it would be useful if you set the DoubleBuffer property on your form to true (it's no silver bullet though).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文