Редактирование: Transparent Backgrounds in Qt 4.1

Материал из Wiki.crossplatform.ru

Перейти к: навигация, поиск
Внимание: Вы не представились системе. Ваш IP-адрес будет записан в историю изменений этой страницы.
Правка может быть отменена. Пожалуйста, просмотрите сравнение версий, чтобы убедиться, что это именно те изменения, которые вас интересуют, и нажмите «Записать страницу», чтобы изменения вступили в силу.
Текущая версия Ваш текст
Строка 1: Строка 1:
-
{{Панель навигации по Qt Quarterly|Выпуск 16}}
+
{{menu_Qt_Издания}}
by Andreas Aardal Hanssen'''
by Andreas Aardal Hanssen'''
Строка 5: Строка 5:
Qt 4.1 radically improves widget drawing through its new "backing store", allowing semi-transparent (alpha-blended) child widgets and faster widget painting, as well as solving long-standing issues with nonrectangular widgets.
Qt 4.1 radically improves widget drawing through its new "backing store", allowing semi-transparent (alpha-blended) child widgets and faster widget painting, as well as solving long-standing issues with nonrectangular widgets.
-
__TOC__
+
*[[#thesystemsbackground | The System's Background]]
 +
*[[#contentspropagation | Contents Propagation]]
 +
*[[#newinqt41thebackingstore | New in Qt 4.1: The Backing Store]]
</blockquote>
</blockquote>
Строка 19: Строка 21:
To better understand what has changed in Qt 4.1, we will start by reviewing how backgrounds work in Qt 3.x and 4.0 and how to obtain child widget transparency. Much of this is still applicable in Qt 4.1, so read on!
To better understand what has changed in Qt 4.1, we will start by reviewing how backgrounds work in Qt 3.x and 4.0 and how to obtain child widget transparency. Much of this is still applicable in Qt 4.1, so read on!
-
 
+
<div id="thesystemsbackground"></div>
== The System's Background ==
== The System's Background ==
-
A widget represents a distinct region of desktop real estate in which we can paint shapes and colors. Widgets can be stacked on top of each other, and the topmost widget covers the widget underneath it. If a child widget covers half of its parent widget, the parent widget can only draw onto its own exposed areas (available as [[Qt:Документация_4.3.2/qpaintevent#region | QPaintEvent::region()]]). Painting operations on the child widgets are clipped away.
+
A widget represents a distinct region of desktop real estate in which we can paint shapes and colors. Widgets can be stacked on top of each other, and the topmost widget covers the widget underneath it. If a child widget covers half of its parent widget, the parent widget can only draw onto its own exposed areas (available as [[Qt:Документация_4.3.2/qpaintevent.php#region | QPaintEvent::region()]]). Painting operations on the child widgets are clipped away.
On all desktop platforms, a Qt widget is also an independent object known to the window system. By default, the system provides a background based on the widget's background role and palette, which is used whenever a new area of the widget is shown for the first time.
On all desktop platforms, a Qt widget is also an independent object known to the window system. By default, the system provides a background based on the widget's background role and palette, which is used whenever a new area of the widget is shown for the first time.
-
For example, the background role of a [[Qt:Документация_4.3.2/qlabel | QLabel]] is [[Qt:Документация_4.3.2/qpalette#ColorRole-enum | QPalette::Background]], which traditionally corresponds to a gray color in the palette; for a [[Qt:Документация_4.3.2/qlineedit | QLineEdit]], the background role is [[Qt:Документация_4.3.2/qpalette#ColorRole-enum | QPalette::Base]], which is usually white.
+
For example, the background role of a [[Qt:Документация_4.3.2/qlabel | QLabel]] is [[Qt:Документация_4.3.2/qpalette.php#ColorRole-enum QPalette::Background]], which traditionally corresponds to a gray color in the palette; for a [[Qt:Документация_4.3.2/qlineedit | QLineEdit]], the background role is [[Qt:Документация_4.3.2/qpalette.php#ColorRole-enum | QPalette::Base]], which is usually white.
If we call <tt>update()</tt> or <tt>repaint()</tt> to repaint a widget, Qt automatically erases the widget using the background color, relieving us from painting all the widget's pixels. This is very convenient, but it comes at a price:
If we call <tt>update()</tt> or <tt>repaint()</tt> to repaint a widget, Qt automatically erases the widget using the background color, relieving us from painting all the widget's pixels. This is very convenient, but it comes at a price:
Строка 38: Строка 40:
In <tt>paintEvent()</tt>, we could now get away with drawing only the foreground. If we don't draw anything in <tt>paintEvent()</tt>, the widget will be totally white (or whatever color or brush <tt>Base</tt> stands for). Without having to draw anything, we can alter the widget's background color by changing the palette or setting a different background role.
In <tt>paintEvent()</tt>, we could now get away with drawing only the foreground. If we don't draw anything in <tt>paintEvent()</tt>, the widget will be totally white (or whatever color or brush <tt>Base</tt> stands for). Without having to draw anything, we can alter the widget's background color by changing the palette or setting a different background role.
-
If <tt>paintEvent()</tt> paints all the widget's pixels, we can tell Qt not to erase the widget (or the pixmap) with the background color by setting the [http://doc.trolltech.com/3.3/qt.html#WidgetFlags-enum Qt::WNoAutoErase] (Qt 3) or [[Qt:Документация_4.3.2/qt#WidgetAttribute-enum | Qt::WA_NoBackground]] (Qt 4) flag. In Qt 3, this is a common anti-flicker technique; in Qt 4, this is a minor speed optimization.
+
If <tt>paintEvent()</tt> paints all the widget's pixels, we can tell Qt not to erase the widget (or the pixmap) with the background color by setting the [http://doc.trolltech.com/3.3/qt.php#WidgetFlags-enum Qt::WNoAutoErase] (Qt 3) or [[Qt:Документация_4.3.2/qt.php#WidgetAttribute-enum | Qt::WA_NoBackground]] (Qt 4) flag. In Qt 3, this is a common anti-flicker technique; in Qt 4, this is a minor speed optimization.
-
As a further optimization, we can also disable the window system background by calling [http://doc.trolltech.com/3.3/qwidget.html#setBackgroundMode setBackgroundMode(Qt::NoBackground)] (Qt 3) or [[Qt:Документация_4.3.2/qwidget#setAttribute | setAttribute(Qt::NoSystemBackground)]] (Qt 4). Now, the widget is truly uninitialized, and if we don't paint all the pixels in <tt>paintEvent()</tt>, we can see some interesting "artwork" as we move the window around.
+
As a further optimization, we can also disable the window system background by calling [http://doc.trolltech.com/3.3/qwidget.php#setBackgroundMode setBackgroundMode(Qt::NoBackground)] (Qt 3) or [[Qt:Документация_4.3.2/qwidget.php#setAttribute | setAttribute(Qt::NoSystemBackground)]] (Qt 4). Now, the widget is truly uninitialized, and if we don't paint all the pixels in <tt>paintEvent()</tt>, we can see some interesting "artwork" as we move the window around.
 +
<div id="contentspropagation"></div>
== Contents Propagation ==
== Contents Propagation ==
Строка 51: Строка 54:
* If the parent doesn't paint anything underneath the child widget other than its background, you can fill the child widget's background by inheriting the parent widget's brush and applying a suitable offset by calling [http://doc.trolltech.com/3.3/qwidget.html QWidget]::setBackgroundOrigin().
* If the parent doesn't paint anything underneath the child widget other than its background, you can fill the child widget's background by inheriting the parent widget's brush and applying a suitable offset by calling [http://doc.trolltech.com/3.3/qwidget.html QWidget]::setBackgroundOrigin().
-
Although Qt 3 doesn't support semi-transparency for widgets, we can simulate it using [http://doc.trolltech.com/3.3/qimage.html   QImage] if necessary.
+
Although Qt 3 doesn't support semi-transparency for widgets, we can simulate it using [http://doc.trolltech.com/3.3/qimage  QImage] if necessary.
<div style="margin: 1em; float: right; background: #9C9CFF; padding: 2px; width: 40%">
<div style="margin: 1em; float: right; background: #9C9CFF; padding: 2px; width: 40%">
Строка 65: Строка 68:
No matter which approach is taken, contents propagation takes its toll on the application's performance. Exposing a child widget will trigger a repaint for the parent widget. For complex hierarchies, the results can be unbearably slow. For every region with ''n'' overlapping widgets, the bottommost widget gets ''n'' repaints, and for every repaint we may have layouts, font metrics, clipping, and perhaps some complex operations such as an image-to-pixmap conversion or gradient generation. Contents propagation can result in ''n''І paint events, even for the simplest widget exposures.
No matter which approach is taken, contents propagation takes its toll on the application's performance. Exposing a child widget will trigger a repaint for the parent widget. For complex hierarchies, the results can be unbearably slow. For every region with ''n'' overlapping widgets, the bottommost widget gets ''n'' repaints, and for every repaint we may have layouts, font metrics, clipping, and perhaps some complex operations such as an image-to-pixmap conversion or gradient generation. Contents propagation can result in ''n''І paint events, even for the simplest widget exposures.
-
If two semi-transparent widgets overlap (e.g., a semi-transparent rubber band covers a semi-transparent graph widget background), things get even worse. Because of this, [[Qt:Документация_4.3.2/qt#WidgetAttribute-enum |Qt::WA_ContentsPropagated]] in Qt 4.0 does not support overlapping siblings.
+
If two semi-transparent widgets overlap (e.g., a semi-transparent rubber band covers a semi-transparent graph widget background), things get even worse. Because of this, [[Qt:Документация_4.3.2/qt.php#WidgetAttribute-enum |Qt::WA_ContentsPropagated]] in Qt 4.0 does not support overlapping siblings.
-
 
+
== New in Qt 4.1: The Backing Store ==
== New in Qt 4.1: The Backing Store ==
Строка 85: Строка 87:
How does all of this affect widget backgrounds? Here's a list of the most significant changes in 4.1:  
How does all of this affect widget backgrounds? Here's a list of the most significant changes in 4.1:  
-
*[[Qt:Документация_4.3.2/qpalette#ColorRole-enum | QPalette::Background]] has been renamed [[Qt:Документация_4.3.2/qpalette#ColorRole-enum | QPalette::Window]] to avoid the confusion between [[Qt:Документация_4.3.2/qwidget | QWidget]]'s [[Qt:Документация_4.3.2/qwidget#backgroundRole-prop | backgroundRole]] property and [[Qt:Документация_4.3.2/qpalette | QPalette]]'s [[Qt:Документация_4.3.2/qpalette#ColorRole-enum | Background]] role. Similarly, [[Qt:Документация_4.3.2/qpalette#ColorRole-enum | QPalette::Foreground]] has been renamed [[Qt:Документация_4.3.2/qpalette#ColorRole-enum | QPalette::WindowText]].
+
*[[Qt:Документация_4.3.2/qpalette#ColorRole-enum | QPalette::Background]] has been renamed [[Qt:Документация_4.3.2/qpalette.php#ColorRole-enum | QPalette::Window]] to avoid the confusion between [[Qt:Документация_4.3.2/qwidget | QWidget]]'s [[Qt:Документация_4.3.2/qwidget.php#backgroundRole-prop | backgroundRole]] property and [[Qt:Документация_4.3.2/qpalette | QPalette]]'s [[Qt:Документация_4.3.2/qpalette#ColorRole-enum | Background]] role. Similarly, [[Qt:Документация_4.3.2/qpalette#ColorRole-enum | QPalette::Foreground]] has been renamed [[Qt:Документация_4.3.2/qpalette.php#ColorRole-enum | QPalette::WindowText]].
-
*Window backgrounds are now initialized with the [[Qt:Документация_4.3.2/qpalette#ColorRole-enum | QPalette::Window]] brush. All child widgets are by default "transparent"; Qt doesn't fill the widget for us. Because of this, painting with an alpha color can now be done directly in <tt>paintEvent()</tt>.
+
*Window backgrounds are now initialized with the [[Qt:Документация_4.3.2/qpalette.php#ColorRole-enum | QPalette::Window]] brush. All child widgets are by default "transparent"; Qt doesn't fill the widget for us. Because of this, painting with an alpha color can now be done directly in <tt>paintEvent()</tt>.
-
*[[Qt:Документация_4.3.2/qwidget | QWidget]] has a new property called [[Qt:Документация_4.3.2/qwidget#autoFillBackground-prop | autoFillBackground]], which is <tt>false</tt> by default. Setting this to <tt>true</tt> will give your custom widgets the same background behavior that they had in Qt 4.0.
+
*[[Qt:Документация_4.3.2/qwidget | QWidget]] has a new property called [[Qt:Документация_4.3.2/qwidget.php#autoFillBackground-prop | autoFillBackground]], which is <tt>false</tt> by default. Setting this to <tt>true</tt> will give your custom widgets the same background behavior that they had in Qt 4.0.
-
*[[Qt:Документация_4.3.2/qt#WidgetAttribute-enum | Qt::WA_NoBackground]] is now called [[Qt:Документация_4.3.2/qt#WidgetAttribute-enum | Qt::WA_OpaquePaintEvent]], with the same meaning as before. By setting this option, you provide Qt with a guarantee that you will paint ''all'' the pixels in your paint event with non-transparent colors. (If you set [[Qt:Документация_4.3.2/qt#WidgetAttribute-enum | Qt::WA_OpaquePaintEvent]], or enable [[Qt:Документация_4.3.2/qwidget#autoFillBackground-prop | QWidget::autoFillBackground]] and use an opaque background brush, Qt won't need to recompose the background. This will improve the rendering speed of your widgets significantly.)
+
*[[Qt:Документация_4.3.2/qt.php#WidgetAttribute-enum | Qt::WA_NoBackground]] is now called [[Qt:Документация_4.3.2/qt.php#WidgetAttribute-enum | Qt::WA_OpaquePaintEvent]], with the same meaning as before. By setting this option, you provide Qt with a guarantee that you will paint ''all'' the pixels in your paint event with non-transparent colors. (If you set [[Qt:Документация_4.3.2/qt.php#WidgetAttribute-enum | Qt::WA_OpaquePaintEvent]], or enable [[Qt:Документация_4.3.2/qwidget.php#autoFillBackground-prop | QWidget::autoFillBackground]] and use an opaque background brush, Qt won't need to recompose the background. This will improve the rendering speed of your widgets significantly.)
-
*[[Qt:Документация_4.3.2/qt#WidgetAttribute-enum | Qt::WA_ContentsPropagated]] has become superfluous, because each widget's contents are now propagated by default.
+
*[[Qt:Документация_4.3.2/qt.php#WidgetAttribute-enum | Qt::WA_ContentsPropagated]] has become superfluous, because each widget's contents are now propagated by default.
In some very rare cases, the change might affect the semantics of existing programs. If one of your custom widgets goes transparent, calling <tt>setAutoFillBackground(true)</tt> on the widget will fix the problem.
In some very rare cases, the change might affect the semantics of existing programs. If one of your custom widgets goes transparent, calling <tt>setAutoFillBackground(true)</tt> on the widget will fix the problem.
Строка 98: Строка 100:
|}
|}
-
The potential for performance using the backing store architecture is far beyond what we had before. What's more, our users now have the option of writing modern widgets that stand out from the competition, on all platforms, without requiring advanced graphics support on their deployed platforms (such as XRender on X11). See the [[Fading Effects with Qt 4.1]] article for a real-world application of semi-transparent child widgets.
+
The potential for performance using the backing store architecture is far beyond what we had before. What's more, our users now have the option of writing modern widgets that stand out from the competition, on all platforms, without requiring advanced graphics support on their deployed platforms (such as XRender on X11). See the [http://crossplatform.ru/?q=node/290 Fading Effects with Qt 4.1] article for a real-world application of semi-transparent child widgets.
With Qt 4.1, you can now use [[Qt:Документация_4.3.2/qpainter | QPainter]] to its full potential, with semi-transparent backgrounds and antialiased curves blended against the parent widget's background. And it won't just work on Mac OS X and Windows 2000 or better. It will work on all platforms, which is exactly what you'd expect from your favorite cross-platform GUI framework.
With Qt 4.1, you can now use [[Qt:Документация_4.3.2/qpainter | QPainter]] to its full potential, with semi-transparent backgrounds and antialiased curves blended against the parent widget's background. And it won't just work on Mac OS X and Windows 2000 or better. It will work on all platforms, which is exactly what you'd expect from your favorite cross-platform GUI framework.
-
'''Note: More information about contents propagation and child widget transparency can be found in the [[Qt:Документация_4.3.2/qwidget#transparency-and-double-buffering | Transparency and Double Buffering section of the QWidget documentation]]'''.
+
'''Note: More information about contents propagation and child widget transparency can be found in the [[Qt:Документация_4.3.2/qwidget.php#transparency-and-double-buffering | Transparency and Double Buffering section of the QWidget documentation]]'''.
<hr align="center" width="25%" />
<hr align="center" width="25%" />
<div id="fn1"></div><sup>[1]</sup>
<div id="fn1"></div><sup>[1]</sup>
In Qt 4, this is not an issue because of double-buffering. When we paint on a widget, we're actually drawing on a pixmap that will be copied to the screen.
In Qt 4, this is not an issue because of double-buffering. When we paint on a widget, we're actually drawing on a pixmap that will be copied to the screen.

Пожалуйста, обратите внимание, что все ваши добавления могут быть отредактированы или удалены другими участниками. Если вы не хотите, чтобы кто-либо изменял ваши тексты, не помещайте их сюда.
Вы также подтверждаете, что являетесь автором вносимых дополнений, или скопировали их из источника, допускающего свободное распространение и изменение своего содержимого (см. Wiki.crossplatform.ru:Авторское право). НЕ РАЗМЕЩАЙТЕ БЕЗ РАЗРЕШЕНИЯ ОХРАНЯЕМЫЕ АВТОРСКИМ ПРАВОМ МАТЕРИАЛЫ!


Шаблоны, использованные на текущей версии страницы: