我的Label控件出现问题,非常闪烁。
下面是一些重现问题的代码。
如何解决这个问题?
更新:前一种情况的解决方案(表单直接包含标签)是使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());
}
}
}
答案 0 :(得分:10)
问题在于对接。如果您将Label.Dock
从Fill
更改为None
,请手动设置标签的大小以填充拆分面板,然后将其锚定在所有方面,它不会闪烁。
如果您想查看闪烁的原因,Dock
仍设置为Fill
,请覆盖OnResize
课程中的DoubleBufferedLabel
,启动应用程序,正在运行时在OnResize
中设置断点。添加Size
的监视,您会看到它在设计时和运行时大小之间翻转。
我尝试在您的示例中使用常规SplitContainer
和Label
,在表单上将DoubleBuffer
设置为False
,如果我离开{{1,则不会闪烁在Dock
上设置为None
。
答案 1 :(得分:2)
将其粘贴到您的表单代码中以帮助Dock布局计算:
protected override void OnLoad(EventArgs e) {
label1.Size = this.ClientSize;
base.OnLoad(e);
}
答案 2 :(得分:1)
不是真的答案,但为什么要更新标签每毫秒? 如果您的意思是1秒,则必须将间隔设置为1000.
你可以通过给表单时间重绘自己并使用更大的间隔来解决这个问题。
更新:结果显示,将 DoubleBuffered 设置为true可解决问题。感谢csharptest.net指出这一点,并DxCK来纠正我。
答案 3 :(得分:1)
我认为你正在寻找:http://msdn.microsoft.com/en-us/library/3t7htc9c.aspx
示例:
class Form1 : Form
{
public Form1() {
this.DoubleBuffered = true;
}
}
答案 4 :(得分:0)
停止将定时器设置为1ms。没有认真的,你在这里看到的是标签试图跟上它的变化,但没有这样做,因为它们经常发生。所以可能的解决方案是:
答案 5 :(得分:0)
为什么不通过异步委托运行标签更新功能?或者使用System.Threading命名空间来获得不同的风格。
另外,正如我之前提到的那样,如果你将表单上的DoubleBuffer属性设置为true(虽然它不是银弹)会很有用。
答案 6 :(得分:0)
激活表单上的双缓冲将解决问题。但这实际上是一种昂贵的解决方案。如果您只是将以下内容添加到表单中:
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
闪烁也将结束。
Windows操作系统的默认行为首先让所有窗口绘制背景,然后让它们进行实际绘制。这是过去,当时绘画字母实际上花了相当多的时间。该标志告诉它紧接着相互折叠背景颜料和常规颜料(对于同一窗口)。
真正的双重缓冲可以保留用于您实际自己绘画的情况(当您重写OnPaint时)。