winforms Метка мерцание - PullRequest
       8

winforms Метка мерцание

2 голосов
/ 28 сентября 2010

У меня проблема с элементом управления Label, который ужасно мерцает.

Ниже приведен код для воспроизведения проблемы.

Как решить эту проблему?

ОБНОВЛЕНИЕ:Решение для предыдущего случая (форма содержит метку напрямую) состояло в том, чтобы создать форму. 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());
        }
    }
}

Ответы [ 7 ]

10 голосов
/ 29 сентября 2010

Проблема с стыковкой. Если вы измените значение Label.Dock с Fill на None, вручную установите размер метки, чтобы заполнить разделенную панель, а затем закрепите ее со всех сторон, она не будет мерцать.

Если вы хотите увидеть причину мерцания, в то время как Dock по-прежнему установлен на Fill, переопределите OnResize в вашем классе DoubleBufferedLabel, запустите приложение, и во время его работы установите точку останова в OnResize. Добавьте часы для Size, и вы увидите, что они переключаются между временем разработки и размерами выполнения.

Я пытался использовать обычные SplitContainer и Label в вашем примере, установите DoubleBuffer на False в форме, и он не мерцал, если я оставил Dock установленным None на Label.

2 голосов
/ 28 сентября 2010

Вставьте это в код формы, чтобы помочь в расчете макета Dock:

    protected override void OnLoad(EventArgs e) {
        label1.Size = this.ClientSize;
        base.OnLoad(e);
    }
1 голос
/ 28 сентября 2010

Я думаю, что вы ищете это: http://msdn.microsoft.com/en-us/library/3t7htc9c.aspx

пример:

class Form1 : Form
{
   public Form1() {
      this.DoubleBuffered = true;
   }
}
1 голос
/ 28 сентября 2010

Не совсем ответ, но зачем вам обновлять ярлык каждую миллисекунду ? Если вы имели в виду 1 секунду, вам придется установить интервал в 1000.

Вы можете решить эту проблему, предоставив форме время перерисовывать себя и используя больший интервал.

Обновление: получилось, установка DoubleBuffered в значение true решает проблему. Спасибо за csharptest.net за указание на это и DxCK за исправление меня.

0 голосов
/ 29 сентября 2010

Активация двойной буферизации в форме решит проблему.Но это на самом деле дорогое решение.Если вы просто добавите в форму следующее:

 SetStyle(ControlStyles.AllPaintingInWmPaint, true);

, мерцание тоже закончится.

Стандартное поведение ОС Windows: сначала все окна закрашивают свой фон, а затем позволяют рисовать.Это с давних времен, когда рисование букв на самом деле занимало значительное количество времени.Этот флаг говорит, что сразу же нужно сложить фоновую краску и обычную краску (для одного и того же окна).

Реальная двойная буферизация может быть зарезервирована для случаев, когда вы действительно рисуете себя (когда переопределяете OnPaint).

0 голосов
/ 28 сентября 2010

Почему бы не запустить функцию обновления метки через асинхронный делегат? Или используйте пространство имен System.Threading для другого аромата.

Кроме того, как уже упоминали люди до меня, было бы полезно, если бы вы установили свойство DoubleBuffer в своей форме в true (хотя это не серебряная пуля).

0 голосов
/ 28 сентября 2010

Прекратить установку таймеров на 1 мс. Не серьезно, то, что вы видите здесь, это то, что Label пытается не отставать от своих изменений, но не делает этого, потому что они часто. Возможные решения:

  • Выберите способ изменения метки реже
  • Активировать двойную буферизацию в форме
...