Странное поведение TPaintBox

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Аватара пользователя
Andrew55
новенький
Сообщения: 17
Зарегистрирован: 19.01.2011 10:20:37
Откуда: Ставрополь

Странное поведение TPaintBox

Сообщение Andrew55 »

Здравствуйте всем!
Я сделал псевдокнопки на основе TPaintBox, которые меняют свой вид при прохождении над
ними указателя мыши. Все вроде бы работает нормально, но при определенных обстоятельствах,
совершенно бессистемно, из-за чего не могу второй день определить причину, прорисовка
моих псевдокнопок происходит на канвасе формы, то есть при перемещении указателя мыши
над псевдокнопками они перерисовываются совершенно в другом месте, хотя и в определенном.
Происходит это не всегда и не со всеми кнопками.
Реакция на нажатие на кнопку сохраняется, то есть кнопка в исходной позиции сохраняется, перерисовка
не осуществляется, а прорисовывается еще один экземпляр кнопки, который является только картинкой,
но не самой кнопкой. На прилагаемом рисунке можно разглядеть эту ситуацию. Сами кнопки располагаются
в нижней части окна, а дополнительная прорисовка выше и левее.
Может, у кого есть соображения по этому поводу?
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Andrew55
Код нужен, однако, мала-мала... ;)
Аватара пользователя
Andrew55
новенький
Сообщения: 17
Зарегистрирован: 19.01.2011 10:20:37
Откуда: Ставрополь

Сообщение Andrew55 »

Да код, однако, не мала-мала.
Я думаю, что, может, есть общие соображения на этот счет, в смысле принципиальном.
Есть псевдокнопка, которая представляет собой, по сути, TPaintBox, для которого расписаны
процедуры перерисовки на его канвасе градиентной заливки и вывода текста в зависимости
от того, находится ли на нем указатель мыши, произведено ли нажатие на "кнопку" и отработка
события Click. Так почему происходит прорисовка дублирующего изображения не в месте
расположения компонента TPaintBox, а в другой позиции формы?
Кстати, на форме также находится компонент, сделанный на основе TPaintBox, и предназначенный
для рисования графиков (напоминающий TAChart).
Размещал мои "кнопки" на голой форме. В этом случае ложные прорисовки никогда не возникают.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Общие соображения - где-то путаются объекты.
Аватара пользователя
dunin
энтузиаст
Сообщения: 634
Зарегистрирован: 02.05.2007 13:18:11
Откуда: Тољя††и
Контактная информация:

Сообщение dunin »

{$telepathy mode on}
Для получения эффекта: нажимаем на левую (основную) кнопку мыши на псевдокнопке внизу - тянем мышь на график - отпускаем кнопку мыши и получаем ненужную псевдокнопку на графике?
Так? Не? :|
Аватара пользователя
Andrew55
новенький
Сообщения: 17
Зарегистрирован: 19.01.2011 10:20:37
Откуда: Ставрополь

Сообщение Andrew55 »

Нет, просто при перемещении указателя мыши, без нажатия кнопок мыши, по псевдокнопкам происходит
прорисовка ложного изображения. Любое событие, требующее перерисовки формы, убирает ложные
изображения, но если опять перемещать указатель мыши по псевдокнопкам, ложные изображения
снова появляются.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
Сообщения: 1409
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

Скорее, криво работает сохранение/восстановление состояния канвы и/или преобразование координат. Т.к. PaintBox рисует на канве родителя, процесс происходит примерно так:

1) Сохранить состояние Form.Canvas
2) Переместить начало координат из (0,0) в (PaintBox.Left, PaintBox.Top)
3) Задать регион отсечения, ограничив его значениями (PaintBox.Width, PaintBox.Height)
4) Вызвать PaintBox.Paint
5) Восстановить состояние Form.Canvas, в том числе исходный регион отсечения и начало координат.

Если в результате выполнения этих шагов начало координат "не вернется" в точку (0,0), то следующий компонент может быть нарисован в неправильном месте...
Аватара пользователя
Andrew55
новенький
Сообщения: 17
Зарегистрирован: 19.01.2011 10:20:37
Откуда: Ставрополь

Сообщение Andrew55 »

Сергей, а почему может "криво работать"?
Kon.pasc
новенький
Сообщения: 26
Зарегистрирован: 31.10.2009 16:45:38

Сообщение Kon.pasc »

У меня точно такая же проблема. Только я рисую не кнопки, а итемы в TListbox. И именно при перемещении мыши над итемом он рисуется в другом месте и в другом компоненте. Причину я нашел - в событии WMMouseMove значение Self.Canvas.Handle не всегда действительно и бывает даже вообще из другого визуального компонента. Дальнейший поиск баги захлебнулся в дебрях LCL и виджетов. То есть исправить это я не смог и забил на отрисовку по MouseEnter/MouseMove/MouseLeave. Повторяемость была странной - даже откомпилированный .exe то показывал багу, то нет, но чаще показывал.

А как сделать так, чтобы вызов собственной отрисовки не попал между пунктами 1-5 что написал Sergei I. Gorelkin?
Аватара пользователя
Andrew55
новенький
Сообщения: 17
Зарегистрирован: 19.01.2011 10:20:37
Откуда: Ставрополь

Сообщение Andrew55 »

Жаль, что все оказывается так непросто. Думалось, что это я сам где-то ошибся. В кои века
собрался написать свой компонент, и такой облом. Жаль.
Интересно, что баги, о которых я писал, проявляются почти всегда при статусе формы wsMaximized
и почти никогда при других статусах.
Odyssey
энтузиаст
Сообщения: 580
Зарегистрирован: 29.11.2007 16:32:24

Сообщение Odyssey »

Было бы полезно (для проекта Lazarus и его пользователей) создать минимальный пример, иллюстрирующий проблему. Буквально отрисовка прямоугольника на в единственном PaintBox, плюс пошаговая инструкция, как гарантированно с помощью этого примера увидеть баг. Всё это можно закинуть в багтрекер, и тогда станет возможным его исправление.
Будет ли это полезно вам - решайте.

P.S.
Ещё, если версия Lazarus старая, можно попробовать обновиться до последнего стабильного снапшота -- http://www.hu.freepascal.org/lazarus/ , lazarus fixes (0.9.29).
Ask
постоялец
Сообщения: 163
Зарегистрирован: 25.12.2008 02:51:37

Сообщение Ask »

Кстати, на форме также находится компонент, сделанный на основе TPaintBox, и предназначенный
для рисования графиков (напоминающий TAChart).


А зачем, если не секрет? Почему бы не взять собственно TAChart?
Аватара пользователя
Andrew55
новенький
Сообщения: 17
Зарегистрирован: 19.01.2011 10:20:37
Откуда: Ставрополь

Сообщение Andrew55 »

Odyssey писал(а):как гарантированно с помощью этого примера увидеть баг

В том то и дело, что указанный баг вылезает совершенно непредсказуемо, а это
самое неприятное в нашем деле. Была бы стабильность - ухватили бы его за
хвост. Да и обнаружил я ошибку совершенно случайно, думал, что мой проект
завершен, а потом при, наверное, сотом прогоне обнаружил, что "кнопки"
рисуются совершенно не там, где они размещены. Два дня провозился,
но так ничего и не понял, поэтому временно в проблемных местах
вернулся к использованию стандартных кнопок.
К тому же, как я уже писал, при размещении псевдокнопок на голой форме премещение
по ним мыши ни разу не привело к ошибке. Практически никогда также не проявляется,
если окно не максимизировано. Но если будет время, повожусь еще.

Добавлено спустя 4 минуты 57 секунд:
Ask писал(а):А зачем, если не секрет? Почему бы не взять собственно TAChart?


Функционал смещен в нужную для меня сторону.
Ask
постоялец
Сообщения: 163
Зарегистрирован: 25.12.2008 02:51:37

Сообщение Ask »

Функционал смещен в нужную для меня сторону.


Я, собственно, почему спрашиваю -- мне как разработчику интересно знать, чего пользователям не хватает --
может, Я добавлю :-)
Аватара пользователя
Andrew55
новенький
Сообщения: 17
Зарегистрирован: 19.01.2011 10:20:37
Откуда: Ставрополь

Сообщение Andrew55 »

Здравствуйте, Ask.
Мы с Вами уже немного соприкасались по поводу TAChart, но тогда я ушел от общения,
сказав, что поразбираюсь с этим компонентом. Правда, может я тупой, но так и не нашел
возможности осуществления градиентной заливки фона графика. Кроме того, меня не
устраивает для масштабирования только "резиновая" линия.
Поэтому я сделал следующее.
1. Возможность градиентной заливки (максимум шестью цветами) как фона графика, так
и фона LeftAxis, BotAxis и Title. На мой взгляд, градиентная заливка не только улучшает
вид графика чисто эстетически, но делает его в ряде случае более выразительным.
2. Масштабирование графика (от 1 и выше) как по вертикали, так и по горизонтали.
В моем случае я для этого использовал (видно на картинке) трек-бары.
3. Скроллинг графика по обеим осям координат. Скроллинг производится как с использованием
скролл-баров, так и перемещением указателя мыши при нажатой левой кнопке.
Скролл-бары не внедрены в компонент, но связываются с ним путем предварительной
инициализации. Перемещение указателя мыши воздействует на скролл-бары.
4. Отображение на одной из панелей статус-бара (на картинках отсутствует) текущего значения
в принятой системе координат положения указателя мыши. Производится это внешними средствами
по отношению к компоненту, а в компоненте для этого имеются функции обратного пересчета
позиции указателя мыши в значения системы координат. Иногда бывает полезно, наведя
указатель мыши в некоторую точку графика, узнать текущее значение в данной точке.

С наилучшими пожеланиями.
А.Захаров.
snap4.jpg
snap6.jpg
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Ответить