Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: 0x0001 от Март 08, 2010, 01:26



Название: Как сделать нестандартный вид
Отправлено: 0x0001 от Март 08, 2010, 01:26
не моу понять,
1. как в QT установить произвольную форму Региона окна(кнопки), (Типа MFC: CWnd::SetWindowRgn (mRgn))
2. как в QT устанавливать произвольные картинки(вид) на кнопках, окнах? в MFC я использовал массивы BMP в контексте DC: BtnDC DCBMP[n];, а далее подгружал по OnPain() нужный BMP в зависимости от статуса....

Код:
//Windows CREATE:
SetWindowRgn(BtnRgn,true);//Устанавливаю нужный Регион окна (например, овальное окно)
//WM_PAINT:
BitBlt(hDC,0,0,xsize,ysize,BtnDC[BtnStat],0,0,SRCCOPY);//изображение в контекст окна


Название: Re: Как сделать нестандартный вид
Отправлено: hackoff от Март 08, 2010, 08:27
БХВ - Qt4. Профессиональное программирование на C++.2007
стр 375


Название: Re: Как сделать нестандартный вид
Отправлено: 0x0001 от Март 08, 2010, 12:02
О! Спасибо про это Книгу!

QRegion
QPainter
Qimage


Название: Re: Как сделать нестандартный вид
Отправлено: BRE от Март 08, 2010, 12:06
QPainter
Qimage
Для быстрого рисования картинок лучше использовать QPixmap, вместо QImage.


Название: Re: Как сделать нестандартный вид
Отправлено: SABROG от Март 08, 2010, 13:09
QPainter
Qimage
Для быстрого рисования картинок лучше использовать QPixmap, вместо QImage.

В большинстве случаев это правда. Мне известен только один случай, когда может быть медленней. Если X Server находится на удаленной машине.


Название: Re: Как сделать нестандартный вид
Отправлено: BRE от Март 08, 2010, 13:18
В большинстве случаев это правда. Мне известен только один случай, когда может быть медленней. Если X Server находится на удаленной машине.
::)

У меня прямо камень с души упал, а то я все думал не наврал ли я...


Название: Re: Как сделать нестандартный вид
Отправлено: SABROG от Март 08, 2010, 13:41
::)

У меня прямо камень с души упал, а то я все думал не наврал ли я...

 :D мало ли там чего человек писать собрался, пусть хотя бы знает, что это не панацея. Особенно критичной ситуация может стать при частом конвертировании QImage в QPixmap и наоборот. Но это опять же если X Server не на локальной машине.


Название: Re: Как сделать нестандартный вид
Отправлено: waster от Март 08, 2010, 17:07
На Мак-платформе и в случае Carbon-сборки Qt лучше всё-таки использовать QPixmap, т.к. в этом случае CGImageRef получается напрямую из внутреннего буфера QPixmap'а. Если не забыть заранее подгрузить все QPixmap'ы через QPixmapCache, то в рендеринге всё работает достаточно быстро даже на Mac mini.

Но в любом случае только с QImage получится использовать image composition modes.


Название: Re: Как сделать нестандартный вид
Отправлено: waster от Март 08, 2010, 17:09
Ну и чаще всего гораздо удобнее рисовать самому, переопределив метод QPaintEvent(), т.к. это позволяет делать очень сильно кастомизированные интерфейсы, и особенно помогает, если при 90% готовности кода нужно добавить один пиксел в UI.

Альтернативы: QStyle, Qt Style Sheets и стандартные лайоуты либо недостаточно гибкие для этого, либо глючные, либо тормозные, либо всё сразу.


Название: Re: Как сделать нестандартный вид
Отправлено: waster от Март 08, 2010, 17:17
Теперь по регионам.

SetWindowRgn - в Qt это setMask или класс QRegion.

Здесь надо различать две ситуации: виджет top-level window или чей-то child.

Если child, то Qt всё делает автоматически сама: где прозрачная (или полупрозрачная) дырка в картинке, которую рисует виджет из своего paintEvent'а - там эта дырка так и останется. Возможно, лишь дополнительно придётся поставить маску для кликов, если это какой-нибудь заметно круглый контрол.

С top level window всё куда хуже.

Маски на момент версии 4.5.2 - однобитные (это означает, что антиалиайзинга не добьёшься). Там куча глюков и сильная просада производительности для непрямоугольных окон. Нельзя сделать часть окна одновременно 100% прозрачным и кликабельным в ту же дырку. И многое другое...


Название: Re: Как сделать нестандартный вид
Отправлено: GreatSnake от Март 11, 2010, 09:41
С top level window всё куда хуже.

Маски на момент версии 4.5.2 - однобитные (это означает, что антиалиайзинга не добьёшься). Там куча глюков и сильная просада производительности для непрямоугольных окон. Нельзя сделать часть окна одновременно 100% прозрачным и кликабельным в ту же дырку. И многое другое...
Под X11 для этого используется XShapeExtension, который использует однобитные маски. Т.е. Qt тут не причем.

Насчёт QPixmap vs. QImage...
QPixmap тяжелый ресурс и выделяется на стороне Xserver-а (X11) или ядра (win/GDI). QImage выделяется в памяти процесса.
К тому же в Qt4.x весь GUI рендеринг делается через double-buffering, который делается через QImage.
Т.е. иконка созданная в QPixmap-e в любом случае будет копироваться в QImage, а уже финальный QImage будет копироваться в окно виджета.


Название: Re: Как сделать нестандартный вид
Отправлено: BRE от Март 11, 2010, 10:22
Насчёт QPixmap vs. QImage...
QPixmap тяжелый ресурс и выделяется на стороне Xserver-а (X11) или ядра (win/GDI). QImage выделяется в памяти процесса.
К тому же в Qt4.x весь GUI рендеринг делается через double-buffering, который делается через QImage.
Т.е. иконка созданная в QPixmap-e в любом случае будет копироваться в QImage, а уже финальный QImage будет копироваться в окно виджета.
Т.е. по твоему получается, что QPixmap не ускоряет вывод, а даже замедляет его? Ведь приходиться дополнительно конвертировать формат изображение QPixmap для помещения в QImage.
А как быть с аппаратным 2D-ускорением? Как его можно задействовать при рендеринге в память?
Сравнивал ли ты скорость отрисовки QPixmap и QImage?
Если посмотреть исходники Qt на предмет того, что там используется для отрисовки, то почти везде для формирования используется QPixmap, а не QImage.


Название: Re: Как сделать нестандартный вид
Отправлено: GreatSnake от Март 11, 2010, 10:46
Цитировать
Т.е. по твоему получается, что QPixmap не ускоряет вывод, а даже замедляет его?
Это где это я такое говорил?
Я просто сказал, что QPixmap тяжелый ресурс. Известны случаи, когда у GDI съезжала крыша при большом количестве созданных pixmap-ов.
Конечно, QPixmap, находящийся в памати Xserver-a/GDI отрисуется намного быстрее, чем QImage находящийся в памяти процесса.
Цитировать
А как быть с аппаратным 2D-ускорением? Как его можно задействовать при рендеринге в память?
А вот это для меня большой вопрос. Задействована ли 2D акселерация в Qt4.x вообще.
Цитировать
Если посмотреть исходники Qt на предмет того, что там используется для отрисовки, то почти везде для формирования используется QPixmap, а не QImage.
Я боюсь, что исходники вы смотрели невнимательно. Если сидите на X-ах, то под отладчиком поставьте breakpoint на XPutImage и всё сами увидите.


Название: Re: Как сделать нестандартный вид
Отправлено: BRE от Март 11, 2010, 11:03
Это где это я такое говорил?
Я сделал такой вывод, по тому как ты это написал...  ;)

Конечно, QPixmap, находящийся в памати Xserver-a/GDI отрисуется намного быстрее, чем QImage находящийся в памяти процесса.
Так что же лучше использовать для быстрой отрисовки?

Я боюсь, что исходники вы смотрели невнимательно. Если сидите на X-ах, то под отладчиком поставьте breakpoint на XPutImage и всё сами увидите.
А если breakpoint поставить на XRenderComposite?


Название: Re: Как сделать нестандартный вид
Отправлено: GreatSnake от Март 11, 2010, 12:07
Покопавшись ещё раз в исходниках Qt понял следующее.

Для каждого top-level окна создается QWidgetBackingStore класс, в котором создается QWindowSurface класс
и уже в нём создается off-screen pixmap соответствующий размеру top-level окна. Этот pixmap при изменении размера окна _всегда_ пересоздается, т.к. pixmaps не могут динамически менять размер.
XRenderComposite() в основном используется для рендеринга статических текстур.
Отрисовка всех drawPrimitivies делается через QImage с последующим копированием в off-screen pixmap.

Вообщем визуально всё это выглядит конечно красиво, но ожидать мега скорости от такого подхода не стоит - за всё нужно платить :(


Название: Re: Как сделать нестандартный вид
Отправлено: BRE от Март 11, 2010, 15:14
Вот поэтому, как мне кажется, и нужно использовать QPixmap.
Например, есть виджет состоящий из фоновой статической картинки и, не знаю, нескольких лампочек.
Фоновую картину мы может формировать при изменении размеров виджета (первый QPixmap), один раз.
Лампочки мы может перерисовывать при изменении их состояний (один или несколько других QPixmap), один раз на изменение.
А перерисовывать весь виджет мы можем быстро выводя эти пиксмапы друг на друга. Копирование будет обеспечивать XWindow/GDI на максимальной для архитектуры скорости.


Название: Re: Как сделать нестандартный вид
Отправлено: GreatSnake от Март 11, 2010, 15:28
Согласен, но если требуется composing, то этот номер не пройдёт.