-
Приведу топорный пример для пояснения сути вопроса FromAr: array[0..99999] of TPoint;
ToAr: array[0..99999] of TPoint;
Button.OnClick
begin
end;
PaintBox.OnPaint
var
i: Integer;
begin
for i := 0 to 99999 do begin
PaintBox.Canvas.MoveTo(FromAr[i].X, FromAr[i].Y);
PaintBox.Canvas.LineTo(ToAr[i].X, ToAr[i].Y);
end;
end; Может ли случиться перерисовка, пока не выполнились все операции по модификации FromAr и ToAr по Button.OnClick? Такого как ниже лепить не надо? Block: Boolean; Button.OnClick begin Block := True; {что-то делаю с FromAr и ToAr} действия.... действия.... ................. Block := False; end; PaintBox.OnPaint var i: Integer; begin if not Block then begin for i := 0 to 99999 do begin PaintBox.Canvas.MoveTo(FromAr[i].X, FromAr[i].Y); PaintBox.Canvas.LineTo(ToAr[i].X, ToAr[i].Y); end; end; end;
-
Если я еще не забыл Delphi, то перерисовка произойдет, когда:
1. Система пошлет в очередь сообщений WM_PAINT (например, если по окну проехали другим окном).
2. И это WM_PAINT будет выбрано из очереди.
Если программа однопоточная и чем-то занята (модификацией массивов или еще чем-то), то п.2 не случится до завершения операции (если не вызывать Application.ProcessMessages принудительно). То есть, перерисовки в это время не будет.
Если же программа многопоточная и модификация массивов выполняется в отдельном потоке (причем асинхронно), то главный поток, независимо от второго потока, выберет сообщение и произведет перерисовку. Но и в этом случае потоки можно синхронизировать так, что главный поток будет ждать, когда второй поток завершит обновление массивов - и только после этого главный поток сделает перерисовку. Причем на время перерисовки можно заставить ждать уже второй поток.
-
И все же таким приемом удалось избежать некоторых багов, которые неделями не мог найти. Вот например было у меня приложение с деревом объектов, ноды которого ссылались на конролы, а внизу конролов лежал paintbox в котором отрисовывалось выделение рамкой выбранного контрола. Так вот нажимая delete в treeviee удалялся с формы контрол и соотаетствующий нод. Но все дело в том, что там было групповое выделение. И видать при удалении первого контрола, а затем его из treeview вызывался onpaint
-
> Гена (13.12.16 19:37) [2]
BeginUpdate/EndUpdate ?
-
-
> BeginUpdate/EndUpdate ?
> PaintBox.OnPaint > var > i: Integer; > begin > if not Block then begin > for i := 0 to 99999 do begin > PaintBox.Canvas.MoveTo(FromAr[i].X, FromAr[i].Y); > PaintBox.Canvas.LineTo(ToAr[i].X, ToAr[i].Y); > end; > end; > > end;
Велосипед
-
> Может ли случиться перерисовка, пока не выполнились все > операции по модификации FromAr и ToAr по Button.OnClick? >
Нет не может
-
Как уже говорили - не может --> при отсутствии потоков и вызовов ProcessMessages(). От себя добавлю что не только ProcessMessages() - перерисовка TProgressBar при изменении Position происходит сразу, а не после. Вы же не написали что именно делаете в OnClick(), планируете ли обращаться к каким-то компонентам. Мало ли что попадётся какой аналог OnPictureChange() и перерисует.
А я бы вместо TPaintBox взял TImage. В данном конкретном случае это будет явно лучше.
-
> А я бы вместо TPaintBox взял TImage. В данном конкретном > случае это будет явно лучше.
Обоснования последуют, почем именно в "данном конкретном случае" TImage лучше (чем?) TPaintBox ?
-
Ну для начала основной вопрос данной темы отпадёт самим собой (или как там правильно говорится). А почему лучше - достаточно сравнить количество выполняемых действий. Частоту их выполнения. Прикинуть сколько получится "лишних". Можно конечно и тест провести, но я это смогу только если на выходных, по времени.
-
An a Student (14.12.16 16:14) [9]
> Ну для начала основной вопрос данной темы отпадёт самим > собой (или как там правильно говорится).
Почему ?
> А почему лучше - достаточно сравнить количество выполняемых > действий. Частоту их выполнения. Прикинуть сколько получится > "лишних".
И где сравнение ?
-
Потому что TImage будет перерисовываться когда ему нужно. И рисоваться очень быстро. А изменение изображения не будет зависеть от WM_PAINT вообще. И как бонус будут отсутствовать тормоза при перетаскивании/ресайзе/прочейпересировковызывающейфигне окна.
Говорю же - нету сейчас времени, будет вам подробное сравнение если так хотите, но только на выходных.
-
An a Student (14.12.16 22:13) [11]
Вы подробнее, не стесняйтесь, я до выходных вполне подожду. Мне крайне интересно поведение TImage, который перерисовывается "когда ему нужно, а не когда WM_PAINT"
-
Я такого не говорил, "когда нужно" не подразумевает "не при WM_PAINT". Просто перерисовка может происходить до выхода из обработчика OnClick(). В воскресение утром будет подробно.
-
> Я такого не говорил
"Потому что TImage будет перерисовываться когда ему нужно. И рисоваться очень быстро. А изменение изображения не будет зависеть от WM_PAINT вообще"
Как прикажешь тебя понимать, Саид ?
-
Изменение изображения будет происходить в TButton.OnClick(). Перерисовка TImage будет делаться тогда когда это посчитает нужным VCL. Даже если в процессе OnClick() будет чем-либо спровоцирована перерисовка TImage - оно моментально выведет старый "кадр", без задержек. А смена на новый будет только после выхода из OnClick(). То что и требуется. И без лагов/подвисаний - 100000 линий рисовать это ж уже не мухры-хурмы.
Вот поизменяйте размеры окон, посворачивайте/поразворачивайте, поперетаскивайте их (в том числе чтоб они попадали за пределы экрана), отдельно друг от друга. Даже на более шустром отцовском компе с Win7 разница очевидна, а уж на моём слабом нетбуке с XP... Не знаю как тут прикреплять файлы, можно ли на обменники, но раз сам модератор сильно хочет видеть "тест":
-
-
> Перерисовка TImage будет делаться тогда когда это посчитает > нужным VCL. Даже если в процессе OnClick() будет чем-либо > спровоцирована перерисовка TImage - оно моментально выведет > старый "кадр", без задержек
а) Я не вижу исходников, а запускать исполняемые файлы не в моих правилах б) Не увидел именно сравнения в твоих рассуждениях.
-
При дефолтных/начальных значених: 1) Вариант с TPaintBox жутко подвисает, окно не ресайзится нормально, не перетаскивается нормально, работать с окном невозможно, обработчик OnPaint выполняется неприемлемо долго, при этом количество вызовов MoveTo и LineTo достигают 23000000 и продолжают плодиться, хотя картинка даже не меняется. 2) Вариант с TImage вообще не виснет, и ресайз и перетаскивание без лагов и задержек, обработчик OnPaint выполняется моментально, количество вызовов MoveTo и LineTo ровно 100000 и больше не увеличивается. При изменении векторного изображения: 1) При отсутствии побочных перерисовок оба варианта тратят равноценное время на "изменение+перерисовка". 2) При побочных перерисовках вариант с TPaintBox будет выполняться намного медленнее, лагать, подвешивать окно, да ещё и может выводить недообработанные/недоизменённые данные.
-
Исходники будут или только рассуждения ?
|