1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
|
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Free Documentation License
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of this
** file.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\group appearance
\title Widget Appearance and Style
\brief Classes used for customizing UI appearance and style.
*/
/*!
\page style-reference.html
\title Styles and Style Aware Widgets
\ingroup qt-gui-concepts
\brief Styles and the styling of widgets.
Styles (classes that inherit QStyle) draw on behalf of widgets
and encapsulate the look and feel of a GUI. The QStyle class is
an abstract base class that encapsulates the look and feel of a
GUI. Qt's built-in widgets use it to perform nearly all of their
drawing, ensuring that they look exactly like the equivalent
native widgets.
Several styles are built into Qt (e.g., windows style and motif style).
Other styles are only available on specific platforms (such as
the windows XP style). Custom styles are made available as plugins
or by creating an instance of the style class in an application and
setting it with QApplication::setStyle().
To implement a new style, you inherit one of Qt's existing styles
- the one most resembling the style you want to create - and
reimplement a few virtual functions. This process is somewhat
involved, and we therefore provide this overview. We give a
step-by-step walkthrough of how to style individual Qt widgets.
We will examine the QStyle virtual functions, member variables,
and enumerations.
The part of this document that does not concern the styling of
individual widgets is meant to be read sequentially because later
sections tend to depend on earlier ones. The description of the
widgets can be used for reference while implementing a style.
However, you may need to consult the Qt source code in some cases.
The sequence in the styling process should become clear after
reading this document, which will aid you in locating relevant code.
To develop style aware widgets (i.e., widgets that conform to
the style in which they are drawn), you need to draw them using the
current style. This document shows how widgets draw themselves
and which possibilities the style gives them.
\section1 Classes for Widget Styling
These classes are used to customize an application's appearance and
style.
\annotatedlist appearance
\section1 The QStyle implementation
The API of QStyle contains functions that draw the widgets, static
helper functions to do common and difficult tasks (e.g.,
calculating the position of slider handles) and functions to do
the various calculations necessary while drawing (e.g., for the
widgets to calculate their size hints). The style also help some
widgets with the layout of their contents. In addition, it creates
a QPalette that contains \l{QBrush}es to draw with.
QStyle draws graphical elements; an element is a widget or a
widget part like a push button bevel, a window frame, or a scroll
bar. Most draw functions now take four arguments:
\list
\o an enum value specifying which graphical element to draw
\o a QStyleOption specifying how and where to render that element
\o a QPainter that should be used to draw the element
\o a QWidget on which the drawing is performed (optional)
\endlist
When a widget asks a style to draw an element, it provides the style
with a QStyleOption, which is a class that contains the information
necessary for drawing. Thanks to QStyleOption, it is possible to make
QStyle draw widgets without linking in any code for the widget. This
makes it possible to use \l{QStyle}'s draw functions on any paint
device, i.e., you can draw a combobox on any widget, not just on a
QComboBox.
The widget is passed as the last argument in case the style needs
it to perform special effects (such as animated default buttons on
Mac OS X), but it isn't mandatory.
We will in the course of this section look at the style elements,
the style options, and the functions of QStyle. Finally, we describe
how the palette is used.
Items in item views is drawn by \l{Delegate Classes}{delegates} in
Qt. The item view headers are still drawn by the style. Qt's
default delegate, QStyledItemDelegate, draws its items partially
through the current style; it draws the check box indicators and
calculate bounding rectangles for the elements of which the item
consists. In this document, we only describe how to implement a
QStyle subclass. If you wish to add support for other datatypes
than those supported by the QStyledItemDelegate, you need to
implement a custom delegate. Note that delegates must be set
programmatically for each individual widget (i.e., default
delegates cannot be provided as plugins).
\section2 The Style Elements
A style element is a graphical part of a GUI. A widget consists
of a hierarchy (or tree) of style elements. For instance, when a
style receives a request to draw a push button (from QPushButton,
for example), it draws a label (text and icon), a button bevel,
and a focus frame. The button bevel, in turn, consists of a frame
around the bevel and two other elements, which we will look at
later. Below is a conceptual illustration of the push button
element tree. We will see the actual tree for QPushButton when we
go through the individual widgets.
\image javastyle/conceptualpushbuttontree.png
Widgets are not necessarily drawn by asking the style to draw
only one element. Widgets can make several calls to the style to
draw different elements. An example is QTabWidget, which draws its
tabs and frame individually.
There are three element types: primitive elements, control
elements, and complex control elements. The elements are defined
by the \l{QStyle::}{ComplexControl}, \l{QStyle::}{ControlElement},
and \l{QStyle::}{PrimitiveElement} enums. The values of
each element enum has a prefix to identify their type: \c{CC_} for
complex elements, \c{CE_} for control elements, and \c{PE_} for
primitive elements. We will in the following three sections see what
defines the different elements and see examples of widgets that use
them.
The QStyle class description contains a list of these elements and
their roles in styling widgets. We will see how they are used when
we style individual widgets.
\section3 Primitive Elements
Primitive elements are GUI elements that are common and often used
by several widgets. Examples of these are frames, button bevels,
and arrows for spin boxes, scroll bars, and combo boxes.
Primitive elements cannot exist on their own: they are always part
of a larger construct. They take no part in the interaction with
the user, but are passive decorations in the GUI.
\section3 Control Elements
A control element performs an action or displays information
to the user. Examples of control elements are push buttons, check
boxes, and header sections in tables and tree views. Control
elements are not necessarily complete widgets such as push
buttons, but can also be widget parts such as tab bar tabs and
scroll bar sliders. They differ from primitive elements in that
they are not passive, but fill a function in the interaction with
the user. Controls that consist of several elements often use the
style to calculate the bounding rectangles of the elements. The
available sub elements are defined by the \l{QStyle::}{SubElement}
enum. This enum is only used for calculating bounding rectangles,
and sub elements are as such not graphical elements to be drawn
like primitive, control, and complex elements.
\section3 Complex Control Elements
Complex control elements contain sub controls. Complex controls
behave differently depending on where the user handles them with
the mouse and which keyboard keys are pressed. This is dependent
on which sub control (if any) that the mouse is over or received a
mouse press. Examples of complex controls are scroll bars and
combo boxes. With a scroll bar, you can use the mouse to move the
slider and press the line up and line down buttons. The available
sub controls are defined by the \l{QStyle}{SubControl} enum.
In addition to drawing, the style needs to provide the widgets
with information on which sub control (if any) a mouse press was
made on. For instance, a QScrollBar needs to know if the user
pressed the slider, the slider groove, or one of the buttons.
Note that sub controls are not the same as the control elements
described in the previous section. You cannot use the style to
draw a sub control; the style will only calculate the bounding
rectangle in which the sub control should be drawn. It is common,
though, that complex elements use control and primitive elements
to draw their sub controls, which is an approach that is
frequently used by the built-in styles in Qt and also the Java
style. For instance, the Java style uses PE_IndicatorCheckBox to
draw the check box in group boxes (which is a sub control of
CC_GroupBox). Some sub controls have an equivalent control element,
e.g., the scroll bar slider (SC_SCrollBarSlider and
CE_ScrollBarSlider).
\section3 Other QStyle Tasks
The style elements and widgets, as mentioned, use the style to
calculate bounding rectangles of sub elements and sub controls,
and pixel metrics, which is a style dependent size in screen
pixels, for measures when drawing. The available rectangles and
pixel metrics are represented by three enums in QStyle:
\l{QStyle::}{SubElement}, \l{QStyle::}{SubControl}, and
\l{QStyle::}{PixelMetric}. Values of the enums can easily by
identified as they start with SE_, SC_ and PM_.
The style also contain a set of style hints, which is
represented as values in the \l{QStyle::}{StyleHint} enum. All
widgets do not have the same functionality and look in the
different styles. For instance, when the menu items in a menu do not
fit in a single column on the screen, some styles support
scrolling while others draw more than one column to fit all items.
A style usually has a set of standard images (such as a warning, a
question, and an error image) for message boxes, file dialogs,
etc. QStyle provides the \l{QStyle::}{StandardPixmap} enum. Its
values represent the standard images. Qt's widgets use these, so
when you implement a custom style you should supply the images
used by the style that is being implemented.
The style calculates the spacing between widgets in layouts. There
are two ways the style can handle these calculations. You can set
the PM_LayoutHorizontalSpacing and PM_LayoutVerticalSpacing, which
is the way the java style does it (through QCommonStyle).
Alternatively, you can implement QStyle::layoutSpacing() and
QStyle::layoutSpacingImplementation() if you need more control over
this part of the layout. In these functions you can calculate the
spacing based on control types (QSizePolicy::ControlType) for
different size policies (QSizePolicy::Policy) and also the style
option for the widget in question.
\section2 Style Options
The sub-classes of QStyleOption contain all information necessary
to style the individual elements. Style options are instantiated -
usually on the stack - and filled out by the caller of the QStyle
function. Depending on what is drawn the style will expect
different a different style option class. For example, the
QStyle::PE_FrameFocusRect element expects a QStyleOptionFocusRect
argument, and it's possible to create custom subclasses that a
custom style can use. The style options keep public variables
for performance reasons.
The widgets can be in a number of different states, which are
defined by the \l{QStyle::}{State} enum. Some of the state flags have
different meanings depending on the widget, but others are common
for all widgets like State_Disabled. It is QStyleOption that sets
the common states with QStyleOption::initFrom(); the rest of the
states are set by the individual widgets.
Most notably, the style options contain the palette and bounding
rectangles of the widgets to be drawn. Most widgets have
specialized style options. QPushButton and QCheckBox, for
instance, use QStyleOptionButton as style option, which contain
the text, icon, and the size of their icon. The exact contents of
all options are described when we go through individual widgets.
When reimplementing QStyle functions that take a
QStyleOption parameter, you often need to cast the
QStyleOption to a subclass (e.g., QStyleOptionFocusRect). For
safety, you can use qstyleoption_cast() to ensure that the
pointer type is correct. If the object isn't of the right type,
qstyleoption_cast() returns 0. For example:
\snippet doc/src/snippets/code/doc_src_qt4-styles.qdoc 0
The following code snippet illustrates how to use QStyle to
draw the focus rectangle from a custom widget's paintEvent():
\snippet doc/src/snippets/code/doc_src_qt4-styles.qdoc 1
The next example shows how to derive from an existing style to
customize the look of a graphical element:
\snippet doc/src/snippets/customstyle/customstyle.h 0
\codeline
\snippet doc/src/snippets/customstyle/customstyle.cpp 2
\snippet doc/src/snippets/customstyle/customstyle.cpp 3
\snippet doc/src/snippets/customstyle/customstyle.cpp 4
\section2 QStyle Functions
The QStyle class defines three functions for drawing the primitive,
control, and complex elements:
\l{QStyle::}{drawPrimitive()},
\l{QStyle::}{drawControl()}, and
\l{QStyle::}{drawComplexControl()}. The functions takes the
following parameters:
\list
\o the enum value of the element to draw
\o a QStyleOption which contains the information needed to
draw the element.
\o a QPainter with which to draw the element.
\o a pointer to a QWidget, typically the widget
that the element is painted on.
\endlist
Not all widgets send a pointer to themselves. If the style
option sent to the function does not contain the information you
need, you should check the widget implementation to see if it
sends a pointer to itself.
The QStyle class also provides helper functions that are used
when drawing the elements. The \l{QStyle::}{drawItemText()}
function draws text within a specified rectangle and taking a
QPalette as a parameter. The \l{QStyle::}{drawItemPixmap()}
function helps to align a pixmap within a specified bounding
rectangle.
Other QStyle functions do various calculations for the
functions that draw. The widgets also use these functions for
calculating size hints and also for bounding rectangle
calculations if they draw several style elements themselves.
As with the functions that draw elements the helper functions
typically takes the same arguments.
\list
\o The \l{QStyle::}{subElementRect()} function takes a
\l{QStyle::}{SubElement} enum value, and calculates a bounding
rectangle for a sub element. The style uses this function to
know where to draw the different parts of an element. This is
mainly done for reuse. If you create a new style, you can use
the same location of sub elements as the super class.
\o The \l{QStyle::}{subControlRect()} function is used to
calculate bounding rectangles for sub controls in complex
controls. When you implement a new style, you reimplement \c
subControlRect() and calculate the rectangles that are different
from the super class.
\o The \l{QStyle::}{pixelMetric()} function returns a pixel
metric, which is a style dependent size given in screen
pixels. It takes a value of the \l{QStyle::}{PixelMetric} enum
and returns the correct measure. Note that pixel metrics do
not necessarily have to be static measures, but can be
calculated with, for example, the style option.
\o The \l{QStyle::}{hitTestComplexControl()} function returns the
sub control that the mouse pointer is over in a complex control.
Usually, this is simply a matter of using
\l{QStyle::}{subControlRect()} to get the bounding rectangles of
the sub controls, and see which rectangle contains the position of
the cursor.
\endlist
QStyle also have the functions \l{QStyle::}{polish()} and
\l{QStyle::}{unpolish()}. All widgets are sent to the \c polish()
function before being shown and to \c unpolish() when they
are hidden. You can use these functions to set attributes on the
widgets or do other work that is required by your style. For
instance, if you need to know when the mouse is hovering over the
widget, you need to set the \l{Qt::}{WA_Hover} widget attribute.
The State_MouseOver state flag will then be set in the widget's
style options.
QStyle has a few static helper functions that do some common and
difficult tasks. They can calculate the position of a slider
handle from the value of the slider and transform rectangles
and draw text considering reverse layouts; see the QStyle
class documentation for more details.
The usual approach when one reimplements QStyle virtual
functions is to do work on elements that are different from the
super class; for all other elements, you can simply use the super
class implementation.
\section2 The Palette
Each style provides a color - that is, QBrush - palette that
should be used for drawing the widgets. There is one set of colors
for the different widget states (QPalette::ColorGroup): active
(widgets in the window that has keyboard focus), inactive (widgets
used for other windows), and disabled (widgets that are set
disabled). The states can be found by querying the State_Active
and State_Enabled state flags. Each set contains color certain
roles given by the QPalette::ColorRole enum. The roles describe in
which situations the colors should be used (e.g., for painting
widget backgrounds, text, or buttons).
How the color roles are used is up to the style. For instance, if
the style uses gradients, one can use a palette color and make it
darker or lighter with QColor::darker() and QColor::lighter() to
create the gradient. In general, if you need a brush that is not
provided by the palette, you should try to derive it from one.
QPalette, which provides the palette, stores colors for
different widget states and color roles. The palette for a style
is returned by \l{QStyle::}{standardPalette()}. The standard
palette is not installed automatically when a new style is set
on the application (QApplication::setStyle()) or widget
(QWidget::setStyle()), so you must set the palette yourself
with (QApplication::setPalette()) or (QWidget::setPalette()).
It is not recommended to hard code colors as applications and
individual widgets can set their own palette and also use the
styles palette for drawing. Note that none of Qt's widgets set
their own palette. The java style does hard code some colors, but
its author looks past this in silence. Of course, it is not
intended that the style should look good with any palette.
\section2 Implementation Issues
When you implement styles, there are several issues to
consider. We will give some hints and advice on implementation
here.
When implementing styles, it is necessary to look through the
code of the widgets and code of the base class and its ancestors.
This is because the widgets use the style differently, because the
implementation in the different styles virtual functions can
affect the state of the drawing (e.g., by altering the QPainter
state without restoring it and drawing some elements without using
the appropriate pixel metrics and sub elements).
It is recommended that the styles do not alter the proposed size
of widgets with the QStyle::sizeFromContents() function but let
the QCommonStyle implementation handle it. If changes need to be
made, you should try to keep them small; application development
may be difficult if the layout of widgets looks considerably
different in the various styles.
We recommend using the QPainter directly for drawing, i.e., not
use pixmaps or images. This makes it easier for the style conform
to the palette (although you can set your own color table on a
QImage with \l{QImage::}{setColorTable()}).
It is, naturally, possible to draw elements without using the
style to draw the sub elements as intended by Qt. This is
discouraged as custom widgets may depend on these sub elements to
be implemented correctly. The widget walkthrough shows how Qt
uses the sub elements.
\section1 Java Style
We have implemented a style that resembles the Java default look
and feel (previously known as Metal). We have done this as it is
relatively simple to implement and we wanted to build a style for
this overview document. To keep it simple and not to extensive, we
have simplified the style somewhat, but Qt is perfectly able to
make an exact copy of the style. However, there are no concrete
plans to implement the style as a part of Qt.
In this section we will have a look at some implementation
issues. Finally, we will see a complete example on the styling of
a Java widget. We will continue to use the java style
throughout the document for examples and widget images. The
implementation itself is somewhat involved, and it is not
intended that you should read through it.
\section2 Design and Implementation
The first step in designing the style was to select the base
class. We chose to subclass QWindowsStyle. This class implements
most of the functionality we need other than performing the actual
drawing. Also, windows and java share layout of sub controls for
several of the complex controls (which reduces the amount of code
required considerably).
The style is implemented in one class. We have done this
because we find it convenient to keep all code in one file. Also,
it is an advantage with regards to optimization as we instantiate
less objects. We also keep the number of functions at a minimum by
using switches to identify which element to draw in the functions.
This results in large functions, but since we divide the code for
each element in the switches, the code should still be easy to
read.
\section2 Limitations and Differences from Java
We have not fully implemented every element in the Java style.
This way, we have reduced the amount and complexity of the code.
In general, the style was intended as a practical example for
this style overview document, and not to be a part of Qt
itself.
Not all widgets have every state implemented. This goes for
states that are common, e.g., State_Disabled. Each state is,
however, implemented for at least one widget.
We have only implemented ticks below the slider. Flat push
buttons are also left out. We do not handle the case where the
title bars and dock window titles grows to small for their
contents, but simply draw sub controls over each other.
We have not tried to emulate the Java fonts. Java and Qt use very
different font engines, so we don't consider it worth the effort
as we only use the style as an example for this overview.
We have hardcoded the colors (we don't use the QPalette) for
the linear gradients, which are used, for example, for button
bevels, tool bars, and check boxes. This is because the Java
palette cannot produce these colors. Java does not change these
colors based on widget color group or role anyway (they are not
dependent on the palette), so it does not present a problem in any
case.
It is Qt's widgets that are styled. Some widgets do not exist
at all in Java, e.g., QToolBox. Others contain elements that the
Java widgets don't. The tree widget is an example of the latter in
which Java's JTree does not have a header.
The style does not handle reverse layouts. We assume that the
layout direction is left to right. QWindowsStyle handles reverse
widgets; if we implemented reverse layouts, widgets that we change
the position of sub elements, or handle text alignment in labels
our selves would need to be updated.
\section2 Styling Java Check Boxes
As an example, we will examine the styling of check boxes in the
java style. We describe the complete process and print all code in
both the java style and Qt classes involved. In the rest of this
document, we will not examine the source code of the individual
widgets. Hopefully, this will give you an idea on how to search
through the code if you need to check specific implementation
details; most widgets follow the same structure as the check
boxes. We have edited the QCommonStyle code somewhat to remove
code that is not directly relevant for check box styling.
We start with a look at how QCheckBox builds it style option,
which is QStyleOptionButton for checkboxes:
\snippet doc/src/snippets/code/doc_src_styles.qdoc 0
First we let QStyleOption set up the option with the information
that is common for all widgets with \c initFrom(). We will look at
this shortly.
The down boolean is true when the user press the box down; this is
true whether the box is checked or not of the checkbox. The
State_NoChange state is set when we have a tristate checkbox and
it is partially checked. It has State_On if the box is checked and
State_Off if it is unchecked. State_MouseOver is set if the mouse
hovers over the checkbox and the widget has attribute Qt::WA_Hover
set - you set this in QStyle::polish(). In addition, the style
option also contains the text, icon, and icon size of the button.
\l{QStyleOption::}{initFrom()} sets up the style option with the
attributes that are common for all widgets. We print its
implementation here:
\snippet doc/src/snippets/code/doc_src_styles.qdoc 1
The State_Enabled is set when the widget is enabled. When the
widget has focus the State_HasFocus flag is set. Equally, the
State_Active flag is set when the widget is a child of the active
window. The State_MouseOver will only be set if the widget has
the WA_HoverEnabled windows flag set. Notice that keypad
navigation must be enabled in Qt for the State_HasEditFocus to
be included; it is not included by default.
In addition to setting state flags the QStyleOption contains
other information about the widget: \c direction is the layout
direction of the layout, \c rect is the bounding rectangle of the
widget (the area in which to draw), \c palette is the QPalette
that should be used for drawing the widget, and \c fontMetrics is
the metrics of the font that is used by the widget.
We give an image of a checkbox and the style option to match
it.
\image javastyle/checkboxexample.png A java style checkbox
The above checkbox will have the following state flags in its
style option:
\table 90%
\header
\o State flag
\o Set
\row
\o State_Sunken
\o Yes
\row
\o State_NoChange
\o No
\row
\o State_On
\o Yes
\row
\o State_Off
\o No
\row
\o State_MouseOver
\o Yes
\row
\o State_Enabled
\o Yes
\row
\o State_HasFocus
\o Yes
\row
\o State_KeyboardFocusChange
\o No
\row
\o State_Active
\o Yes
\endtable
The QCheckBox paints itself in QWidget::paintEvent() with
style option \c opt and QStylePainter \c p. The QStylePainter
class is a convenience class to draw style elements. Most
notably, it wraps the methods in QStyle used for painting. The
QCheckBox draws itself as follows:
\snippet doc/src/snippets/code/doc_src_styles.qdoc 2
QCommonStyle handles the CE_CheckBox element. The QCheckBox
has two sub elements: SE_CheckBoxIndicator (the checked indicator)
and SE_CheckBoxContents (the contents, which is used for the
checkbox label). QCommonStyle also implements these sub element
bounding rectangles. We have a look at the QCommonStyle code:
\snippet doc/src/snippets/code/doc_src_styles.qdoc 3
As can be seen from the code extract, the common style gets
the bounding rectangles of the two sub elements of
CE_CheckBox, and then draws them. If the checkbox has focus,
the focus frame is also drawn.
The java style draws CE_CheckBoxIndicator, while QCommonStyle
handles CE_CheckboxLabel. We will examine each implementation and
start with CE_CheckBoxLabel:
\snippet doc/src/snippets/code/doc_src_styles.qdoc 4
\l{QStyle::}{visualAlignment()} adjusts the alignment of text
according to the layout direction. We then draw an icon if it
exists, and adjust the space left for the text.
\l{QStyle::}{drawItemText()} draws the text taking alignment,
layout direction, and the mnemonic into account. It also uses the
palette to draw the text in the right color.
The drawing of labels often get somewhat involved. Luckily, it
can usually be handled by the base class. The java style
implements its own push button label since Java-contrary to
windows-center button contents also when the button has an icon.
You can examine that implementation if you need an example of
reimplementing label drawing.
We take a look at the java implementation
of CE_CheckBoxIndicator in \c drawControl():
\snippet doc/src/snippets/javastyle.cpp 0
We first save the state of the painter. This is not always
necessary but in this case the QWindowsStyle needs the painter in
the same state as it was when PE_IndicatorCheckBox was called (We
could also set the state with function calls, of course). We then
use \c drawButtonBackground() to draw the background of the check
box indicator. This is a helper function that draws the background
and also the frame of push buttons and check boxes. We take a look
at that function below. We then check if the mouse is hovering
over the checkbox. If it is, we draw the frame java checkboxes
have when the box is not pressed down and the mouse is over it.
You may note that java does not handle tristate boxes, so we have
not implemented it.
Here we use a png image for our indicator. We could also check
here if the widget is disabled. We would then have to use
another image with the indicator in the disabled color.
\snippet doc/src/snippets/javastyle.cpp 1
We have seen how check boxes are styled in the java style from the
widget gets a paint request to the style is finished painting. To
learn in detail how each widget is painted, you need to go through
the code step-by-step as we have done here. However, it is
usually enough to know which style elements the widgets draw. The
widget builds a style option and calls on the style one or more
times to draw the style elements of which it consists. Usually,
it is also sufficient to know the states a widget can be in and the
other contents of the style option, i.e., what we list in the next
section.
\section1 Widget Walkthrough
In this section, we will examine how most of Qt's widgets are
styled. Hopefully, this will save you some time and effort while
developing your own styles and widgets. You will not find
information here that is not attainable elsewhere (i.e., by
examining the source code or the class descriptions for the style
related classes).
We mostly use java style widgets as examples. The java style does not
draw every element in the element trees. This is because they are
not visible for that widget in the java style. We still make sure
that all elements are implemented in a way that conforms with the
java style as custom widgets might need them (this does not
exclude leaving implementations to QWindowsStyle though).
The following is given for each widget:
\list
\o A table with the members (variables, etc.) of its style option.
\o A table over the state flags (QStyle::StateFlag) that
can be set on the widget and when the states are set.
\o Its element tree (see section \l{The Style Elements}).
\o An image of the widget in which the elements are outlined.
\omit This is not written yet - probably never will be
either
\o List of style hints that should be checked for the
widget.
\o List of standard pixmaps that could be used by the
elements.
\endomit
\endlist
The element tree contains the primitive, control, and complex
style elements. By doing a top-down traversal of the element tree,
you get the sequence in which the elements should be drawn. In the
nodes, we have written the sub element rectangles, sub control
elements, and pixel metrics that should be considered when drawing
the element of the node.
Our approach on styling center on the drawing of the widgets. The
calculations of sub elements rectangles, sub controls, and pixel
metrics used \bold during drawing is only listed as contents in
the element trees. Note that there are rectangles and pixel
metrics that are only used by widgets. This leaves these
calculations untreated in the walkthrough. For instance, the
\l{QStyle::}{subControlRect()} and
\l{QStyle::}{sizeFromContents()} functions often call
\l{QStyle::}{subElementRect()} to calculate their bounding
rectangles. We could draw trees for this as well. However, how
these calculations are done is completely up to the individual
styles, and they do not have to follow a specific structure (Qt
does not impose a specific structure). You should still make sure
that you use the appropriate pixel metrics, though. To limit the
size of the document, we have therefore chosen not to include
trees or describe the calculations made by the Java (or any other)
style.
You may be confused about how the different pixel metrics, sub
element rectangles, and sub control rectangles should be used when
examining the trees. If you are in doubt after reading the QStyle
enum descriptions, we suggest that you examine the QCommonStyle
and QWindowsStyle implementations.
Some of the bounding rectangles that we outline in the widget
images are equal. Reasons for this are that some elements draw
backgrounds while others draw frames and labels. If in doubt,
check the description of each element in QStyle. Also, some
elements are there to layout, i.e., decide where to draw, other
elements.
\section2 Common Widget Properties
Some states and variables are common for all widgets. These are
set with QStyleOption::initFrom(). Not all elements use this function;
it is the widgets that create the style options, and for some
elements the information from \l{QStyleOption::}{initFrom()} is not
necessary.
A table with the common states follows:
\table 90%
\header
\o State
\o State Set When
\row
\o State_Enabled
\o Set if the widget is not disabled (see
QWidget::setEnabled())
\row
\o State_Focus
\o Set if the widget has focus (see
QWidget::hasFocus())
\row
\o State_KeyobordFocusChange
\o Set when the user changes focus with the keyboard
(see Qt::WA_KeyboardFocusChange)
\row
\o State_MouseOver
\o Set if the mouse cursor is over the widget
\row
\o State_Active
\o Set if the widget is a child of the active window.
\row
\o State_HasEditFocus
\o Set if the widget has the edit focus
\endtable
The other common members for widgets are:
\table 90%
\header
\o Member
\o Content
\row
\o rect
\o The bounding rectangle of the element to draw. This
is set to the widget bounding rectangle
(QWidget::rect()).
\row
\o direction
\o The layout direction; a value of the
Qt::LayoutDirection enum.
\row
\o palette
\o The QPalette to use when drawing the element. This
is set to the widgets palette (QWidget::palette()).
\row
\o fontMetrics
\o The QFontMetrics to use when drawing text on the
widget.
\endtable
The complex style options (classes that inherit
QStyleOptionComplex) used for complex style elements share two
variables: \l{QStyleOptionComplex::}{subControls} and
\l{QStyleOptionComplex::}{activeSubControls}. Both variables are
an OR'ed combination of QStyle::SubControl enum values. They
indicate which sub controls the complex control consists of and
which of these controls are currently active.
As mentioned, the style calculates the size of the widgets
contents, which the widgets calculate their size hints from. In
addition, complex controls also use the style to test which
sub-controls the mouse is over.
\section2 Widget Reference
Without further delay, we present the widget walkthrough; each
widget has its own sub-section.
\section3 Push Buttons
The style structure for push buttons is shown below. By doing a
top-down traversal of the tree, you get the sequence in which the
elements should be drawn.
\image javastyle/pushbutton.png The style structure for push buttons
The layout of the buttons, with regard element bounds, varies from
style to style. This makes it difficult to show conceptual images
of this. Also, elements may - even be intended to - have the same
bounds; the PE_PushButtonBevel, for instance, is used in
QCommonStyle to draw the elements that contains it:
PE_FrameDefaultButton, PE_FrameButtonBevel, and
PE_PanelButtonCommand, all of which have the same bounds in common
and windows style. PE_PushButtonBevel is also responsible for
drawing the menu indicator (QCommonStyle draws
PE_IndicatorArrowDown).
An image of a push button in the java style that show the bounding
rectangles of the elements is given below. Colors are used to
separate the bounding rectangles in the image; they do not fill
any other purpose. This is also true for similar images for the
other widgets.
\image javastyle/button.png
The java style, as well as all other styles implemented in Qt,
does not use PE_FrameButtonBevel. It is usual that a button
with a PE_DefaultFrame adjusts the PE_PanelButtonCommand's
rectangle by PM_ButtonDefaultIndicator. The CE_PushButtonLabel
is found by adjusting the rect by PM_DefaultFrameWidth.
We will now examine the style option for push
buttons - QStyleOptionButton. A table for the states that
QPushButton can set on the style option follows:
\table 90%
\header
\o State
\o State Set When
\row
\o State_Sunken
\o Button is down or menu is pressed shown
\row
\o State_On
\o Button is checked
\row
\o State_Raised
\o Button is not flat and not pressed down
\endtable
Other members of QStyleOptionButton is:
\table 90%
\header
\o Member
\o Content
\row
\o features
\o Flags of the QStyleOptionButton::ButtonFeatures enum,
which describes various button properties (see enum)
\row
\o icon
\o The buttons QIcon (if any)
\row
\o iconSize
\o The QSize of the icon
\row
\o text
\o a QString with the buttons text
\endtable
\section3 Check and Radio Buttons
The structures for radio and check buttons are identical.
We show the structure using QCheckBox element and pixel
metric names:
\image javastyle/checkbox.png
QStyleOptionButton is used as the style option for both check
and radio buttons. We first give a table of the states that
can be set in the option:
\table 90%
\header
\o State
\o State Set When
\row
\o State_sunken
\o The box is pressed down
\row
\o State_NoChange
\o The box is partially checked (for tristate
checkboxes.)
\row
\o State_On
\o The box is checked
\row
\o State_Off
\o The box is unchecked
\endtable
See \l{Push Buttons} for a table over other members in the
QStyleOptionButtonClass.
\section3 Tabs
In Qt, QTabBar uses the style to draw its tabs. Tabs exist either
in a QTabWidget, which contains a QTabBar, or as a separate bar.
If the bar is not part of a tab widget, it draws its own base.
QTabBar lays out the tabs, so the style does not have control over
tab placement. However, while laying out its tabs, the bar asks
the style for PM_TabBarTabHSpace and PM_TabBarTabVSpace, which is
extra width and height over the minimum size of the tab bar tab
label (icon and text). The style can also further influence the
tab size before it is laid out, as the tab bar asks for
CT_TabBarTab. The bounding rectangle of the bar is decided by the
tab widget when it is part of the widget (still considering
CT_TabBarTab).
The tab bar is responsible for drawing the buttons that appear on
the tab bar when all tabs do not fit. Their placement is not
controlled by the style, but the buttons are \l{QToolButton}s
and are therefore drawn by the style.
Here is the style structure for QTabWidget and QTabBar:
\image javastyle/tab.png
The dotted lines indicate that the QTabWidget contains a tab bar,
but does not draw it itself, that QTabBar only draws its base line
when not part of a tab widget, and that the tab bar keeps two tool
buttons that scroll the bar when all tabs do not fit; see \l{Tool
Buttons} for their element tree. Also note that since the buttons
are children of the tab bar, they are drawn after the bar. The
tabs bounding rectangles overlap the base by PM_TabBarBaseOverlap.
Here is a tab widget in the java style:
\image javastyle/tabwidget.png
In the java style (and also windows), the tab bar shape and label
have the same bounding rectangle as CE_TabBarTab. Notice that the
tabs overlap with the tab widget frame. The base of the tab bar
(if drawn) is the area where the tabs and frame overlap.
The style option for tabs (QStyleOptionTab) contains the necessary
information for drawing tabs. The option contains the position of
the tab in the tab bar, the position of the selected tab, the
shape of the tab, the text, and icon. After Qt 4.1 the option
should be cast to a QStyleOptionTabV2, which also contains the
icons size.
As the java style tabs don't overlap, we also present an image of
a tab widget in the windows style. Note that if you want the tabs
to overlap horizontally, you do that when drawing the tabs in
CE_TabBarTabShape; the tabs bounding rectangles will not be
altered by the tab bar. The tabs are drawn from left to right in a
north tab bar shape, top to bottom in an east tab bar shape, etc.
The selected tab is drawn last, so that it is easy to draw it over
the other tabs (if it is to be bigger).
\image javastyle/windowstabimage.png
A table of the states a tab bar can set on its tabs follows:
\table 90%
\header
\o State
\o State Set When
\row
\o State_Sunken
\o The tab is pressed on with the mouse.
\row
\o State_Selected
\o If it is the current tab.
\row
\o State_HasFocus
\o The tab bar has focus and the tab is selected
\endtable
Note that individual tabs may be disabled even if the tab bar
is not. The tab will be active if the tab bar is active.
Here follows a table of QStyleOptionTabV2's members:
\table 90%
\header
\o Member
\o Content
\row
\o cornerWidgets
\o Is flags of the CornerWidget enum, which indicate
if and which corner widgets the tab bar has.
\row
\o icon
\o The QIcon of the tab
\row
\o iconSize
\o The QSize of the icon
\row
\o position
\o A TabPosition enum value that indicates the tabs
position on the bar relative to the other tabs.
\row
\o row
\o holds which row the tab is in
\row
\o selectedPosition
\o A value of the SelectedPosition enum that indicates
whether the selected tab is adjacent to or is the
tab.
\row
\o shape
\o A value of the QTabBar::Shape enum indication
whether the tab has rounded or triangular corners
and the orientation of the tab.
\row
\o text
\o The tab text
\endtable
The frame for tab widgets use QStyleOptionTabWidgetFrame as
style option. We list its members here. It does not have
states set besides the common flags.
\table 90%
\header
\o Member
\o content
\row
\o leftCornerWidgetSize
\o The QSize of the left corner widget (if any).
\row
\o rightCornerWidgetSize
\o The QSize of the right corner widget (if any).
\row
\o lineWidth
\o holds the line with for drawing the panel.
\row
\o midLineWith
\o this value is currently always 0.
\row
\o shape
\o The shape of the tabs on the tab bar.
\row
\o tabBarSize
\o The QSize of the tab bar.
\endtable
\section3 Scroll Bars
Here is the style structure for scrollBars:
\image javastyle/scrollbar.png
QScrollBar simply creates its style option and then draws
CC_ScrollBar. Some styles draw the background of add page and sub
page with PE_PanelButtonBevel and also use indicator arrows to
draw the arrows in the nest and previous line indicators; we have
not included these in the tree as their use is up to the
individual style. The style's PM_MaximumDragDistance is the
maximum distance in pixels the mouse can move from the bounds
of the scroll bar and still move the handle.
Here is an image of a scrollbar in the java style:
\image javastyle/scrollbarimage.png
You may notice that the scrollbar is slightly different from
Java's as it has two line up indicators. We have done this to show
how that you can have two separate bounding rectangles for a
single sub control. The scroll bar is an example of a widget that
is entirely implemented by the java style - neither QWindowsStyle
nor QCommonStyle are involved in the drawing.
We have a look at the different states a scroll bar can set on
the style option:
\table 90%
\header
\o State
\o State Set When
\row
\o State_Horizontal
\o The scroll bar is horizontal
\endtable
The style option of QScrollBar is QStyleOptionSlider. Its
members are listed in the following table. The option is used
by all \l{QAbstractSlider}s; we only describe the members
relevant for scroll bars here.
\table 90%
\header
\o Member
\o Content
\row
\o maximum
\o the maximum value of the scroll bar
\row
\o minimum
\o the minimum value of the scroll bar
\row
\o notchTarget
\o the number of pixels between notches
\row
\o orientation
\o a value of the Qt::Orientation enum that specifies
whether the scroll bar is vertical or horizontal
\row
\o pageStep
\o the number to increase or decrease the sliders
value (relative to the size of the slider and its value
range) on page steps.
\row
\o singleStep
\o the number to increase or decrease the sliders
value on single (or line) steps
\row
\o sliderValue
\o The value of the slider
\row
\o sliderPosition
\o the position of the slider handle. This is the same
as \c sliderValue if the scroll bar is
QAbstractSlider::tracking. If not, the scroll
bar does not update its value before the mouse
releases the handle.
\row
\o upsideDown
\o holds the direction in which the scroll bar
increases its value. This is used instead of
QStyleOption::direction for all abstract sliders.
\endtable
\section3 Sliders
When calculating the sliders size hint, PM_SliderTickness and
PM_SliderLength is queried from the style. As with scroll bars,
the QSlider only lets the user move the handle if the mouse is
within PM_MaximumDragDistance from the slider bounds. When it
draws itself it creates the style option and calls \c
drawComplexControl() with CC_Slider:
\image javastyle/slider.png
We also show a picture of a slider in the java style. We show
the bounding rectangles of the sub elements as all drawing is done
in CC_Slider.
\image javastyle/sliderimage.png
QSlider uses QStyleOptionSlider as all \l{QAbstractSlider}s do. We
present a table with the members that affect QSlider:
\table 90%
\header
\o Member
\o Content
\row
\o maximum
\o the maximum value of the slider
\row
\o minimum
\o the minimum value of the slider
\row
\o notchTarget
\o this is the number of pixels between each notch
\row
\o orientation
\o a Qt::Orientation enum value that gives whether the
slider is vertical or horizontal.
\row
\o pageStep
\o a number in slider value to increase or decrease
for page steps
\row
\o singleStep
\o the number to increase or decrease the sliders
value on single (or line) steps.
\row
\o sliderValue
\o the value of the slider.
\row
\o sliderPosition
\o the position of the slider given as a slider value.
This will be equal to the \c sliderValue if the
slider is \l{QAbstractSlider::}{tracking}; if
not, the sliders value will not change until the handle is
released with the mouse.
\row
\o upsideDown
\o this member is used instead of QStyleOption::direction
for all abstract sliders.
\endtable
You should note that the slider does not use direction for
reverse layouts; it uses \c upsideDown.
\section3 Spin Boxes
When QSpinBox paints itself it creates a QStyleOptionSpinBox and
asks the style to draw CC_SpinBox. The edit field is a line
edit that is a child of the spin box. The dimensions of the
field is calculated by the style with SC_SpinBoxEditField.
Here follows the style tree for spin boxes. It is not
required that a style uses the button panel primitive to paint
the indicator backgrounds. You can see an image below the tree
showing the sub elements in QSpinBox in the java style.
\image javastyle/spinbox.png
\image javastyle/spinboximage.png
The QStyleOptionSpinBox, which is the style option for spin
boxes. It can set the following states on the spin box.:
\table 90%
\header
\o State
\o State Set When
\row
\o State_Sunken
\o Is set if one of the sub controls CC_SpinUp or
CC_SpinDown is pressed on with the mouse.
\endtable
The rest of the members in the spin boxes style options are:
\table 90%
\header
\o Property
\o Function
\row
\o frame
\o boolean that is true if the spin box is to draw a
frame.
\row
\o buttonSymbols
\o Value of the ButtonSymbols enum that decides the
symbol on the up/down buttons.
\row
\o stepEnabled
\o A value of the StepEnabled indication which of the
spin box buttons are pressed down.
\endtable
\section3 Title Bar
The title bar complex control, CC_TitleBar, is used to draw
the title bars of internal windows in QMdiArea. It typically
consists of a window title and close, minimize, system menu, and
maximize buttons. Some styles also provide buttons for shading
the window, and a button for context sensitive help.
The bar is drawn in CC_TitleBar without using any sub elements.
How the individual styles draw their buttons is individual, but
there are standard pixmaps for the buttons that the style should
provide.
\image javastyle/titlebar.png
In an image over a title bar in the java style, we show the
bounding rectangles of the sub elements supported by the java style
(all of which are drawn with standard pixmaps). It is usual to
draw the button backgrounds using PE_PanelButtonTool, but it's no
rule.
\image javastyle/titlebarimage.png
The style option for title bars is QStyleOptionTitleBar. It's
members are:
\table 90%
\header
\o Member
\o Content
\row
\o icon
\o The title bars icon
\row
\o text
\o the text for the title bar's label
\row
\o windowFlags
\o flags of the Qt::WindowFlag enum. The window flags
used by QMdiArea for window management.
\row
\o titleBarState
\o this is the QWidget::windowState() of the window
that contains the title bar.
\endtable
\section3 Combo Box
A QComboBox uses the style to draw the button and label of
non-editable boxes with CC_ComboBox and CE_ComboBoxLabel.
The list that pops up when the user clicks on the combo box is
drawn by a \l{Delegate Classes}{delegate}, which we do not cover
in this overview. You can, however, use the style to control the
list's size and position with the sub element
SC_ComboBoxListBoxPopup. The style also decides where the edit
field for editable boxes should be with SC_ComboBoxEditField; the
field itself is a QLineEdit that is a child of the combo box.
\image javastyle/combobox.png
We show an image over a java style combo box in which we have
outlined its sub elements and sub element rectangles:
\image javastyle/comboboximage.png
Java combo boxes do not use the focus rect; it changes its
background color when it has focus. The SC_ComboBoxEdit field is
used both by QComboBox to calculate the size of the edit field and
the style for calculating the size of the combo box label.
The style option for combo boxes is QStyleOptionComboBox. It
can set the following states:
\table 90%
\header
\o State
\o Set When
\row
\o State_Selected
\o The box is not editable and has focus
\row
\o State_Sunken
\o SC_ComboBoxArrow is active
\row
\o State_on
\o The container (list) of the box is visible
\endtable
The style options other members are:
\table
\header
\o Member
\o Content
\row
\o currentIcon
\o the icon of the current (selected) item of the
combo box.
\row
\o currentText
\o the text of the current item in the box.
\row
\o editable
\o holds whether the combo box is editable or not
\row
\o frame
\o holds whether the combo box has a frame or not
\row
\o iconSize
\o the size of the current items icon.
\row
\o popupRect
\o the bounding rectangle of the combo box's popup
list.
\endtable
\section3 Group Boxes
When calculating the size hint, QGroupBox fetches three pixel
metrics from the style: PM_IndicatorWidth,
PM_CheckBoxLabelSpacing, and PM_IndicatorHeight. QGroupBox has
the following style element tree:
\image javastyle/groupbox.png
Qt does not impose restrictions on how the check box is drawn; the
java style draws it with CE_IndicatorCheckBox. See \l{Check and
Radio Buttons} for the complete tree.
We also give an image of the widget with the sub controls and
sub control rectangles drawn:
\image javastyle/groupboximage.png
The style option for group boxes are QStyleOptionGroupBox. The
following states can be set on it:
\table 90%
\header
\o State
\o Set When
\row
\o State_On
\o The check box is checked
\row
\o State_Sunken
\o The checkbox is pressed down
\row
\o State_Off
\o The check box is unchecked (or there is no check box)
\endtable
The remaining members of QStyleOptionGroupBox are:
\table
\header
\o Member
\o Content
\row
\o features
\o flags of the QStyleOptionFrameV2::FrameFeatures
enum describing the frame of the group box.
\row
\o lineWidth
\o the line width with which to draw the panel. This
is always 1.
\row
\o text
\o the text of the group box.
\row
\o textAlignment
\o the alignment of the group box title
\row
\o textColor
\o the QColor of the text
\endtable
\section3 Splitters
As the structure of splitters are simple and do not contain any
sub elements, we do not include image of splitters. CE_Splitter
does not use any other elements or metrics.
For its style option, Splitters uses the base class QStyleOption.
It can set the following state flags on it:
\table 90%
\header
\o State
\o Set When
\row
\o State_Horizontal
\o Set if it is a horizontal splitter
\endtable
QSplitter does not use \l{QStyleOption::}{initFrom()} to set up its
option; it sets the State_MouseOver and State_Disabled flags
itself.
\section3 Progress Bar
The CE_ProgressBar element is used by QProgressBar, and it is the
only element used by this widget. We start with looking at the
style structure:
\image javastyle/progressbar.png
Here is a progress bar in the windows style (the java style
bounding rectangles are equal):
\image javastyle/progressbarimage.png
The style option for QProgressBar is QStyleOptionProgressBarV2.
The bar does not set any state flags, but the other members of the
option are:
\table 90%
\header
\o Member
\o Content
\row
\o minimum
\o The minimum value of the bar
\row
\o maximum
\o The maximum value of the bar
\row
\o progress
\o The current value of the bar
\row
\o textAlignment
\o How the text is aligned in the label
\row
\o textVisible
\o Whether the label is drawn
\row
\o text
\o The label text
\row
\o orientation
\o Progress bars can be vertical or horizontal
\row
\o invertedAppearance
\o The progress is inverted (i.e., right to left in a
horizontal bar)
\row
\o bottomToTop
\o Boolean that if true, turns the label of vertical
progress bars 90 degrees.
\endtable
\section3 Tool Buttons
Tool buttons exist either independently or as part of tool bars.
They are drawn equally either way. The QToolButton draws only one
style element: CC_ToolButton.
As you must be used to by now (at least if you have read this
document sequentially), we have a tree of the widget's style
structure:
\image javastyle/toolbutton.png
Note that PE_FrameButtonTool and PE_IndicatorArrowDown are
included in the tree as the java style draws them, but they can
safely be omitted if you prefer it. The structure may also be
different. QWindowsStyle, for instance, draws both
PE_IndicatorButtonDropDown and PE_IndicatorArrowDown in
CE_ToolButton.
We also have an image of a tool button where we have outlined
the sub element bounding rectangles and sub controls.
\image javastyle/toolbuttonimage.png
Here is the states table for tool buttons:
\table 90%
\header
\o State
\o Set When
\row
\o State_AutoRise
\o the tool button has the autoRise property set
\row
\o State_raised
\o the button is not sunken (i.e., by being checked or
pressed on with the mouse).
\row
\o State_Sunken
\o the button is down
\row
\o State_On
\o the button is checkable and checked.
\endtable
QStyleOptionToolButton also contains the following members:
\table
\header
\o Member
\o Content
\row
\o arrowType
\o a Qt::ArrowType enum value, which contains the
direction of the buttons arrow (if an arrow is to
be used in place of an icon)
\row
\o features
\o flags of the QStyleOptionToolButton::ButtonFeature
enum describing if the button has an arrow, a menu,
and/or has a popup-delay.
\row
\o font
\o the QFont of the buttons label
\row
\o icon
\o the QIcon of the tool button
\row
\o iconSize
\o the icon size of the button's icon
\row
\o pos
\o the position of the button, as given by
QWidget::pos()
\row
\o text
\o the text of the button
\row
\o toolButtonStyle
\o a Qt::ToolButtonStyle enum value which decides
whether the button shows the icon, the text, or both.
\endtable
\section3 Toolbars
Toolbars are part of the \l{QMainWindow}{main window framework}
and cooperates with the QMainWindow to which it belongs while it
builds its style option. A main window has 4 areas that toolbars
can be placed in. They are positioned next to the four sides of
the window (i.e., north, south, west, and east). Within each area
there can be more than one line of toolbars; a line consists of
toolbars with equal orientation (vertical or horizontal) placed
next to each other.
\l{QToolbar}{QToolbar}s in Qt consists of three elements
CE_ToolBar, PE_IndicatorToolBarHandle, and
PE_IndicatorToolBarSeparator. It is QMainWindowLayout that
calculates the bounding rectangles (i.e., position and size of the
toolbars and their contents. The main window also uses the \c
sizeHint() of the items in the toolbars when calculating the size
of the bars.
Here is the element tree for QToolBar:
\image javastyle/toolbar.png
The dotted lines indicate that the QToolBar keeps an instance of
QToolBarLayout and that QToolBarSeparators are kept by
QToolBarLayout. When the toolbar is floating (i.e., has its own
window) the PE_FrameMenu element is drawn, else QToolbar draws
CE_ToolBar.
Here is an image of a toolbar in the java style:
\image javastyle/toolbarimage.png
QToolBarSaparator uses QStyleOption for their style option. It
sets the State_horizontal flag if the toolbar they live in is
horizontal. Other than that, they use \l{QStyleOption::}{initFrom()}.
The style option for QToolBar is QStyleOptionToolBar. The only
state flag set (besides the common flags) is State_Horizontal
if the bar is horizontal (i.e., in the north or south toolbar area).
The member variables of the style option are:
\table 90%
\header
\o Member
\o Content
\row
\o features
\o Holds whether the bar is movable in a value of the
ToolBarFeature, which is either Movable or None.
\row
\o lineWidth
\o The width of the tool bar frame.
\row
\o midLineWidth
\o This variable is currently not used and is always
0.
\row
\o positionOfLine
\o The position of the toolbar line within the toolbar
area to which it belongs.
\row
\o positionWithinLine
\o The position of the toolbar within the toolbar line.
\row
\o toolBarArea
\o The toolbar area in which the toolbar lives.
\endtable
\section3 Menus
Menus in Qt are implemented in QMenu. The QMenu keeps a list of
action, which it draws as menu items. When QMenu receives paint
events ,it calculates the size of each menu item and draws them
individually with CE_MenuItem. (Menu items do not have a separate
element for their label (contents), so all drawing is done in
CE_MenuItem. The menu also draws the frame of the menu with
PE_FrameMenu. It also draws CE_MenuScroller if the style supports
scrolling. CE_MenuTearOff is drawn if the menu is to large for its
bounding rectangle.
In the style structure tree, we also include QMenu as it also does
styling related work. The bounding rectangles of menu items are
calculated for the menus size hint and when the menu is displayed
or resized.
\image javastyle/menu.png
The CE_MenuScroller and CE_MenuTearOff elements are handled by
QCommonStyle and are not shown unless the menu is to large to fit
on the screen. PE_FrameMenu is only drawn for pop-up menus.
QMenu calculates rectangles based on its actions and calls
CE_MenuItem and CE_MenuScroller if the style supports that.
It is also usual to use PE_IndicatorCheckBox (instead of using
PE_IndicatorMenuCheckMark) and PE_IndicatorRadioButton for drawing
checkable menu items; we have not included them in the style tree
as this is optional and varies from style to style.
\image javastyle/menuimage.png
The style option for menu items is QStyleOptionMenuItem. The
following tables describe its state flags and other members.
\table 90%
\header
\o State
\o Set When
\row
\o State_Selected
\o The mouse is over the action and the action is not
a separator.
\row
\o State_Sunken
\o The mouse is pressed down on the menu item.
\row
\o State_DownArrow
\o Set if the menu item is a menu scroller and it scrolls
the menu downwards.
\endtable
\table 90%
\header
\o Member
\o Content
\row
\o checkType
\o A value of the \l{QStyleOptionMenuItem::}{CheckType} enum,
which is either NotCheckable, Exclusive, or
NonExclusive.
\row
\o checked
\o Boolean that is true if the menu item is checked.
\row
\o font
\o The QFont to use for the menu item's text.
\row
\o icon
\o the QIcon of the menu item.
\row
\o maxIconWidth
\o The maximum width allowed for the icon
\row
\o menuHasChecableItem
\o Boolean which is true if at least one item in the
menu is checkable.
\row
\o menuItemType
\o The type of the menu item. This a value of the
\l{QStyleOptionMenuItem::}{MenuItemType}.
\row
\o menuRect
\o The bounding rectangle for the QMenu that the menu
item lives in.
\row
\o tabWidth
\o This is the distance between the text of the menu
item and the shortcut.
\row
\o text
\o The text of the menu item.
\endtable
The setup of the style option for CE_MenuTearOff and
CE_MenuScroller also uses QStyleOptionMenuItem; they only set the
\c menuRect variable in addition to the common settings with
QStyleOption's \l{QStyleOption::}{initFrom()}.
\section3 Menu Bar
QMenuBar uses the style to draw each menu bar item and the empty
area of the menu bar. The pull-down menus themselves are
\l{QMenu}s (see \l{Menus}). The style element tree for the menu
bar follows:
\image javastyle/menubar.png
The panel and empty area is drawn after the menu items. The
QPainter that the QMenuBar sends to the style has the bounding
rectangles of the items clipped out (i.e., clip region), so you
don't need to worry about drawing over the items. The pixel
metrics in QMenuBar is used when the bounding rectangles of the
menu bar items are calculated.
\image javastyle/menubarimage.png
QStyleOptionMenuItem is used for menu bar items. The members that
are used by QMenuBar is described in the following table:
\table
\header
\o Member
\o Content
\row
\o menuRect
\o the bounding rectangle of the entire menu bar to
which the item belongs.
\row
\o text
\o the text of the item
\row
\o icon
\o the icon of the menu item (it is not common that
styles draw this icon)
\endtable
QStyleOptionMenuItem is also used for drawing CE_EmptyMenuBarArea.
QStyleOptionFrame is used for drawing the panel frame The
\l{QStyleOptionFrame::}{lineWidth} is set to PM_MenuBarPanelWidth.
The \l{QStyleOptionFrame::}{midLineWidth} is currently always set
to 0.
\section3 Item View Headers
It is the style that draws the headers of Qt's item views. The
item views keeps the dimensions on individual sections. Also
note that the delegates may use the style to paint decorations
and frames around items. QItemDelegate, for instance, draws
PE_FrameFocusRect and PE_IndicatorViewItemCheck.
\image javastyle/header.png
Here is a QTableWidget showing the bounding rects of a Java
header:
\image javastyle/headerimage.png
The QHeaderView uses CT_HeaderSection, PM_HeaderMargin and
PM_HeaderGripMargin for size and hit test calculations. The
PM_HeaderMarkSize is currently not used by Qt. QTableView draws
the button in the top-left corner (i.e., the area where the
vertical and horizontal headers intersect) as a CE_Header.
The style option for header views is QStyleOptionHeader. The view
paints one header section at a time, so the data is for the
section being drawn. Its contents are:
\table 90%
\header
\o Member
\o Content
\row
\o icon
\o the icon of the header (for section that is being
drawn).
\row
\o iconAlignment
\o the alignment (Qt::Alignment) of the icon in the header.
\row
\o orientation
\o a Qt::Orientation value deciding whether the header
is the horizontal header above the view or the
vertical header on the left.
\row
\o position
\o a QStyleOptionHeader::SectionPosition value
giving the header section's position relative to
the other sections.
\row
\o section
\o holds the section that is being drawn.
\row
\o selectedPosition
\o a QStyleOptionHeader::SelectedPosition value giving
the selected section's position relative to the
section that is being painted.
\row
\o sortIndicator
\o a QStyleOptionHeader::SortIndicator value that
describes the direction in which the section's sort
indicator should be drawn.
\row
\o text
\o the text of the currently drawn section.
\row
\o textAlignment
\o the Qt::Alignment of the text within the
headersection.
\endtable
\section3 Tree Branch Indicators
The branch indicators in a tree view is drawn by the style with
PE_IndicatorBranch. We think of indicators here as the indicators
that describe the relationship of the nodes in the tree. The
generic QStyleOption is sent to the style for drawing this
elements. The various branch types are described by states. Since
there are no specific style option, we simply present the states
table:
\table 90%
\header
\o State
\o Set When
\row
\o State_Sibling
\o the node in the tree has a sibling (i.e., there is
another node in the same column).
\row
\o State_Item
\o this branch indicator has an item.
\row
\o State_Children
\o the branch has children (i.e., a new sub-tree can
be opened at the branch).
\row
\o State_Open
\o the branch indicator has an opened sub-tree.
\endtable
The tree view (and tree widget) use the style to draw the branches
(or nodes if you will) of the tree.
QStyleOption is used as the style for PE_IndicatorBranch has state
flags set depending on what type of branch it is.
Since there is no tree structure for branch indicators, we only
present an image of a tree in the java style. Each state is marked
in the image with a rectangle in a specific color (i.e., these
rectangles are not bounding rectangles). All combinations of
states you must be aware of are represented in the image.
\image javastyle/branchindicatorimage.png
\section3 Tool Boxes
PM_SmallIconSize for sizeHints.
QToolBox is a container that keeps a collection of widgets. It has
one tab for each widget and display one of them at a time. The
tool box lays the components it displays (the tool box buttons
and selected widget) in a QVBoxLayout. The style tree for tool
boxes looks like this:
\image javastyle/toolbox.png
We show an image of a tool box in the Plastique style:
\image javastyle/toolboximage.png
All elements have the same bounding rectangles in the
Plastique as well as the other Qt built-in styles.
The style option for tool boxes is QStyleOptionToolBox. It
contains the text and icon of the tool box contents. The only
state set by QToolBox is State_Sunken, which is set when the user
presses a tab down with the mouse. The rest of the
QStyleOptionToolBox members are:
\table 90%
\header
\o Member
\o Content
\row
\o icon
\o the icon on the toolbox tab
\row
\o text
\o the text on the toolbox tab
\endtable
\section3 Size Grip
The size grip calculates its size hint with CT_SizeGrip. The pixel
metric PM_SizeGripSize is currently unused by Qt. The element tree
for and an image in the Plastique style of QSizeGrip follows:
\image javastyle/sizegrip.png
\image javastyle/sizegripimage.png
We show the size grip in a \l{QMainWindow}'s bottom right
corner.
The size grip style option, QStyleOptionSizeGrip, have one
member except the common members from QStyleOption:
\table 90%
\header
\o Member
\o Content
\row
\o corner
\o a Qt::Corner value that describe which corner in a
window (or equivalent) the grip is located.
\endtable
\section3 Rubber Band
The \l{QRubberBand}'s style tree consists of two nodes.
\image javastyle/rubberband.png
We present an image of a Java style window being moved in a
QMdiArea with a rubber band:
\image javastyle/rubberbandimage.png
The style option for rubber bands is QStyleOptionRubberBand.
Its members are:
\table
\header
\o Member
\o Content
\row
\o opaque
\o boolean that is true if the rubber band must be
drawn in an opaque style (i.e., color)
\row
\o shape
\o a QRubberBand::Shape enum value that holds the
shape of the band (which is either a rectangle or a
line)
\endtable
\section3 Dock Widgets
When the dock widget lays out its contents it asks the style for
these pixel metrics: PM_DockWidgetSeparatorExtent,
PM_DockWidgetTitleBarButtonMargin, PM_DockWidgetFrameWidth, and
PM_DockWidgetTitleMargin. It also calculates the bounding
rectangles of the float and close buttons with
SE_DockWidgetCloseButton and SE_DockWidgetFloatButton.
\image javastyle/dockwidget.png
The dotted lines indicate that the sender keeps instances of the
recipient of the arrow (i.e., it is not a style element to draw).
The dock widget only draws PE_frameDockWidget when it is detached
from its main window (i.e., it is a top level window). If it is
docked it draws the indicator dock widget resize handle. We show a
dock widget in both docked and floating state in the plastique
style:
\image javastyle/dockwidgetimage.png
The style option is QStyleOptionDockWidget:
\table 90%
\header
\o Member
\o Content
\row
\o closeable
\o boolean that holds whether the dock window can be
closed
\row
\o floatable
\o boolean that holds whether the dock window can
float (i.e., detach from the main window in which
it lives)
\row
\o movable
\o boolean that holds whether the window is movable
(i.e., can move to other dock widget areas)
\row
\o title
\o the title text of the dock window
\endtable
For the buttons, QStyleOptionButton is used (see \l{Tool Buttons}
for content description). The dock widget resize handle has a
plain QStyleOption.
*/
|