Я пытаюсь реализовать следующий метод: пустой Ball:: DrawOn (Графика g);
Метод должен потянуть все предыдущие местоположения (сохраненный в очереди) шара и наконец текущего местоположения. Я не знаю, имеет ли это значение, но я печатаю предыдущие местоположения с помощью g. DrawEllipse (...) и текущее местоположение с помощью g. FillEllipse (...).
Вопрос, что, как Вы могли предположить, существует много рисования, которое будет сделано, и таким образом дисплей начинает мерцать очень. Я искал путь к двойному буферу, но все, что я мог найти, является этими 2 путями:
1) Система. Windows. Формы. Управление. DoubleBuffered = верный;
2) SetStyle (ControlStyles. DoubleBuffer | ControlStyles. UserPaint | ControlStyles. AllPaintingInWmPaint, верный);
при попытке использовать первое, я получаю ошибку при объяснении, что от в этом методе Свойство DoubleBuffered недоступно из-за его уровня защиты. В то время как я не могу изобразить, как использовать метод SetStyle.
Действительно ли это возможно вообще к двойному буферу, в то время как весь доступ, который я имею, к Графическому Объекту, я добираюсь, как введено в методе?
Заранее спасибо,
Править: Я создал следующий класс
namespace doubleBuffer
{
class BufferedBall : System.Windows.Forms.Form{
private Ball ball;
public BufferedBall(Ball ball)
{
this.ball = ball;
}
public void DrawOn(Graphics g){
this.DoubleBuffered = true;
int num = 0;
Rectangle drawArea1 = new Rectangle(5, 35, 30, 100);
LinearGradientBrush linearBrush1 =
new LinearGradientBrush(drawArea1, Color.Green, Color.Orange, LinearGradientMode.Horizontal);
Rectangle drawArea2 = new Rectangle(5, 35, 30, 100);
LinearGradientBrush linearBrush2 =
new LinearGradientBrush(drawArea2, Color.Black, Color.Red, LinearGradientMode.Vertical);
foreach (PointD point in ball.previousLocations)
{
Pen myPen1;
if (num % 3 == 0)
myPen1 = new Pen(Color.Yellow, 1F);
else if (num % 3 == 1)
myPen1 = new Pen(Color.Green, 2F);
else
myPen1 = new Pen(Color.Red, 3F);
num++;
myPen1.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
myPen1.StartCap = System.Drawing.Drawing2D.LineCap.RoundAnchor;
myPen1.EndCap = System.Drawing.Drawing2D.LineCap.AnchorMask;
g.DrawEllipse(myPen1, (float)(point.X - ball.radius), (float)(point.Y + ball.radius), (float)(2 * ball.radius), (float)(2 * ball.radius));
}
if ((ball.Host.ElapsedTime * ball.Host.FPS * 10) % 2 == 0){
g.FillEllipse(linearBrush1, (float)(ball.Location.X - ball.radius), (float)(ball.Location.Y + ball.radius), (float)(2 * ball.radius), (float)(2 * ball.radius));
}else{
g.FillEllipse(linearBrush2, (float)(ball.Location.X - ball.radius), (float)(ball.Location.Y + ball.radius), (float)(2 * ball.radius), (float)(2 * ball.radius));
}
}
}
}
и шар drawOn похож на это:
new BufferedBall(this).DrawOn(g);
Это то, что Вы имели в виду? потому что это все еще мерцает?
Класс формы
имеет свойство DoubleBuffered как защищенное. http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx , но поскольку вы получаете свою форму из Form
, вы можете использовать Это.
Более простой способ установить стиль для двойной буферизации классов, производных от Control, - использовать отражение. См. здесь: http://www.csharp-examples.net/set-doublebuffered/
Это избавит вас от необходимости создавать подкласс элемента управления только для установки защищенного свойства.
Другой вариант, который я вам предложу, это сделать все рисунки в Bitmap, а затем в методе OnPaint просто нарисовать этот Bitmap на форме.
Это ручная работа, но она дает вам полный контроль. Я использовал его с некоторым успехом в некоторых своих домашних проектах.
Вы также можете посмотреть на XNA - это может быть излишним для вашего проекта, но вы можете использовать XNA в WinForms в качестве движка рендеринга.
Вам не нужно устанавливать DoubleBuffered в true каждый раз при перерисовке. Она не отключается при завершении рисования. Просто удалите строку из DrawOn и установите ее в конструкторе или Forms Designer и проверьте результаты. Установка значения false приводит к значительному мерцанию, а установка true - нет.
Я попробовал ваш код в форме, где таймер заставляет перерисовывать изображение каждую миллисекунду, и заметил отсутствие мерцания, когда DoubleBuffered равно true:
private int yDir = 1,xDir=1;
int step = 1;
private void timer1_Tick(object sender, EventArgs e)
{
if (ball.Location.Y >= this.Height-50)
yDir = -1 ;
if (ball.Location.X >= this.Width-50)
xDir= -1 ;
ball.MoveBy(xDir*step,yDir*step);
ball.Host.ElapsedTime++;
this.Invalidate();
}
private void DoubleBufferedBall_Paint(object sender, PaintEventArgs e)
{
DrawOn(e.Graphics);
}
это. DoubleBuffered = true;
Это нормально, но вы должны переместить этот оператор в конструктор. Двойная буферизация требует настройки, Windows Forms должна создать буфер, что должно быть сделано до запуска события paint. Конструктор идеален.