![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Мерцание при перерисовке(GDI+) [D7, WinXP]
unknowing © (2007-04-24 20:11:00)Рисую окружность с рисками через каждые 10 гр, двигаю стрелку по таймеру... И всё это сильно мерцает:(
Как от этого эффекта избавляются профессионалы??
Привожу кусок кода(строго не судить:):
procedure TMainForm.Draw(Count: Smallint);
var
graphics : TGPGraphics;
Pen : TGPPen;
SolidBrush : TGPSolidBrush;
R,
X, Y,
Xc,Yc,
cs, SN,
cs2, SN2 : Single;
CountR : Integer;
const
dash : array[0..2] of single = (2, 20, 20);
begin
graphics := TGPGraphics.Create(PaintBox.Canvas.Handle);
graphics.Clear(clBlack);
Pen := TGPPen.Create(MakeColor(0, 255, 0),2); // салатовый
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
R :=PaintBox.Height - 80; //диаметр окружности
X:= (PaintBox.Width / 2)-R/2; //координата х левого верхнего угла прямоугольника
Y:= (PaintBox.Height / 2)-R/2 ;//координата у левого верхнего угла
graphics.DrawEllipse(Pen, X, Y, R, R); // окружность
Xc := X+(R/2); //координаты центра окружности
Yc := Y+(R/2);
//---------------------риски румбов----------------------------
CountR:=0;
while CountR<360 do
begin
Pen.SetWidth(1);
cs := Xc+(R/2)*cos(CountR*pi/180);
sn := Yc+(R/2)*sin(CountR*pi/180);
cs2 := Xc+(7+R/2)*cos(CountR*pi/180);
sn2 := Yc+(7+R/2)*sin(CountR*pi/180);
if frac(CountR/30) = 0 then
begin //параметры для толстых рисок
Pen.SetWidth(3); //
sn2 := Yc+(10+R/2)*sin(CountR*pi/180);
end;
graphics.DrawLine(pen, cs, sn,cs2,sn2); //рисуем риску
Inc(CountR,10);
end;
//---------------------------------------------------------------
//---------------------движение стрелки-----------------------
Pen.SetWidth(2);
cs := Xc+(R/2)*cos(Count*pi/180);
sn := Yc+(R/2)*sin(Count*pi/180);
cs2 := Xc+(R/2 - 15)*cos((10+Count)*pi/180);
sn2 := Yc+(R/2 - 15)*sin((10+Count)*pi/180);
graphics.DrawLine(pen, cs,sn, cs2,sn2); //стрелка (левая)
cs2 := Xc+(R/2- 15)*cos((-10+Count)*pi/180);
sn2 := Yc+(R/2- 15)*sin((-10+Count)*pi/180);
graphics.DrawLine(pen, cs,sn, cs2,sn2); //стрелка (правая)
//---------------------------------------------------------------
//-----------------------базовые линии окружности-------------
Pen.SetWidth(0.5);
Pen.SetDashPattern(@dash, 4);
graphics.DrawLine(Pen,Xc,Yc-R/2-15,Xc,Yc+R/2+15); //горизонтальная базовая линия окружности
graphics.DrawLine(Pen,Xc-R/2-15,Yc,Xc+R/2+15,Yc);
//---------------------------------------------------------------
Pen.Free;
graphics.Free;
end; //Draw
procedure TMainForm.FormCreate(Sender: TObject);
begin
Count:=0;
end;
procedure TMainForm.Timer1Timer(Sender: TObject);
begin
INC(Count,10);
Draw(Count);
//Timer1.Interval=500;
end;
antonn (2007-04-29 11:22:00) [21]по окончании необходимости рисовать. когда приложение в трей свернулось, например...
homm (2007-04-29 09:39:00) [22]> [20] antonn © (29.04.07 09:12)
По окончании чего? Прорисовки то-ли? Дак тогда так и нужно, а если окончании раоты программы, то, нафига мне 2 метра хлама в оператвке, когда приложение свернуто в трей?
antonn (2007-04-29 09:12:00) [23]
> Потому что потому. Если бы все программы сразу выделяли
> максимальное количество памяти, которое им понадобится,
> было бы очень печально работать на айбиэм писи. Скажи, часто
> ли у тебя окна свернутые в трей находяться? Если нет — снимаю
> шляпу.
> а по окончании убить.
homm (2007-04-29 06:08:00) [24]> Ну а если он мерцает, значит достаточно часто, так почему
> бы не создать один раз нужные объекты и юзать их в процессе
> работы? а по окончании убить.
Потому что потому. Если бы все программы сразу выделяли максимальное количество памяти, которое им понадобится, было бы очень печально работать на айбиэм писи. Скажи, часто ли у тебя окна свернутые в трей находяться? Если нет — снимаю шляпу.
antonn (2007-04-28 23:36:00) [25]создавать отдельно (ну при создании формы) и рисовать используя эти объекты.
для теста можно сделать так в [3], только выводить там где graphics.Free; как нибудь типа paintbox.canvas.copyrect(rect(0,0,paintbox.width,paintbox.height),bitmap.canvas, rect(0,0,bitmap.width,bitmap.height));
Unknowing (2007-04-28 21:51:00) [26]
> antonn © (28.04.07 14:38) [16]
дело в том, что в процессе работы стрелка двигается с частотой 10 Гц и всё с этой же частой перерисовывается. Если не освобождать каждый раз - коллапс... Я лучше ничего не придумал... Есть ли лучший способ?
antonn (2007-04-28 14:38:00) [27]каким образом? если только в рисовании битмап на 20Мб и русет раз в пол часа, тогда понятно. Ну а если он мерцает, значит достаточно часто, так почему бы не создать один раз нужные объекты и юзать их в процессе работы? а по окончании убить.
Unknowing (2007-04-28 13:48:00) [28]
> clickmaker © (28.04.07 12:01) [14]
память эффективней используется, вроде...
clickmaker (2007-04-28 12:01:00) [29]
> [13] Unknowing © (27.04.07 18:46)
а почему не один раз?
Unknowing (2007-04-27 18:46:00) [30]
> antonn © (26.04.07 23:50) [12]
Да, и каждый раз освобождается.
antonn (2007-04-26 23:50:00) [31]есть встречный вопрос - Bitmap создается при каждом рисовании кадра?
unknowing (2007-04-26 19:50:00) [32]Представляю на Ваш суд такое решение:
Bitmap:= TGpBitmap.Create(PaintBox.Width,PaintBox.Height,2498570);
graphics := TGPGraphics.Create(Bitmap);
graphics.FillRectangle(BrushP,0,0,MFD.Width,MFD.Height);
//рисую черный квадрат во весь PaintBox
... здесь рисую окружности, риски и пр.
playBack :=TGPGraphics.Create(MFD.Canvas.Handle);
cBitmap:= TGPCachedBitmap.Create(bitmap, playBack);
playBack.DrawCachedBitmap(cBitmap, 0, 0);
Есть ли лучший способ очистки контекста(типа Clear(clBlack))??
antonn (2007-04-25 00:24:00) [33]я вот из-за этого бага когда то потерял немало времени и нервов, стал подозревать даже невинную IPHLPAPI.DLL :))
homm (2007-04-25 00:12:00) [34]> Doublebuffered:=true + тема в ОС не классическая + D7 +
> Манифест на форме - дают интересные результаты на таких
> контролах, как TButton/TPanel:
В принцепе понятно, чего они не работают, видимо посылают WM_ERASEBACKGROUND, а при включеной даблдуфере, ВСЛ фигу возвращает :) Это конечно аргумент, но зато когда у вас на форме будет 50 компонентов графических, каждый из них будет перерисовывться отдельно, а с дабл буфером рдителя, они все отобразяться одновременно, что куда приятнее выглядит.
antonn (2007-04-24 23:49:00) [35]
> По идее,
> любой способ, реализованный своими руками, лучше.
ну не совсем так, потому как подводные камни есть, иногда велосипед лучше не изобретать. только если у него треугольные колеса иногда, тогда да - можно самому:)
Rial (2007-04-24 23:46:00) [36]> [5] homm © (24.04.07 21:45)
> > А лучше делать ручную буферизацию:
>
> Чегой то лучше? Аргументы?
Все правильно человек советует. По идее,
любой способ, реализованный своими руками, лучше.
Т.к. понимаешь, как он работает и знаешь, что в нем не так :)
А вопросы затрат времени на написание буферизации отпадает
(цена/качество), т.к. задача это простая в общем то.
antonn (2007-04-24 23:36:00) [37]
> Чегой то лучше? Аргументы?
Doublebuffered:=true + тема в ОС не классическая + D7 + Манифест на форме - дают интересные результаты на таких контролах, как TButton/TPanel:
http://antonn.ru/index.php?download=1ec64a0d_1177443306.GIF&id=fe4def6b4ca8370e6c848b091ed4bd3d(15Кб)
одного этого достаточно, чтобы делать вручную...
homm (2007-04-24 21:45:00) [38]> А лучше делать ручную буферизацию:
Чегой то лучше? Аргументы?
Krupsky (2007-04-24 21:38:00) [39]Вся эта братия
graphics : TGPGraphics;
Pen : TGPPen;
SolidBrush : TGPSolidBrush;
и установки:
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
должны быть заранее сделаны. Draw должна быть как можно более быстродейственной!
Рисовать нужно не в таймере, а в TPaintBox.OnPaint. А в таймере нужно вызывать перерисовку при помощи TPaintBox.Invalidate.
Попробуй так, напиши, что получилось.
Fenik (2007-04-24 21:10:00) [40]Ну есть у тебя созданный при старте битмап:
Bmp := TBitmap.Create;
Bmp.Width := 100;
Bmp.Height := 100;
и т.д.
Во время прорисовки указываешь хэндл битмапа а не пеинтбокса (если такое возможно для gdi+ никогда с ним не работал):
graphics := TGPGraphics.Create(Bmp.Canvas.Handle);
А потом выводишь на экран, что-то вроде
PaintBox.Canvas.Draw(0, 0, Bmp);
лучше юзать BitBlt для этого. Можно вообще прямо на форму копировать, тогда мерцать точно не будет )
Совет: 1) заготовить риски загодя, потом просто копируя их с битмапа на битмап, на котором будут стрелки рисоваться. 2) использовать try finally для уничтожения объектов.