2015-12-30 5 views
1

Я все еще довольно новичок в C# и .NET, поэтому мои вопросы могут звучать noobish. Я пытаюсь создать простое графическое приложение Windows Forms, которое в принципе будет рисовать круг каждый раз, когда пользователь нажимает и он расширяется, а медленно исчезает. Когда я попытался использовать PaintEvent для моей графической функциональности, ничего не произошло, поэтому я создал отдельную функцию под названием «Render», которая вызывается в моем основном таймере обновления. Приложение работало, но графика мерцала. После некоторых исследований я понял, что мне нужно включить двойную буферизацию, чтобы она отображалась в буфер, а затем буфер отображался на экране. Мерцание все еще не прекратилось! Это потому, что двойная буферизация работает только для PaintEvents, и если да, то как я могу заставить PaintEvents работать, или я не могу разрешить двойную буферизацию? Спасибо за помощь! Вот код:C# Winforms Графика мерцает. (Двойная буферизация не помогает!)

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

namespace Widget 
{ 

public class Circle 
{ 
    public float X; 
    public float Y; 
    public float Radius; 
    public int Alpha; 

    public Circle(float X, float Y, float Radius, int Alpha) 
    { 
     this.X = X; 
     this.Y = Y; 
     this.Radius = Radius; 
     this.Alpha = Alpha; 
    } 
} 

public partial class Form1 : Form 
{ 
    public static readonly int ScreenX = Screen.PrimaryScreen.Bounds.Width; 
    public static readonly int ScreenY = Screen.PrimaryScreen.Bounds.Height; 

    public int WindowWidth = 500, WindowHeight = 500; 
    public Graphics G; 
    private Pen Pen; 

    private Timer timer = new Timer(); 
    private List<Circle> Circles; 

    public Form1() 
    { 
     this.Text = "Widget - Sam Brandt"; 
     this.Size = new Size(WindowWidth, WindowHeight); 
     this.StartPosition = FormStartPosition.Manual; 
     this.Location = new Point(ScreenX - WindowWidth - 100, 0); 
     this.FormBorderStyle = FormBorderStyle.FixedSingle; 
     this.MaximizeBox = false; 
     this.Icon = new Icon("C:\\Users\\Admin\\Desktop\\Code Repositories\\Visual Studios\\Widget\\Widget\\Properties\\WidgetIcon.ico"); 
     Pen = new Pen(Color.Black, 1); 
     G = CreateGraphics(); 
     //this.Paint += new PaintEventHandler(OnPaint); 
     ConstructMouse(); 
     FormWithTimer(); 
     DoubleBuffered = true; 

     Circles = new List<Circle>(); 
    } 

    public void ConstructMouse() 
    { 
     this.MouseUp += new MouseEventHandler(OnMouseUp); 
     this.MouseMove += new MouseEventHandler(OnMouseMove); 
     this.MouseDown += new MouseEventHandler(OnMouseDown); 
    } 

    public void FormWithTimer() 
    { 
     timer.Tick += new EventHandler(timer_Tick); 
     timer.Interval = (10); 
     timer.Enabled = true; 
     timer.Start(); 
    } 

    protected void OnMouseUp(object sender, MouseEventArgs e) 
    { 
    } 

    protected void OnMouseMove(object sender, MouseEventArgs e) 
    { 
    } 

    public void OnMouseDown(object sender, MouseEventArgs e) 
    { 
     Circles.Add(new Circle(e.Location.X, e.Location.Y, 0, 255)); 
    } 

    /*public void OnPaint(object sender, PaintEventArgs e) 
    { 
     e.Graphics.Clear(Color.White); 
     for (int i = 0; i < Circles.Count; i++) 
     { 
      Circle C = Circles[i]; 
      e.Graphics.DrawEllipse(new Pen(Color.FromArgb(C.Alpha, 0, 0, 0), 1), C.X - C.Radius, C.Y - C.Radius, 2 * C.Radius, 2 * C.Radius); 
     } 
    }*/ 

    private void Tick() 
    { 
     for (int i = 0; i < Circles.Count; i++) 
     { 
      Circle C = Circles[i]; 
      C.Radius++; 
      C.Alpha -= 3; 
      if (C.Alpha == 0) 
      { 
       Circles.RemoveAt(i); 
      } 
     } 
    } 

    public void Render() 
    { 
     G.Clear(Color.White); 
     for (int i = 0; i < Circles.Count; i++) 
     { 
      Circle C = Circles[i]; 
      G.DrawEllipse(new Pen(Color.FromArgb(C.Alpha, 0, 0, 0), 1), C.X - C.Radius, C.Y - C.Radius, 2 * C.Radius, 2 * C.Radius); 
     } 
    } 

    public void timer_Tick(object sender, EventArgs e) 
    { 
     Render(); 
     Tick(); 
    } 
} 
} 
+1

Где вы добавляли двойную буферизацию? – Phiter

+0

Почему вы чувствуете необходимость использовать таймер? 10 мс таймер ... вот почему ты мерцаешь. –

+0

Philter Fernades: В конструкторе. T McUnknown: Как мне это сделать? – Adraria

ответ

3

Короткий ответ - держите DoubleBuffered = true и используйте Paint событие.

Когда я пытался использовать PaintEvent для моей графической функциональности, ничего не произошло

Когда вы делаете некоторые изменения и хотите, чтобы отразить их, используйте Control.Invalidate метод, который в соответствии с документацией

Невердифицирует всю поверхность элемента управления и вызывает перерисовку элемента управления.

В вашем случае, что-то вроде этого

void timer_Tick(object sender, EventArgs e) 
{ 
    Tick(); 
    Invalidate(); 
} 
+0

Это сработало отлично! благодаря – Adraria

0

Больше наблюдений здесь, но, вероятно, будет ответом.

  • Почему таймер?
  • Используйте событие Paint, оно вызывается, когда GDI + определяет его необходимость, вы постоянно рисуете свой код как есть.
  • Ваш код делает его похожим на то, что вы не используете двойную буферизацию.
+0

Спасибо, что ответили! 1. Я использовал таймер изначально, чтобы увеличить круги каждые 10 мс, но включил рендеринг, потому что событие рисования не рисовало. 2. Когда я использую событие Paint, ничего не происходит ... Это потому, что я не правильно дублирую буфер или что-то еще? 3. Я установил для свойства «DoubleBuffered» значение «true» в конструкторе. Есть что-то еще, что мне нужно сделать? Извините, я не знаю, я новичок. :) – Adraria

0

Я сделаю все рисунок в отдельный графический объект, а затем скопировать, что ваши основные графического объекта на событие тиков таймера, только если есть было изменение. Возможно, вам придется отслеживать это с помощью логического элемента. Это означает, что ваш фоновый рисунок должен быть вызван каким-либо другим событием.

Если ваше изображение действительно меняется каждые 10 миллисекунд, я немного замедляю таймер и устанавливаю его в 50 миллисекунд.

0

Попробуйте это (в VB):

Dim aProp = GetType(Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance) 
aProp.SetValue(Me, True, Nothing) 

были также проблемы с двойной буферизации, и обычное свойство настройки DoubleBuffered истина не работают. Я нашел это решение где-то в сети

Смежные вопросы