Конференция "Начинающим" » PaintBox.OnPaint [D7]
 
  • Гена (13.12.16 15:53) [0]
    Приведу топорный пример для пояснения сути вопроса

    FromAr: array[0..99999] of TPoint;
    ToAr: array[0..99999] of TPoint;

    Button.OnClick
    begin
    {что-то делаю с FromAr и ToAr}
    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;
  • Юрий Зотов © (13.12.16 17:49) [1]
    Если я еще не забыл Delphi, то перерисовка произойдет, когда:

    1. Система пошлет в очередь сообщений WM_PAINT (например, если по окну проехали другим окном).

    2. И это WM_PAINT будет выбрано из очереди.

    Если программа однопоточная и чем-то занята (модификацией массивов или еще чем-то), то п.2 не случится до завершения операции (если не вызывать Application.ProcessMessages принудительно). То есть, перерисовки в это время не будет.

    Если же программа многопоточная и модификация массивов выполняется в отдельном потоке (причем асинхронно), то главный поток, независимо от второго потока, выберет сообщение и произведет перерисовку. Но и в этом случае потоки можно синхронизировать так, что главный поток будет ждать, когда второй поток завершит обновление массивов - и только после этого главный поток сделает перерисовку. Причем на время перерисовки можно заставить ждать уже второй поток.
  • Гена (13.12.16 19:37) [2]
    И все же таким приемом удалось избежать некоторых багов, которые неделями не мог найти. Вот например было у меня приложение с деревом объектов, ноды которого ссылались на конролы, а внизу конролов лежал paintbox в котором отрисовывалось выделение рамкой выбранного контрола.  Так вот нажимая delete в treeviee удалялся с формы контрол и соотаетствующий нод. Но все дело в том, что там было групповое выделение. И видать при удалении первого контрола, а затем его из treeview вызывался onpaint
  • Юрий Зотов © (13.12.16 19:48) [3]
    > Гена   (13.12.16 19:37) [2]

    BeginUpdate/EndUpdate ?
  • Юрий Зотов © (13.12.16 23:32) [4]
  • Гена (14.12.16 08:43) [5]

    > 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;

    Велосипед
  • Игорь Шевченко © (14.12.16 10:54) [6]

    > Может ли случиться перерисовка, пока не выполнились все
    > операции по модификации FromAr и ToAr по Button.OnClick?
    >


    Нет не может
  • An a Student (14.12.16 13:51) [7]
    Как уже говорили - не может --> при отсутствии потоков и вызовов ProcessMessages().
    От себя добавлю что не только ProcessMessages() - перерисовка TProgressBar при изменении Position происходит сразу, а не после. Вы же не написали что именно делаете в OnClick(), планируете ли обращаться к каким-то компонентам. Мало ли что попадётся какой аналог OnPictureChange() и перерисует.

    А я бы вместо TPaintBox взял TImage. В данном конкретном случае это будет явно лучше.
  • Игорь Шевченко © (14.12.16 15:07) [8]

    > А я бы вместо TPaintBox взял TImage. В данном конкретном
    > случае это будет явно лучше.


    Обоснования последуют, почем именно в "данном конкретном случае" TImage лучше (чем?) TPaintBox ?
  • An a Student (14.12.16 16:14) [9]
    Ну для начала основной вопрос данной темы отпадёт самим собой (или как там правильно говорится).
    А почему лучше - достаточно сравнить количество выполняемых действий. Частоту их выполнения. Прикинуть сколько получится "лишних".
    Можно конечно и тест провести, но я это смогу только если на выходных, по времени.
  • Игорь Шевченко © (14.12.16 17:40) [10]
    An a Student   (14.12.16 16:14) [9]


    > Ну для начала основной вопрос данной темы отпадёт самим
    > собой (или как там правильно говорится).


    Почему ?


    > А почему лучше - достаточно сравнить количество выполняемых
    > действий. Частоту их выполнения. Прикинуть сколько получится
    > "лишних".


    И где сравнение ?
  • An a Student (14.12.16 22:13) [11]
    Потому что TImage будет перерисовываться когда ему нужно. И рисоваться очень быстро.
    А изменение изображения не будет зависеть от WM_PAINT вообще. И как бонус будут отсутствовать тормоза при перетаскивании/ресайзе/прочейпересировковызывающейфигне окна.

    Говорю же - нету сейчас времени, будет вам подробное сравнение если так хотите, но только на выходных.
  • Игорь Шевченко © (15.12.16 10:24) [12]
    An a Student   (14.12.16 22:13) [11]

    Вы подробнее, не стесняйтесь, я до выходных вполне подожду. Мне крайне интересно поведение TImage, который перерисовывается "когда ему нужно, а не когда WM_PAINT"
  • An a Student (15.12.16 23:20) [13]
    Я такого не говорил, "когда нужно" не подразумевает "не при WM_PAINT". Просто перерисовка может происходить до выхода из обработчика OnClick().
    В воскресение утром будет подробно.
  • Игорь Шевченко © (16.12.16 11:04) [14]

    > Я такого не говорил


    "Потому что TImage будет перерисовываться когда ему нужно. И рисоваться очень быстро.
    А изменение изображения не будет зависеть от WM_PAINT вообще"

    Как прикажешь тебя понимать, Саид ?
  • An a Student (18.12.16 15:58) [15]
    Изменение изображения будет происходить в TButton.OnClick(). Перерисовка TImage будет делаться тогда когда это посчитает нужным VCL. Даже если в процессе OnClick() будет чем-либо спровоцирована перерисовка TImage - оно моментально выведет старый "кадр", без задержек. А смена на новый будет только после выхода из OnClick(). То что и требуется. И без лагов/подвисаний - 100000 линий рисовать это ж уже не мухры-хурмы.

    Вот поизменяйте размеры окон, посворачивайте/поразворачивайте, поперетаскивайте их (в том числе чтоб они попадали за пределы экрана), отдельно друг от друга.
    Даже на более шустром отцовском компе с Win7 разница очевидна, а уж на моём слабом нетбуке с XP...
    Не знаю как тут прикреплять файлы, можно ли на обменники, но раз сам модератор сильно хочет видеть "тест":
  • An a Student (18.12.16 15:59) [16]
    Вот, отдельным постом на всякий случай: http://dropmefiles.com/8ILqb
  • Игорь Шевченко © (18.12.16 16:05) [17]

    > Перерисовка TImage будет делаться тогда когда это посчитает
    > нужным VCL. Даже если в процессе OnClick() будет чем-либо
    > спровоцирована перерисовка TImage - оно моментально выведет
    > старый "кадр", без задержек


    а) Я не вижу исходников, а запускать исполняемые файлы не в моих правилах
    б) Не увидел именно сравнения в твоих рассуждениях.
  • An a Student (18.12.16 16:23) [18]
    При дефолтных/начальных значених:
    1) Вариант с TPaintBox жутко подвисает, окно не ресайзится нормально, не перетаскивается нормально, работать с окном невозможно, обработчик OnPaint выполняется неприемлемо долго, при этом количество вызовов MoveTo и LineTo достигают 23000000 и продолжают плодиться, хотя картинка даже не меняется.
    2) Вариант с TImage вообще не виснет, и ресайз и перетаскивание без лагов и задержек, обработчик OnPaint выполняется моментально, количество вызовов MoveTo и LineTo ровно 100000 и больше не увеличивается.
    При изменении векторного изображения:
    1) При отсутствии побочных перерисовок оба варианта тратят равноценное время на "изменение+перерисовка".
    2) При побочных перерисовках вариант с TPaintBox будет выполняться намного медленнее, лагать, подвешивать окно, да ещё и может выводить недообработанные/недоизменённые данные.
  • Игорь Шевченко © (18.12.16 16:41) [19]
    Исходники будут или только рассуждения ?
 
Конференция "Начинающим" » PaintBox.OnPaint [D7]
Есть новые Нет новых   [118410   +20][b:0][p:0.002]