Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Igors от Декабрь 22, 2013, 12:31



Название: Портирование рисования
Отправлено: Igors от Декабрь 22, 2013, 12:31
Добрый день

Есть старый класс рисования, конструктор
Код
C++ (Qt)
OldPainter::OldPainter( Window * win )
{
GrafPtr port = win->GetPort();
::SetGWorld(port, ::GetMainDevice());   // порт (окно), экран
//...
}
После этого идет рисование нативными ф-циями, напр PaintRect() и все такое. Поскольку вывод double-buffered, никаких изменений на экране еще не происходит. Потом делается такой финт ушами
Код
C++ (Qt)
OldPainter::~OldPainter( void )
{
//..
::QDFlashPortBuffer(..);
//..
}
И окно прекрасно обновляется, причем немедленно.

Как же мне это перевести на Qt  ???

Спасибо


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 22, 2013, 12:37
Вариант "сохранить логику и переписать на QPainter" не предлагать?


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 22, 2013, 12:47
Вариант "сохранить логику и переписать на QPainter" не предлагать?
Так а каким образом ее хранить? Покажите на примере (в псевдокоде конечно)


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 22, 2013, 13:25
Эм... Без приведённого кода никак, но псевдокод.

Было
Код:
PaintRect(бла бла прямоугольник 40 на 40);
SetPixel(бла бла в центре красная точка);
if (какие то данные)
    LineTo(бла бла соединяем все углы с центром);

Станет
Код:
QPainter painter(this);
painter.drawRect(0,0,40,40);
painter.drawPoint(20,20); // + color red
if (какие то данные)
    painter.lineTo(и ещё 3 раза, соединяем все углы с центром);

PS если вы умолчали о каких то подводных камнях старого класса или условностей - не обессудьте, сами виноваты :D


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 22, 2013, 13:36
Все рисуем в backbuffer, по завершении говорим окну update и в его paintEvent рисуем backbuffer.


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 22, 2013, 13:48
Код:
QPainter painter(this);
painter.drawRect(0,0,40,40);
painter.drawPoint(20,20); // + color red
if (какие то данные)
    painter.lineTo(и ещё 3 раза, соединяем все углы с центром);
Это было бы просто замечательно, перевести код на QPainter не проблема. Но ведь я получу по дюнделю создав QPainter(QWidget *) вне paintEvent? Или есть ходы?

Все рисуем в backbuffer, по завершении говорим окну update и в его paintEvent рисуем backbuffer.
update не вызывает немедленной перерисовки - нужно получить событие. Да, есть repaint, но на OSX он == update


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 22, 2013, 13:53
update не вызывает немедленной перерисовки - нужно получить событие. Да, есть repaint, но на OSX он == update
Конечно не вызывает, рисовать на виджет можно только в определенный момент - событие paintEvent. Вы можете только попросить сгенерировать такое событие.


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 22, 2013, 13:55
Эмм.. у вас же обычное рисование.

Просто рисуете всё на буфере - картинке и по мере необходимости update с перерисовкой картинки. Есть проблема? Нет проблемы.

Есть ещё способ с installEventFilter - перехватывать paintEvent, но там со сложными виджетами засада, типа view и прочего.

PS опять не вижу проблемы ^.^ Надо очки поменять что ли...


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 22, 2013, 14:21
PS опять не вижу проблемы ^.^ Надо очки поменять что ли...
Псевдокод
Код
C++ (Qt)
if (1) {
OldPainter op(win);
op.PaintRect(&R);
}   // здесь деструктор вытолкнет нарисованный Rect на экран
while (true) {
// здесь что-то делаем достаточно долго, напр неск секунд
}
Старый код рассчитывает что экран уже обновлен. Чтобы добиться того же с Qt нужно что-то делать, но что? Вызов processEvents может оказаться совсем не безобиден

Конечно не вызывает, рисовать на виджет можно только в определенный момент - событие paintEvent. Вы можете только попросить сгенерировать такое событие.
Хммм....  ну а так ли уж это бесспорно? Да и рисование в pixMap здесь хорошего впечатления не производит


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 22, 2013, 14:33
Приводите пример рисования, мы его разберём. Как я и написал с самого начала - есть ограничения, которые вы не привели.

По простому - разбить на итерации. Нужен квадрат - рисуем квадрат.

Было
Код:
OldPainter op(win);
op.PaintRect(&R);
while (true) {
// здесь что-то делаем достаточно долго, напр неск секунд
}

Стало
Код:
QPainter painter();
painter.begin(&fon); // рисуем на пиксмапе в любое время, когда надо обновляем.
painter.drawRect(bla bla розового цвета);
painter.end();
update();
while (true) {
// здесь что-то делаем достаточно долго, напр неск секунд
}

По-моему вполне нормально переносится. Месяца три назад помогал одному человеку похожее сделать.


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 22, 2013, 14:36
По-моему вполне нормально переносится.
Ничего не произойдет от такого update.
События никто не обрабатывает.


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 22, 2013, 14:41
Во 1 это псевдокод.
Во 2 нужна вся картина и тогда уже будем приводит реально работающий код ^.^ Думаю для всех участвующих в обсуждении цикл событий Qt знаком. Как и методы работы с ним.

Добавим processEvent's, или же  ресурсоёмкие действия вынесем в другую функцию, а можно вообще в отдельный поток. Всё что угодно ;)


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 22, 2013, 15:22
Старый код рассчитывает что экран уже обновлен.
Когда? Объект op не разрушался.

Хммм....  ну а так ли уж это бесспорно?
Для основных платформ (win / X) так.
Внутри вашего top-window вы можете делать что хотите (рисовать на виджеты или QImage или куда хотите), но пользователь это увидит только когда графическая подсистема ОС попросит программу отрисовать его top-window послав ему сообщение.

Да и рисование в pixMap здесь хорошего впечатления не производит
Ну Qt всегда рисует в QImage - она буфферизирует отрисовку.


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 22, 2013, 15:34
Когда? Объект op не разрушался.
Точно, подправил

Ну Qt всегда рисует в QImage - она буфферизирует отрисовку.
Даже там где ОС обеспечивает double-buffer? Не уверен. Кстати нативные ф-ции для немедленного обновления есть, причем не одна. Ладно, не суть.

Во 1 это псевдокод.
Во 2 нужна вся картина и тогда уже будем ..
Пожалуйста, "тарахтелку" не включайте  :)

Хорошо, зайдем с др стороны: а как мне добиться получения paintEvent не трогая при этом др события ? 


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 22, 2013, 15:39
Кстати нативные ф-ции для немедленного обновления есть, причем не одна.
Это какие?


Название: Re: Портирование рисования
Отправлено: gil9red от Декабрь 22, 2013, 15:43
Код:
update()
repaint()
Вот только repaint вызывает немедленное обновление :)


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 22, 2013, 15:49
Это какие?
Да хотя бы
CGContextFlush
CGContextSynchronize
QDFlushPortBuffer

Напр здесь говорят как грамотно флашить
https://developer.apple.com/library/mac/documentation/performance/Conceptual/Drawing/Articles/FlushingContent.html (https://developer.apple.com/library/mac/documentation/performance/Conceptual/Drawing/Articles/FlushingContent.html). Да, и кстати Widget::macCGHandle возвращает тот самый что нужен CG-вызовам. А на бздошном Вындоуз есть как минимум RedrawWindow, (т.е. repaint должен работать) ну ладно, с Вындоуз после

Вот только repaint вызывает немедленное обновление :)
Как уже говорили выше - на OSX нет


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 22, 2013, 15:59
Да хотя бы
Про это не знаю и углубляться не буду. Хотя я сильно сомневаюсь, что это вообще возможно в многозадачной среде.

А на бздошном Вындоуз есть как минимум RedrawWindow, (т.е. repaint должен работать) ну ладно, с Вындоуз после
А здесь венда будет посылать сообщения (причем не одно) и отрисовка будет работать в обработчике события.
В иксах также.



Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 22, 2013, 16:32
Хорошо, зайдем с др стороны: а как мне добиться получения paintEvent не трогая при этом др события ? 

Вызов update + processEvents вам не катит? или repaint? В чем отличие от мгновенной отрисовки ? В том, что отрисовка произойдет на полмс позже?


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 22, 2013, 17:47
Хотя я сильно сомневаюсь, что это вообще возможно в многозадачной среде.
Старое приложение это делает весьма непринужденно - причем как на OSX, так и на Вындоуз. Проблема в том как это в Qt впихнуть

Вызов update + processEvents вам не катит? или repaint? В чем отличие от мгновенной отрисовки ? В том, что отрисовка произойдет на полмс позже?
Просто никакой перерисовки не произойдет. Вот как делается сейчас (без Qt)
Код
C++ (Qt)
if (1) {
OldPainter op(win);
op.PaintRect(&R);
}   // здесь деструктор вытолкнет нарисованный Rect на экран
while (true) {
// здесь что-то делаем достаточно долго, напр неск секунд
}
Заменив OldPainter на QPainter мы получим ошибку - ведь этот код не внутри paintEvent. Придется так
Код
C++ (Qt)
PatchPaintParams(&R);   // надо как-то дать знать что делать внутри paintEvent
repaint();
while (true) {
...
 
При этом еще изрядно искромсав paintEvent. Это уже хреново - и это еще очень мягко сказано.
Но и это еще не все - repaint не сработает на OSX, а если "протолкнуть" его с помощью processEvents то др события будут обрабатываться, а на это код после while совсем не рассчитан.


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 22, 2013, 18:18
Старое приложение это делает весьма непринужденно - причем как на OSX, так и на Вындоуз.
И делает это в конечном итоге в обработчике событий аналогичном paintEvent.
Даже в таких библиотеках как SDL, где пользователю кажется, что он работает напрямую с окном, все происходит через события. Это спрятано внутри.

а на это код после while совсем не рассчитан.
Может это стоит исправить и дальше спокойно жить? :)


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 22, 2013, 18:46
Я тебя не понимаю
Просто никакой перерисовки не произойдет. Вот как делается сейчас (без Qt)

Вы сообщеньки читаете? паинтер МОЖЕТ рисовать на чем угодно в любое время, кроме виджетов. Нарисовав на буфере и отдав команду update, вы нарисуете на QImage и paintEvent отрисует этот QImage на виджете. Всё произойдет мгновенно и до while.

PS ну если не верите, сами попробуйте. Вы вот эту цитату написали не попробовав, на одном лишь своём мнении.


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 22, 2013, 19:09
И делает это в конечном итоге в обработчике событий аналогичном paintEvent.
Точно нет, напр такие вызовы есть в обработчиках мыши, клавы и др.

Может это стоит исправить и дальше спокойно жить? :)
Чужой старый код, Сколько всего таких мест - не знаю, найдя первые 10 считать перестал  :)

Полазил в отладчике QPainter::begin(). Есть флажок WA_OutsidePaintEvent, но он годится только чтобы заткнуть варнинги консоли. Самого рисования не происходит т.к. нет контекста (CGContextRef) - а он как раз извлекается из события рисования ОС. Подсунуть вроде можно. Поизучаю как создавать контекст нативными средствами  

Вы вот эту цитату написали не попробовав, на одном лишь своём мнении.
Сегодня утром неск раз перепроверил (хотя помнил и раньше). Уверяю Вас, при вызовах update/repaint ну совершенно ничего не происходит :'( И в исходниках есть комменты что на OSX это нормально. Заметим что сейчас в приложении рисование (что мы обсуждаем) происходит поверх старого/текущего, поэтому вариант с pixMap совершенно не привлекателен - где хранить все если простыня со скроллом? А валить все в paintEvent (см мой предыдущий пост) - проще застрелиться


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 22, 2013, 19:30
Точно нет, напр такие вызовы есть в обработчиках мыши, клавы и др.
Это не показатель. Все может рисоваться в теневые буферы и на реальный экран выбрасываться при поступлении сообщения от ОС.

Так исходники этой программы есть?
Возможно, она в качестве бекенда для отрисовки использует что-то типа opengl, directx или подобных технологий?
Одной RedrawWindow() дело не закончится, посмотрите ее описание и вы увидите упоминание о всех сообщениях, которые будут слаться главному окну и при обработке которых оно должно все рисовать.

поэтому вариант с pixMap совершенно не привлекателен - где хранить все если простыня со скроллом
С каким скроллом? :)
Backbuffer размером с окно (не больше и не меньше) и рисовать на него нужно как на обычное окно.


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 22, 2013, 19:58
Т.е. у вас OSX. Опять умолчанная информация ) Это не обвинение, а просто собираю портрет вашей программы :D

PS если так хотите заcтрелиться - в Qt как ни странно всё рисуется на QImage в paintEvent :)


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 22, 2013, 20:43
Так, ну бычит, правда "с использованием неповторимого местного диалекта" :) Исходник прилагаю, нативняк передрал из Qt. Если кто проверит на какаве (у меня стоит сборка Carbon) - буду благодарен. Если мака нет - см скриншот плюс мои уверения что paintEvent и pixMap полностью отсутствуют. Заметим что рисование не затирает предыдущее - как и требовалось.

На Вындоуз пока не знаю, но надеюсь что просто priv->hd = GetDC(..)  и потом конечно ReleaseDC(..)


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 22, 2013, 21:15
PS если так хотите заcтрелиться - в Qt как ни странно всё рисуется на QImage в paintEvent :)
Я тоже это слышал, и вот сейчас проверил на drawLine. Рисуется нативными вызовами в контексте  полученном из события рисования ОС (а не на QImage/QPixmap). Что есть тот контекст - личное дело ОС, во всяком случае с double-buffered точно не видео. Обобщать этот результат не стоит - конкретный ОС


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 22, 2013, 21:42
Обобщать этот результат не стоит - конкретный ОС
Точно. Платформопроблемы.
http://qt-project.org/faq/answer/how_does_qtwa_paintonscreen_relate_to_the_backing_store_widget_composition_


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 22, 2013, 22:46
Рад, что у вас всё получилось :)


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 23, 2013, 10:00
Рад, что у вас всё получилось :)
Ну и чего сидим, на Вындоуз не проверяем? (я недавно винт менял, поэтому даже MSVC не стоит). Там должно быть намного проще, см аттач. Ну отрихтуете что надо, хедерок подкинете.

Смысл простой - QPainter'у нужен контекст (HDC в Вындоуз)


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 23, 2013, 10:26
Ну и чего сидим, на Вындоуз не проверяем?
Если верить этому, то все должно получиться.
http://forum.vingrad.ru/forum/topic-256400.html

Но сохранится ли изображение если окно скрыть и показать или проехаться другим окном?


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 23, 2013, 11:33
Зачем что-то пробовать, если независимо в винде на image рисовать мона? Непонятно.


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 23, 2013, 12:01
Если верить этому, то все должно получиться.
http://forum.vingrad.ru/forum/topic-256400.html
Что на взятом GetDC можно рисовать нативняком сколько угодно - то ясно, но пройдет ли с QPainter?

Но сохранится ли изображение если окно скрыть и показать или проехаться другим окном?
Это рисование "до следующего paintEvent", поэтому если скрыть - все пропало. Если проехаться - то надо переключиться на др окно, но это повлечет paintEvent. Если окно сдвинуть вправо и кликнуть, то нарисованный текст будет за пределами экрана. Если теперь окно сдвинуть влево, то на OSX все норм, текст покажется т.к. сидит в буфере, но на Вындоуз нет, опять paintEvent.

Зачем что-то пробовать, если независимо в винде на image рисовать мона? Непонятно.
Это разные вещи, рисованием на image того же эффекта не достичь. Ну не надо так не надо.     


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 23, 2013, 12:11
Это рисование "до следующего paintEvent", поэтому если скрыть - все пропало.
Ну если такое поведение устраивает... рисовать одно и тоже в нескольких местах.


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 23, 2013, 12:25
Попробовал. Ничего не рисует.
QPainter::begin: Paint device returned engine == 0, type: 1

Не понял смысла в
Код:
if (1) {
QPainter painter(w);
QString txt = QString::number(++numCall) + " pick";
painter.drawLine(0, 0, 100, 100);
painter.drawText(pt, txt);
}
Ведь мы не внутри paintEvent, пейнтер никогда не даст разрешения.
Если брать DC, то и рисовать надо нативными функциями. Но тогда как и предсказывает Old будет "крайне ненадёжное рисование".


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 24, 2013, 17:01
Ведь мы не внутри paintEvent, пейнтер никогда не даст разрешения.
Если брать DC, то и рисовать надо нативными функциями. Но тогда как и предсказывает Old будет "крайне ненадёжное рисование".
И сразу какая-то паника, неумелый пересказ букваря и ссылка на старшего товарища :) Что значит "не даст", кто его спрашивает? Вариант для Вындоуз в аттаче, проверяем


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 24, 2013, 17:16
Проверить невозможно в виду версии Qt. Просто нет таких хедеров и методов :) (как я понял из пятой версии вы их тягаете.)

Не вижу смысла в ваших действиях... Приведи пример пожалуйста, для чего это может пригодиться? Чего нельзя сделать стандартными и понятными любому средствами Qt?

PS Из хлеба можно сделать троллейбус. Но зачем? Вы лезете в недра Qt, ломая систему и мешая следующему наследнику вашего кода шанса разобраться...

PPS смотря на ваш код видится мне, что при дальнейшем использовании будут проблемы. Но можно использовать если проект "окончательный" и никогда никуда не будет встроен. Ибо разобраться в получившемся аде будет сложновато :D


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 24, 2013, 17:53
Не вижу смысла в ваших действиях... Приведи пример пожалуйста, для чего это может пригодиться? Чего нельзя сделать стандартными и понятными любому средствами Qt?
Этот пример и был приведен в первом посте темы. Возможно Вас смутило незнакомое API, и Вы не поняли о чем речь (что впрочем не помешало Вам принять активное участие в обсуждении :)). Ладно, попробую объяснить проще. Есть старое (не Qt) приложение использующее такую технику
Код
C++ (Qt)
DrawSomething( Window * );   // нарисовать что-то в окне (с выводом на экран)
DoSomethingLong();            // какие-то длинные вычисления
 
Если у Вас есть предложения как сделать это "стандартными и понятными любому средствами Qt" - я их с удовольствием выслушаю. Если в очередной раз "рисуем на pixMap" - то сначала подумайте сами (хоть немного) во что это вольется.


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 24, 2013, 17:57
Понял что вы не читаете мои сообщения :D

PS если дочитали до сюда, ещё раз объясните чем рисование на системном фоне отличается от рисования на несистемном фоне pixmap в Windows?

Ваше первое сообщение уже давно "решено". В OSX так нельзя. В windows можно. Зачем лезть фиг знает куда?


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 24, 2013, 18:10
Есть старое (не Qt) приложение использующее такую технику
Теперь новое приложение что-то выведет на экран и пойдет что-то считать. В этот момент пользователь свернет/развернет окно этого приложения или переключится на другое окно - получим окно с артефактами.
Все что выводилось на экран "во всех местах" нужно сохранять, что бы потом штатно это рисовать в paintEvent.

Сейчас тот самый момент, когда "старую технику" нужно заменить новой. :)



Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 24, 2013, 19:48
Сейчас тот самый момент, когда "старую технику" нужно заменить новой. :)
Хотелось бы, но как это сделать? Поизучав старый код, вижу 2 типичных случая такого рисования

1) Просто-напросто перерисовать контрол(ы). Это связано с тем что используется старый синхронный подход
Код
C++ (Qt)
while (MouseDown()) {
 // здесь напр EditText должен показать новое значение
}
Он берет контекст и просто вызывает paint контрола сам. Да, в Вындоуз это решается через repaint, но решения для OSX я не нашел. А переделать все драги на событийную схему - нереально пока под Qt вообще не ходит

2) Подсветить что-то. Напр юзверь попал в айтем. Опять взял контекст, отрисовал напрямую именно этот айтем и обвел его рамочкой. Юзверь отпустил мышь - ну сделал inval(), пришел штатный paint, что айтем выбран он понимает, а о рамочке ничего не знает - ну так она и не нужна, мышь-то уже отпущена.

Перекрытие окна само по себе не опасно, т.к. double-buffer. А событие paint не придет пока не отдал управление. Все бычит.

ещё раз объясните чем рисование на системном фоне отличается от рисования на несистемном фоне pixmap в Windows?
Объяснить не могу т.к. без понятия что то за системный/несистемный фоны ??? Поверьте, все Ваши сообщения я прочитал и пытался рассматривать их конструктивно - но пока без особого успеха :) Прикрепляю маленький скриншот дабы показать что требуется   



Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 24, 2013, 20:44
Кхм. Я вас главное понял. Вопрос закрываем.

А конечная точка - да, на OSX решайте костылями.
На windows переписывайте нормально, с помощью paintEvent.

В OSX это неизбежное зло(как вывод этой темы), а в windows всё это просто реализуемо.


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 25, 2013, 08:57
... а в windows всё это просто реализуемо.
Тогда я попрошу Вас ответить за свои слова: воспроизведите скриншот из моего предыдущего поста - в принципе конечно, "пиксель в пиксель" не требуется


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 25, 2013, 10:33
Задачу приведите. Полную. Типа "чтобы рисовалась надпись в любой момент в нужном месте окна при нажатии мышкой".

А "воспроизвести скриншот" слишком расплывчатая задача, при реализации которой можно в любой момент сказать "а вот тут не вот так должно быть".


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 25, 2013, 12:25
Задачу приведите. Полную. Типа "чтобы рисовалась надпись в любой момент в нужном месте окна при нажатии мышкой".
Нормальная формулировка, только "нужное место" включает и занятое контролами (см скриншот). Платформа Вындоуз. Жду Вашего кода. Спасибо.


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 25, 2013, 17:52
https://drive.google.com/file/d/0B_mrvcleB88yZTVJMU9oLTlNYjg/edit?usp=sharing
С фильтрами мудрить не стал, нет времени на отладку, но мысль ясна я думаю.


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 26, 2013, 13:37
https://drive.google.com/file/d/0B_mrvcleB88yZTVJMU9oLTlNYjg/edit?usp=sharing
С фильтрами мудрить не стал, нет времени на отладку, но мысль ясна я думаю.
Занялись само-плагиатом, "накрытие виджета стеклом" - а еще есть емкий и хороший термин "layer". В этом нет ничего плохого, но в данном случае это явно не к месту. Создав виджет "сверху" Вы получили массу забот

- нужно следить чтобы он пропускал события через себя
- нужно следить чтобы он был все время самым верхним и покрывал все (напр при resize)
- нужно его зачищать а когда?
и.т.д.

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

Мое мнение - в данном случае надо подходить более принципиально/идейно. Рисование double-buffered, (пусть в одном случае средствами ОС, в др средствами Qt) - значит и надо рисовать прямо в буфере, если такая необходимость возникла. И неважно что там в букваре пишут. А пытаться решить это еще одним (triple) буфером - безыдейно и обречено на "ловлю блох" ("костыль" в молодежных терминах)

Ну ничего, ответили кодом - уже молодец  :)


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 26, 2013, 14:09
Кхм...
Цитировать
в данном случае это явно не к месту
1) Рисование "поверх" подразумевает наличие нескольких слоёв для контроля, собственно, рисования. Думаю вы лучше меня это знаете.

Цитировать
- нужно следить чтобы он пропускал события через себя
2) Достаточно модифицировать пример из Шлее или Бланшета (не помню точно у кого) для пропуска сообщений. Этот функционал я не сделал, ибо его нужно отлаживать, а времени не особо было.

Цитировать
- нужно следить чтобы он был все время самым верхним и покрывал все (напр при resize)
3)Как ни странно, следить "чтоб он был самым верхним" очень легко и просто - мы же следим за пропуском событий. Так что п.2 включает в себя п.3.

Цитировать
- нужно его зачищать а когда?
4) Зачищать когда хотите. Ибо вы получаете полную власть над слоем. Что угодно, хоть чёртиков рисуйте, хоть ангелов стирайте.

Цитировать
напр инвертировать участок окна Вы не сможете.
5) Могу. У меня есть картинка родителя. И у меня есть холст для рисования поверх. Далее уже дело техники.
Получить картинку, инвертировать цвета и нарисовать поверх - спокойно. Придётся часто обновлять в зависимости от области. Но это будет уже затратно и стоит задуматься "а оно нам надо?" ©.
В общем реализуемо, но малополезно.


Цитировать
более принципиально/идейно.
6) Предложите свой вариант вашего кода, который не будет зависеть от "ой окно скрылось и всё исчезло" или "перекрыло окном".


Цитировать
И по той же цитате.
7) Мы хотим рисовать под виджетом (сам виджет), на виджете (контролы) и над виджетом (поверхность). По здравому смыслу надо всё разделять, что мы и делаем, как благоразумные программисты.
3 сущности, как вы правильно и заметили. Мы же не дикари всё пихать в одну котомку.

Задача выполнена? Да. (возразите?)
Затратно? Нет.
Получили ещё один класс? Ради этого тема и была создана. Та малая толика, что он съест компенсируется выполнением задачи.

Само-плагиат? Ничего подобного. К тому же это один из рекомендованных разработчиками Qt способов рисования поверх виджета. Ссылку не приведу за давностью времени, но данная тема обсуждалась ещё на Qt 4.6+ на англицком языке. Тогда у меня руки не дошли попробовать.

Там предлагался ещё способ, я к сожалению не помню какой. Других способов "контролируемого" рисования поверх виджета пока нет.

PS кстати идейный подход вас не смущает смешиванием сущностей?

PPS ваш способ кстати использует хедеры Qt 5.* . Так что я пока не видел примера работающего кода.


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 26, 2013, 20:17
6) Предложите свой вариант вашего кода, который не будет зависеть от "ой окно скрылось и всё исчезло" или "перекрыло окном".
Пример как это работает
Код
C++ (Qt)
OldPainter painter(window);
Rect R = GetControlRect(comboBox);
for (int i = 0; i < 100; ++i) {
DoSomething(i);
painter.FillRect(&R, i);
}
Inval(&R);
 
Операция идет, прогресс виден - комбик последовательно заливается каким-то цветом. Сам комбик об этом без понятия - это может быть любой др контрол - или область окна. Хорошо, прилетело какое-то чужое окно, а потом скрылось - ну так на след итерации буфер окна опять отфлашится в видео, все норм. Вот все 100 итерации завершены, ушли на цикл событий, а там уже ждет paint который просто отрисует комбик - без всякой заливки которая уже не нужна.


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 26, 2013, 20:21
Ваш пример будет работать только при итеративной отрисовке с быстрыми "тиками", я так понимаю. В принципе тоже удобно, но только очень специфично.

В любом случае спасибо за "толчок" для написания фоновой рисовалки. Хотел попробовать что-то в этом духе года с 2011, но всё время откладывал и забывал :)

PS было интересно ^.^



Название: Re: Портирование рисования
Отправлено: kamre от Декабрь 26, 2013, 20:42
Вот все 100 итерации завершены, ушли на цикл событий, а там уже ждет paint который просто отрисует комбик - без всякой заливки которая уже не нужна.
А как во время итераций обрабатываются остальные события вроде нажатия на кнопку отмены текущей операции?


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 26, 2013, 21:11
Ваш пример будет работать только при итеративной отрисовке с быстрыми "тиками", я так понимаю.
Этот пример да, а вообще не только. Часто встречается ситуевина когда операция модальна/монопольна, напр юзверь схватил объект и тащит. Перерисовываться надо, но вот др события не должны извлекаться из очереди пока мыша не отпущена.

А как во время итераций обрабатываются остальные события вроде нажатия на кнопку отмены текущей операции?
Этого никто не отменял, и об этом я создал др топик  :)
http://www.prog.org.ru/index.php?topic=26251.msg187843#msg187843 (http://www.prog.org.ru/index.php?topic=26251.msg187843#msg187843)


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 26, 2013, 22:50
Часто встречается ситуевина когда операция модальна/монопольна, напр юзверь схватил объект и тащит. Перерисовываться надо, но вот др события не должны извлекаться из очереди пока мыша не отпущена.
Ох уж эти обобщения... "Часто встречается"... У кого часто встречается? Кому это надо? :)
Посмотрите как реализован DnD в том же Qt, там нет таких странных ограничений.
С какой стати сообщения не должны извлекаться и обрабатываться?


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 26, 2013, 23:11
Old, прошу вас, остановитесь :D Тема уже почти почти завершена :D


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 26, 2013, 23:47
Old, прошу вас, остановитесь :D Тема уже почти почти завершена :D
Правда интересно, почему нам непонятные требования пытаются выдать за само собой разумеющиеся. :)
В принципе, как всегда... но я не перестаю удивляться. :)


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 27, 2013, 13:55
Правда интересно, почему нам непонятные требования пытаются выдать за само собой разумеющиеся. :)
В принципе, как всегда... но я не перестаю удивляться. :)
"нам" - за всех не расписывайтесь :) Есть портируемое приложение которое делает вещи так, и наивно думать что все будет "так же как в Qt". Еще более наивно "следовать Qt примерам-образцам" пытаясь подогнать приложение под них.


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 27, 2013, 15:07
"нам" - за всех не расписывайтесь :)
А вы пишете для кого-то конкретно? Указывайте это, иначе вы пишете нам всем. :)

Есть портируемое приложение которое делает вещи так, и наивно думать что все будет "так же как в Qt".
Наивно называть приложение сделанное через жопу - "часто встречается". :)
Написали бы правду, не было бы моих комментариев.


Название: Re: Портирование рисования
Отправлено: Bepec от Декабрь 27, 2013, 15:15
Не буду холиварить, но поддержу Old.
Ибо если один у нас ходит кверх ногами, это не повод всех переучивать в принудительном порядке. Проще прописать этому "одному" лечебных процедур.

PS вы всегда можете скрыть реализацию от приложения. И только вы будете знать как жутко вы обманываете бедную и беззащитную программу.


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 27, 2013, 15:45
Наивно называть приложение сделанное через жопу - "часто встречается". :)
Написали бы правду, не было бы моих комментариев.
Ну вот Вы уже и грубите :) А что же плохого делает приложение? Конечно, рисовать так необязательно, но что в этом некорректного/неграмотного? Я лично ничего не нашел, в обоих используемых ОС это 100% легально. Хорошо, давайте "переделаем по Qt-шному", но никаких Ваших предложений я не видел. Чего ж теперь Вы жопу вспомнили?  :)


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 27, 2013, 15:51
А что же плохого делает приложение?
Причем здесь приложение?
Меня удивила формулировка "часто встречается" и "перерисовывать надо, а события обрабатывать нет".
Это абсурдные требования, которые вы решили представить как само собой разумеющиеся.
Именно это я прокомментировал.

Хорошо, давайте "переделаем по Qt-шному", но никаких Ваших предложений я не видел.
Никакого "Qt-шного" нет, это штатное рисование для большинства (если не всех) платформ.
Или на маках не нужно обрабатывать сообщение типа paintEvent?


Название: Re: Портирование рисования
Отправлено: Igors от Декабрь 27, 2013, 16:49
Меня удивила формулировка "часто встречается" и "перерисовывать надо, а события обрабатывать нет".
Это абсурдные требования, которые вы решили представить как само собой разумеющиеся.
Именно это я прокомментировал.
Почему абсурдные? Вот была API ф-ция WaitMouseUp, потом ее заменили на что-то типа TrackMouseLocation (не помню точно). Аналогичный ф-ционал есть на Вындоуз. В любом случае он позволяет разобраться с драгом до упора. При этом я могу лить в очередь события вызванные драгом. А разрешив обработку я попадаю в ситуацию когда событие пришло, но ничего сделать с ним нельзя (драг активен). Не говоря уже о том что размазывать контекст драга по неск событиям - дело муторное.

Даже чисто теоретически - вторичный цикл событий применять можно и нужно. И вторичный цикл имеет полное право интересоваться лишь небольшим числом событий. Так что нечего понты гнать и разлагать (активно подпевающую) молодежь  :)   


Название: Re: Портирование рисования
Отправлено: Old от Декабрь 27, 2013, 17:08
В любом случае он позволяет разобраться с драгом до упора.
Что значит "разобраться с драгом до упора"?

При этом я могу лить в очередь события вызванные драгом.
Очередь хороша как раз тем, что позволяет обрабатывать ассинхронно совсем не связанные друг с другом события.

А разрешив обработку я попадаю в ситуацию когда событие пришло, но ничего сделать с ним нельзя (драг активен).
Какое событие пришло и почему с ним сделать ничего нельзя?

Не говоря уже о том что размазывать контекст драга по неск событиям - дело муторное.
Мне даже страшно представить, что вы имеете ввиду.

Даже чисто теоретически - вторичный цикл событий применять можно и нужно.
Какой вторичный цикл? Для чего он нужен?

Так что нечего понты гнать и разлагать (активно подпевающую) молодежь  :)   
Понты гоните вы, своими абсурдными заявлениями типа "часто встречается".
А молодежь подпевает потому, что понимает абсурдность ваших заявлений. ;)



Название: Re: Портирование рисования
Отправлено: Igors от Февраль 23, 2014, 14:12
По поводу "так что же из этого вышло"

Хотя "асинхронное рисование" (вне paintEvent) и работает - счастья немного. Нет свободы действий. Напр начал рисовать асинхронно, получил контекст, создал QPainter, все вроде норм. НО я не могу звать processEvents т.к. получаю paintEvent когда контекст уже захвачен асинхронно. И эта ситуация тупиковая, ее не разрулить.

Пришлось все подгонять под paintEvent. Этому посвящено уже полтора месяца, сделано примерно 30%. Ну, бывает и так.