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
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
|
/****************************************************************************
**
** Tutorial
**
** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
**
** This file is part of the Qt GUI Toolkit.
**
** This file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the files LICENSE.GPL2
** and LICENSE.GPL3 included in the packaging of this file.
** Alternatively you may (at your option) use any later version
** of the GNU General Public License if such license has been
** publicly approved by Trolltech ASA (or its successors, if any)
** and the KDE Free Qt Foundation.
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** This file may be used under the terms of the Q Public License as
** defined by Trolltech ASA and appearing in the file LICENSE.QPL
** included in the packaging of this file. Licensees holding valid Qt
** Commercial licenses may use this file in accordance with the Qt
** Commercial License Agreement provided with the Software.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
** herein.
**
**********************************************************************/
/*! \page tutorial.html
\title Qt Tutorial #1 - The 14 Steps
This tutorial gives an introduction to GUI programming using the Qt
toolkit. It doesn't cover everything: the emphasis is on teaching the
programming philosophy of GUI programming, and Qt's features are
introduced as needed. Some commonly used features are never used in
this tutorial.
Chapter one starts with a ten-line hello-world and each subsequent
chapter introduces one or a few more concepts. By Chapter 14, the ten
lines from Chapter 1 have turned into a 650-line game.
If you're completely new to Qt, please read \link how-to-learn-ntqt.html
How to Learn Qt\endlink if you haven't already done so.
Tutorial chapters:
\list 1
\i \link tutorial1-01.html Hello, World!\endlink
\i \link tutorial1-02.html Calling it Quits\endlink
\i \link tutorial1-03.html Family Values\endlink
\i \link tutorial1-04.html Let There Be Widgets\endlink
\i \link tutorial1-05.html Building Blocks\endlink
\i \link tutorial1-06.html Building Blocks Galore!\endlink
\i \link tutorial1-07.html One Thing Leads to Another\endlink
\i \link tutorial1-08.html Preparing for Battle\endlink
\i \link tutorial1-09.html With Cannon You Can\endlink
\i \link tutorial1-10.html Smooth as Silk\endlink
\i \link tutorial1-11.html Giving It a Shot\endlink
\i \link tutorial1-12.html Hanging in the Air the Way Bricks Don't\endlink
\i \link tutorial1-13.html Game Over\endlink
\i \link tutorial1-14.html Facing the Wall\endlink
\endlist
This little game doesn't look much like a modern GUI application. It
uses a good few of the GUI techniques, but after you've worked through
it, we recommend reading \link tutorial2.html Tutorial #2\endlink. The
second tutorial is a little more formal and covers the features of
typical application including menubars, toolbars, loading and saving,
dialogs, etc.
*/
/*! \page tutorial1-01.html
\title Qt Tutorial - Chapter 1: Hello, World!
\img t1.png Screenshot of tutorial one
This first program is a simple hello-world example. It contains only
the bare minimum you need to get a Qt application up and running.
The picture above is a snapshot of this program.
\include t1/main.cpp
\quotefile t1/main.cpp
\section1 Line-by-line Walkthrough
\skipto include
\printline qapp
This line includes the QApplication class definition. There has to be
exactly one QApplication object in every application that uses Qt.
QApplication manages various application-wide resources, such as the
default font and cursor.
\printline qpushbutton
This line includes the QPushButton class definition. The
\link hierarchy.html reference documentation \endlink for each class
mentions at the top which file needs to be included to use that class.
QPushButton is a classical GUI push button that the user can press
and release. It manages its own look and feel, like every other \l
QWidget. A widget is a user interface object that can process user
input and draw graphics. The programmer can change both the overall
\link QApplication::setStyle() look and feel\endlink and many minor
properties of it (such as color), as well as the widget's content. A
QPushButton can show either a text or a \l QPixmap.
\printline main
\printline {
The main() function is the entry point to the program. Almost always
when using Qt, main() only needs to perform some kind of initialization
before passing the control to the Qt library, which then tells the
program about the user's actions via events.
\c argc is the number of command-line arguments and \c argv is the
array of command-line arguments. This is a C/C++ feature. It is not
specific to Qt; however, Qt needs to process these arguments (see
following).
\printline QApplication
\c a is this program's QApplication. Here it is created and processes
some of the command-line arguments (such as -display under X Window).
Note that all command-line arguments recognized by Qt are removed from
\c argv (and \c argc is decremented accordingly). See the \l
QApplication::argv() documentation for details.
<strong>Note:</strong> It is essential that the QApplication object be
created before any window-system parts of Qt are used.
\printline QPushButton
Here, \e after the QApplication, comes the first window-system code: A
push button is created.
The button is set up to display the text "Hello world!" and be a
window of its own (because the constructor specifies 0 for the parent
window, inside which the button should be located).
\printline resize
The button is set up to be 100 pixels wide and 30 pixels high (plus the
window system frame). In this case we don't care about the button's
position, and we accept the default value.
\printline setMainWidget
The push button is chosen as the main widget for the application. If
the user closes a main widget, the application exits.
You don't have to have a main widget, but most programs do have one.
\printline show
A widget is never visible when you create it. You must call show() to
make it visible.
\printline exec
This is where main() passes control to Qt, and exec() will return when
the application exits.
In exec(), Qt receives and processes user and system events and passes
these on to the appropriate widgets.
\printline }
You should now try to compile and run this program.
\target compiling
\section1 Compiling
To compile a C++ application you need to create a makefile. The
easiest way to create a makefile for Qt is to use the \link
qmake-manual.book qmake\endlink build tool supplied with Qt. If you've
saved \c main.cpp in its own directory, all you have to do is:
\code
qmake -project
qmake
\endcode
The first command tells \link qmake-manual.book qmake\endlink to
create a \c .pro (project) file. The second command tells it to create
a (platform-specific) makefile based on the project file. You should
now be able to type \c make (or \c nmake if you're using Visual
Studio) and then run your first Qt application!
\section1 Behavior
When you run it, you will see a small window filled with a single
button, and on it you can read the famous words, Hello World!
\section1 Exercises
Try to resize the window. Press the button. If you're running X
Window, try running the program with the -geometry option
(for example, \c {-geometry 100x200+10+20}).
You're now ready for \link tutorial1-02.html Chapter 2.\endlink
[\link tutorial1-02.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \page tutorial1-02.html
\title Qt Tutorial - Chapter 2: Calling it Quits
\img t2.png Screenshot of tutorial two
Having created a window in \link tutorial1-01.html Chapter 1, \endlink we will
now go on to make the application quit properly when the user tells it to.
We will also use a font that is more exciting than the default one.
\include t2/main.cpp
\quotefile t2/main.cpp
\section1 Line-by-line Walkthrough
\skipto qfont
\printline qfont
Since this program uses QFont, it needs to include ntqfont.h. Qt's font
abstraction is rather different from the horror provided by X, and
loading and using fonts has been highly optimized.
\skipto QPushButton
\printline QPushButton
This time, the button says "Quit" and that's exactly what the program
will do when the user clicks the button. This is not a coincidence.
We still pass 0 as the parent, since the button is a top-level window.
\printline resize
We've chosen another size for the button since the text is a bit
shorter than "Hello world!". We could also have used \l QFontMetrics
to set right size.
\printline setFont
Here we choose a new font for the button, an 18-point bold font from
the Times family. Note that we create the font on the spot.
It is also possible to change the default font (using \l
QApplication::setFont()) for the whole application.
\printline connect
connect() is perhaps \e the most central feature of Qt.
Note that connect() is a static function in QObject. Do not confuse it
with the connect() function in the socket library.
This line establishes a one-way connection between two Qt objects (objects
that inherit QObject, directly or indirectly). Every Qt object can have
both \c signals (to send messages) and \c slots (to receive messages). All
widgets are Qt objects. They inherit QWidget which in turn inherits
QObject.
Here, the \e clicked() signal of \e quit is connected to the \e
quit() slot of \e a, so that when the button is clicked, the
application quits.
The \link signalsandslots.html Signals and Slots\endlink documentation
describes this topic in detail.
\section1 Behavior
When you run this program, you will see an even smaller window than in
Chapter 1, filled with an even smaller button.
(See \link tutorial1-01.html#compiling Compiling\endlink for how to create a
makefile and build the application.)
\section1 Exercises
Try to resize the window. Press the button. Oops! That connect()
would seem to make some difference.
Are there any other signals in QPushButton you can connect to quit?
Hint: The QPushButton inherits most of its behavior from QButton.
You're now ready for \link tutorial1-03.html Chapter 3.\endlink
[\link tutorial1-01.html Previous tutorial\endlink]
[\link tutorial1-03.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \page tutorial1-03.html
\title Qt Tutorial - Chapter 3: Family Values
\img t3.png Screenshot of tutorial three
This example shows how to create parent and child widgets.
We'll keep it simple and use just a single parent and a lone child.
\include t3/main.cpp
\quotefile t3/main.cpp
\section1 Line-by-line Walkthrough
\skipto ntqvbox.h
\printline ntqvbox.h
We add an include of ntqvbox.h to get the layout class we'll use.
\skipto QVBox
\printline QVBox
Here we simply create a vertical box container. The QVBox arranges
its child widgets in a vertical row, one above the other, handing out
space according to each child's \l QWidget::sizePolicy().
\printline resize
We set its width to 200 pixels and the height to 120 pixels.
\printline quit
A child is born.
This QPushButton is created with both a text ("Quit") and a parent
(box). A child widget is always on top of its parent. When
displayed, it is clipped by its parent's bounds.
The parent widget, the QVBox, automatically adds the child centered in
its box. Because nothing else is added, the button gets all the space
the parent has.
\skipto show
\printline show
When a parent widget is shown, it will call show for all its children
(except those on which you have done an explicit \l QWidget::hide()).
\section1 Behavior
The button no longer fills the entire widget. Instead, it gets a
"natural" size. This is because there is now a new top-level widget,
which uses the button's size hint and size change policy to set the
button's size and position. (See \l QWidget::sizeHint() and \l
QWidget::setSizePolicy() for more information about these functions.)
(See \link tutorial1-01.html#compiling Compiling\endlink for how to create a
makefile and build the application.)
\section1 Exercises
Try resizing the window. How does the button change? What is the
button's size-change policy? What happens to the button's height if
you run the program with a bigger font? What happens if you try to
make the window \e really small?
You're now ready for \link tutorial1-04.html Chapter 4.\endlink
[\link tutorial1-02.html Previous tutorial\endlink]
[\link tutorial1-04.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \page tutorial1-04.html
\title Qt Tutorial - Chapter 4: Let There Be Widgets
\img t4.png Screenshot of tutorial four
This example shows how to create your own widget, describes how to control the
minimum and maximum sizes of a widget, and introduces widget names.
\include t4/main.cpp
\quotefile t4/main.cpp
\section1 Line-by-line Walkthrough
\skipto MyWidget
\printuntil }
Here we create a new class. Because this class inherits from QWidget,
the new class is a widget and may be a top level window or a child
widget (like the push button in Chapter 3).
This class has only one member, a constructor (in addition to the
members it inherits from QWidget). The constructor is a standard Qt
widget constructor; you should always include a similar constructor
when you create widgets.
The first argument is its parent widget. To create a top-level window
you specify a null pointer as the parent. As you can see, this widget
defaults to be a top-level window.
The second argument is the widget's name. This is \e not the text
that appears in the window's title bar or in the button. It is a name
associated with a widget to make it possible to \link
QObject::queryList() look up \endlink this widget later, and there is
also a \link QObject::dumpObjectTree() handy debugging function
\endlink that will list a complete widget hierarchy.
\printline MyWidget
\printline QWidget
The implementation of the constructor starts here. Like most widgets,
it just passes on the \c parent and \c name to the QWidget
constructor.
\printuntil setMaximumSize
Because this widget doesn't know how to handle resizing, we fix its size
by setting the minimum and maximum to be equal. In the next chapter
we will show how a widget can respond to resize event from the user.
\printuntil setFont
Here we create and set up a child widget of this widget (the new widget's
parent is \c this) which has the widget name "quit". The widget
name has nothing to do with the button text; it just happens to be
similar in this case.
Note that \c quit is a local variable in the constructor. MyWidget
does not keep track of it, but Qt does, and will by default delete it
when MyWidget is deleted. This is why MyWidget doesn't need a
destructor. (On the other hand, there is no harm in deleting a child
when you choose to, the child will automatically tell Qt about its
imminent death.)
The setGeometry() call does the same as move() and resize() did in the
previous chapters.
\printline qApp
\printline }
Because the MyWidget class doesn't know about the application object, it
has to connect to Qt's pointer to it, \c qApp.
A widget is a software component and should know as little as possible
about its environment in order to be as general and reusable as
possible.
Knowing the name of the application object would break this principle,
so Qt offers an alias, qApp, for the cases in which a component such as
MyWidget needs to talk to the application object.
\printuntil }
Here we instantiate our new child, set it to be the main widget, and
execute the application.
\section1 Behavior
This program is very similar in behavior to the previous one. The
difference lies in the way we have implemented it. It does behave
slightly differently, however. Just try to resize it to see.
(See \link tutorial1-01.html#compiling Compiling\endlink for how to create a
makefile and build the application.)
\section1 Exercises
Try to create another MyWidget object in main(). What happens?
Try to add more buttons or put in widgets other than QPushButton.
You're now ready for \link tutorial1-05.html Chapter 5.\endlink
[\link tutorial1-03.html Previous tutorial\endlink]
[\link tutorial1-05.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \page tutorial1-05.html
\title Qt Tutorial - Chapter 5: Building Blocks
\img t5.png Screenshot of tutorial five
This example shows how to create and connect together several widgets
by using signals and slots, and how to handle resize events.
\include t5/main.cpp
\quotefile t5/main.cpp
\section1 Line-by-line Walkthrough
\skipto qapp
\printuntil qvbox
Three new include files are shown here. ntqslider.h and ntqlcdnumber.h are there
because we use two new widgets, QSlider and QLCDNumber. ntqvbox.h is
here because we use Qt's automatic layout support.
\skipto MyWidget
\printuntil }
\target constructor
\printuntil {
MyWidget is now derived from QVBox instead of QWidget. That way we use
the layout of the QVBox (which places all of its children vertically
inside itself). Resizes are now handled automatically by the QVBox and
therefore by MyWidget, too.
\skipto lcd
\printline lcd
\c lcd is a QLCDNumber, a widget that displays numbers in an LCD-like
fashion. This instance is set up to display two digits and to be a child of
\e this. It is named "lcd".
\printline QSlider
\printline slider
\printline slider
QSlider is a classical slider; the user can use the widget to drag
something to adjust an integer value in a range. Here we create a
horizontal one, set its range to 0-99 (inclusive, see the \l
QSlider::setRange() documentation) and its initial value to 0.
\printline connect
Here we use the \link signalsandslots.html signal/slot mechanism \endlink
to connect the slider's valueChanged() signal to the LCD number's
display() slot.
Whenever the slider's value changes it broadcasts the new value by
emitting the valueChanged() signal. Because that signal is connected to
the LCD number's display() slot, the slot is called when the signal is
broadcast. Neither of the objects knows about the other. This is
essential in component programming.
Slots are otherwise normal C++ member functions and follow the normal
C++ access rules.
\section1 Behavior
The LCD number reflects everything you do to the slider, and the
widget handles resizing well. Notice that the LCD number widget
changes in size when the window is resized (because it can), but the
others stay about the same (because otherwise they would look stupid).
(See \link tutorial1-01.html#compiling Compiling\endlink for how to create a
makefile and build the application.)
\section1 Exercises
Try changing the LCD number to add more digits or \link
QLCDNumber::setMode() to change mode.\endlink You can even add four push
buttons to set the number base.
You can also change the slider's range.
Perhaps it would have been better to use \l QSpinBox than a slider?
Try to make the application quit when the LCD number overflows.
You're now ready for \link tutorial1-06.html Chapter 6.\endlink
[\link tutorial1-04.html Previous tutorial\endlink]
[\link tutorial1-06.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \page tutorial1-06.html
\title Qt Tutorial - Chapter 6: Building Blocks Galore!
\img t6.png Screenshot of tutorial six
This example shows how to encapsulate two widgets into a new component and
how easy it is to use many widgets. For the first time, we use a custom
widget as a child widget.
\target main
\include t6/main.cpp
\quotefile t6/main.cpp
\section1 Line-by-line Walkthrough
\skipto LCDRange
\printuntil };
The LCDRange widget is a widget without any API. It just has a
constructor. This sort of widget is not very useful, so we'll add some API later.
\printuntil }
This is lifted straight from the
\link tutorial1-05.html#constructor MyWidget constructor \endlink in Chapter 5.
The only differences are that the button is left out and the class
is renamed.
\printline MyWidget
\printuntil }
MyWidget, too, contains no API except a constructor.
\printline MyWidget
\printuntil connect
The push button that used to be in what is now LCDRange has been
separated so that we can have one "Quit" button and many LCDRange
objects.
\printline grid
We create a QGrid object with four columns. The QGRid widget
automatically arranges its children in rows and columns; you can
specify the number of rows or of columns, and QGrid will discover its
new children and fit them into the grid.
\printline for
\printline for
\printline LCDRange
Four columns, four rows.
We create 4*4 LCDRanges, all of which are children of the grid object.
The QGrid widget will arrange them.
\printline }
That's all.
\section1 Behavior
This program shows how easy it is to use many widgets at a time. Each
one behaves like the slider and LCD number in the previous
chapter. Again, the difference lies in the implementation.
(See \link tutorial1-01.html#compiling Compiling\endlink for how to create a
makefile and build the application.)
\section1 Exercises
Initialize each slider with a different/random value on startup.
The source contains three occurrences of "4". What happens if you
change the one in the \l QGrid constructor call? What about the other
two? Why is this?
You're now ready for \link tutorial1-07.html Chapter 7.\endlink
[\link tutorial1-05.html Previous tutorial\endlink]
[\link tutorial1-07.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \file t7/lcdrange.h */
/*! \file t7/lcdrange.cpp */
/*! \file t7/main.cpp */
/*! \page tutorial1-07.html
\title Qt Tutorial - Chapter 7: One Thing Leads to Another
\img t7.png Screenshot of tutorial seven
This example shows how to create custom widgets with signals and
slots, and how to connect them together in more complex ways. For the
first time, the source is split among several files which we've placed
in the \c t7 subdirectory.
\list
\i \l t7/lcdrange.h contains the LCDRange class definition.
\i \l t7/lcdrange.cpp contains the LCDRange implementation.
\i \l t7/main.cpp contains MyWidget and main.
\endlist
\section1 Line-by-line Walkthrough
\section2 \l t7/lcdrange.h
This file is mainly lifted from \link tutorial1-06.html#main main.cpp \endlink in
Chapter 6; only the changes are noted here.
\quotefile t7/lcdrange.h
\skipto ifndef
\printuntil define
This is the classic C construction to avoid errors if a header file
happens to be included more than once. If you don't use it already,
it is a very good habit to develop. The #ifndef should enclose \e all of the
header file.
\printline include
\c ntqvbox.h is included. LCDRange inherits QVBox, and the header file
of a parent class must always be included. We cheated a bit in the
previous chapters, and we let \c ntqwidget.h be included indirectly via
other header files such as \c ntqpushbutton.h.
\printline QSlider
This is another classic trick, but one that's much less used often. Because
we don't need QSlider in the \e interface of the class, only in the
implementation, we use a forward declaration of the class in the
header file and include the header file for QSlider in the .cpp
file.
This makes the compilation of big projects much faster, because when a
header file has changed, fewer files need to be recompiled. It can
often speed up big compilations by a factor of two or more.
\skipto LCDRange
\printuntil parent=0
Note the Q_OBJECT. This macro must be included in \e all classes that
contain signals and/or slots. If you are curious, it defines the
functions that are implemented in the
\link metaobjects.html meta object file \endlink.
\printline value
\printuntil valueChanged
These three members make up an interface between this widget and other
components in a program. Until now, LCDRange didn't really have an
interface at all.
value() is a public function for accessing the value of the LCDRange.
setValue() is our first custom slot and valueChanged() is our first
custom signal.
Slots must be implemented in the normal way (remember that a slot is also
a C++ member function). Signals are automatically implemented in the
\link signalsandslots.html meta object\endlink file. Signals follow the
access rules of protected C++ functions (i.e., they can be emitted only
by the class they are defined in or by classes inheriting from it).
The signal valueChanged() is used when the LCDRange's value has
changed - just as you guessed from the name. This is not the last
signal you'll see called <i>something</i>Changed().
\section2 \l t7/lcdrange.cpp
\quotefile t7/lcdrange.cpp
This file is mainly lifted from \link tutorial1-06.html#main t6/main.cpp \endlink, and
only the changes are noted here.
\skipto connect
\printline connect
\printline display
\printline connect
\printline valueChanged
This code is from the LCDRange constructor.
The first connect is the same that you have seen in the previous chapter.
The second is new; it connects slider's valueChanged() signal to this
object's valueChanged \e signal. Connect() with 3 arguments always
connects to signals or slots in \c this object.
Yes, that's right. Signals can be connected to other signals. When
the first is emitted, the second signal is also emitted.
Let's look at what happens when the user operates the slider. The
slider sees that its value has changed and emits the valueChanged()
signal. That signal is connected both to the display() slot of the
QLCDNumber and to the valueChanged() signal of the LCDRange.
Thus, when the signal is emitted, LCDRange emits its own
valueChanged() signal. In addition, QLCDNumber::display() is called
and shows the new number.
Note that you're not guaranteed any particular order of execution -
LCDRange::valueChanged() may be emitted before or after
QLCDNumber::display()and is entirely arbitrary.
\skipto LCDRange::value
\printuntil }
The implementation of value() is straightforward; it simply returns
the slider's value.
\printline setValue
\printuntil }
The implementation of setValue() is equally straightforward. Note
that because the slider and LCD number are connected, setting the
slider's value automatically updates the LCD number as well. In
addition, the slider will automatically adjust the value if it is
outside its legal range.
\section2 \l t7/main.cpp
\quotefile t7/main.cpp
\skipto previous
\printline previous
\printuntil setValue
\printline previous
\printline }
\printline }
All of main.cpp is copied from the previous chapter except in
the constructor for MyWidget. When we create the 16 LCDRange object, we
now connect them using the \link signalsandslots.html
signal/slot\endlink mechanism. Each has its valueChanged() signal
connected to the setValue() slot in the previous one. Because LCDRange
emits the signal valueChanged() when its value changes (surprise!), we
are here creating a "chain" of signals and slots.
\target compiling
\section1 Compiling
Creating a makefile for a multi-file application is no different from
creating one for a single-file application. If you've saved all the
files in this example in their own directory, all you have to do is:
\code
qmake -project
qmake
\endcode
The first command tells \link qmake-manual.book qmake\endlink to
create a \c .pro (project) file. The second command tells it to create
a (platform-specific) makefile based on the project file. You should
now be able to type \c make (or \c nmake if you're using Visual
Studio) to build your application.
\section1 Behavior
On startup, the program's appearance is identical to the previous one.
Try operating the slider to the bottom right...
\section1 Exercises
Use the bottom right slider to set all LCDs to 50. Then set the top
half to 40 by clicking once to the left of the slider handle. Now,
use the one to the left of the last one operated to set the first
seven LCDs back to 50.
Click to the left of the handle on the bottom right slider. What
happens? Why is this the correct behavior?
You're now ready for \link tutorial1-08.html Chapter 8.\endlink
[\link tutorial1-06.html Previous tutorial\endlink]
[\link tutorial1-08.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \file t8/lcdrange.h */
/*! \file t8/lcdrange.cpp */
/*! \file t8/cannon.h */
/*! \file t8/cannon.cpp */
/*! \file t8/main.cpp */
/*! \page tutorial1-08.html
\title Qt Tutorial - Chapter 8: Preparing for Battle
\img t8.png Screenshot of tutorial eight
In this example, we introduce the first custom widget that can paint
itself. We also add a useful keyboard interface (with two lines of
code).
\list
\i \l t8/lcdrange.h contains the LCDRange class definition.
\i \l t8/lcdrange.cpp contains the LCDRange implementation.
\i \l t8/cannon.h contains the CannonField class definition.
\i \l t8/cannon.cpp contains the CannonField implementation.
\i \l t8/main.cpp contains MyWidget and main.
\endlist
\section1 Line-by-line Walkthrough
\section2 \l t8/lcdrange.h
This file is very similar to the lcdrange.h in Chapter 7. We have added
one slot: setRange().
\quotefile t8/lcdrange.h
\skipto setRange
\printline setRange
We now add the possibility of setting the range of the LCDRange.
Until now, it has been fixed at 0..99.
\section2 \l t8/lcdrange.cpp
\quotefile t8/lcdrange.cpp
There is a change to the constructor (we'll discuss that later).
\skipto ::setRange
\printuntil slider
\printline }
SetRange() sets the range of the slider in the LCDRange. Because we
have set up the QLCDNumber to always display two digits, we want to
limit the possible range of \c minVal and \c maxVal to 0..99 to avoid
overflow of the QLCDNumber. (We could have allowed values down to -9
but chose not to.) If the arguments are illegal, we use Qt's
qWarning() function to issue a warning to the user and return
immediately. qWarning() is a printf-like function that by default
sends its output to \c stderr. If you want, you can install your own handler
function using \l ::qInstallMsgHandler().
\section2 \l t8/cannon.h
CannonField is a new custom widget that knows how to display itself.
\quotefile t8/cannon.h
\skipto include
\skipto class
\printuntil parent=0
CannonField inherits QWidget, and we use the same idiom as for LCDRange.
\printuntil angleChanged
For the time being, CannonField only contains an angle value for which we
provide an interface using the same idiom as for value in LCDRange.
\printline protected
\printline paintEvent
This is the second of the many event handlers in QWidget that we
encounter. This virtual function is called by Qt whenever a widget needs
to update itself (i.e., paint the widget's surface).
\section2 \l t8/cannon.cpp
\quotefile t8/cannon.cpp
\skipto ::CannonField
\printuntil {
Again, we use the same idiom as for LCDRange in the previous chapter.
\printuntil }
The constructor initializes the angle value to 45 degrees and sets a
custom palette for this widget.
This palette uses the indicated color as background and picks other
colors suitably. (For this widget only the background and text
colors will actually be used.)
\skipto ::setAngle
\printuntil emit
\printline }
This function sets the angle value. We have chosen a legal range of
5..70 and adjust the given number of degrees accordingly. We have
chosen not to issue a warning if the new angle is out of range.
If the new angle equals the old one, we return immediately. It is
important to only emit the signal angleChanged() when the angle \e
really has changed.
Then we set the new angle value and repaint our widget. The \l
QWidget::repaint() function clears the widget (usually filling it with
its background color) and sends a paint event to the widget. This
results in a call to the paint event function of the widget.
Finally, we emit the angleChanged() signal to tell the outside world
that the angle has changed. The \c emit keyword is unique to Qt and
not regular C++ syntax. In fact, it is a macro.
\skipto ::paintEvent
\printuntil drawText
\printline }
This is our first attempt to write a paint event handler. The event
argument contains a description of the paint event. \l QPaintEvent
contains the region in the widget that must be updated. For the time
being, we will be lazy and just paint everything.
Our code displays the angle value in the widget at a fixed position.
First we create a QString with some text and the angle; then we create
a QPainter operating on this widget and use it to paint the string.
We'll come back to QPainter later; it can do a great many things.
\section2 \l t8/main.cpp
\quotefile t8/main.cpp
\skipto cannon.h
\printline cannon.h
We include our new class.
\skipto MyWidget
\printuntil };
This time we include a single LCDRange and a CannonField in our top-level
widget.
\skipto angle
\printline angle
In the constructor, we create and set up our LCDRange.
\printline setRange
We set the LCDRange to accept ranges from 5 to 70 degrees.
\printline cannonField
\printline CannonField
We create our CannonField.
\printuntil setValue
Here we connect the valueChanged() signal of the LCDRange to the
setAngle() slot of the CannonField. This will update CannonField's angle
value whenever the user operates the LCDRange. We also make the reverse
connection so that changing the angle in the CannonField will update the
LCDRange value. In our example we never change the angle of the
CannonField directly; but by doing the last connect() we ensure that no
future changes will disrupt the synchronization between those two values.
This illustrates the power of component programming and proper
encapsulation.
Notice how important it is to emit the angleChanged() signal only when
the angle actually changes. If both the LCDRange and the CannonField
had omitted this check, the program would have entered an infinite
loop upon the first change of one of the values.
\printline QGridLayout
\printline 2x2
So far we have used the no-assembly-required QVBox and QGrid widgets
for geometry management. Now, however, we want to have a little more
control over the layout, and we switch to the more powerful QGridLayout
class. QGridLayout isn't a widget; it is a different class that can
manage the children of \e any widget.
As the comment indicates, we create a two-by-two array with ten pixel
borders. (The constructor for \l QGridLayout can be a little cryptic,
so it's good to put in such comments.)
\printline addWidget
We add the Quit button in the top-left cell of the grid: 0, 0.
\printline addWidget
We put the angle LCDRange in the bottom-left cell, aligned to the top
of its cell. (This alignment is one of the things QGridLayout allows
but QGrid does not allow.)
\printline addWidget
We put the CannonField object in the bottom-right cell. (The top-
right cell is empty.)
\printline setColStretch
We tell QGridLayout that the right column (column 1) is stretchable.
Because the left column isn't (it has stretch factor 0, the default
value), QGridLayout will try to let the left-hand widgets' sizes be
unchanged and will resize just the CannonField when the MyWidget is
resized.
\printline setValue
We set an initial angle value. Note that this will trigger the
connection from LCDRange to CannonField.
\printline setFocus
Our last action is to set \c angle to have keyboard focus so that
keyboard input will go to the LCDRange widget by default.
LCDRange does not contain any keyPressEvent(), so that would seem not
to be terribly useful. However, its constructor just got a new line:
\quotefile t8/lcdrange.cpp
\skipto setFocusProxy
\printline setFocusProxy
The LCDRange sets the slider to be its focus proxy. That means that
when someone (the program or the user) wants to give the LCDRange
keyboard focus, the slider should take care of it. QSlider has a decent
keyboard interface, so with just one line of code we've given LCDRange
one.
\section1 Behavior
The keyboard now does something - the arrow keys, Home, End, PageUp
and PageDown all do something vaguely sensible.
When the slider is operated, the CannonField displays the new angle
value. Upon resizing, CannonField is given as much space as possible.
On Windows machines with an 8-bit display the new background color is
dithered to death. The next chapter works around this.
(See \link tutorial1-07.html#compiling Compiling\endlink for how to create a
makefile and build the application.)
\section1 Exercises
Try to resize the window. What happens if you make it really narrow
or really squat?
If you remove the AlignTop, what happens to the LCDRange's position
and size? Why?
If you give the left-hand column a non-zero stretch factor, what
happens when you resize the window?
Leave out the setFocus() call. Which behavior do you prefer?
Try to change "Quit" to "&Quit" in the QButton::setText() call. How
does the button's look change? What happens if you press Alt+Q while
the program's running? (It is Meta+Q on a few keyboards.)
Center the text in the CannonField.
You're now ready for \link tutorial1-09.html Chapter 9.\endlink
[\link tutorial1-07.html Previous tutorial\endlink]
[\link tutorial1-09.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \file t9/lcdrange.h */
/*! \file t9/lcdrange.cpp */
/*! \file t9/cannon.h */
/*! \file t9/cannon.cpp */
/*! \file t9/main.cpp */
/*! \page tutorial1-09.html
\title Qt Tutorial - Chapter 9: With Cannon You Can
\img t9.png Screenshot of tutorial nine
In this example we become graphic by drawing a cute little blue
cannon. Only cannon.cpp differs from the previous chapter.
\list
\i \l t9/lcdrange.h contains the LCDRange
class definition.
\i \l t9/lcdrange.cpp contains the LCDRange
implementation.
\i \l t9/cannon.h contains the CannonField class
definition.
\i \l t9/cannon.cpp contains the CannonField
implementation.
\i \l t9/main.cpp contains MyWidget and main.
\endlist
\section1 Line-by-line Walkthrough
\section2 \l t9/cannon.cpp
\quotefile t9/cannon.cpp
\skipto ::paintEvent
\printuntil QPainter
We'll now start to use QPainter in earnest. We create a painter that
operates on this widget.
\printline setBrush
When QPainter fills a rectangle, a circle, or whatever, it fills the
shape using its brush. Here we set it to use a blue brush. (We
could also use a pattern.)
\printline setPen
And the edges of what QPainter draws are drawn using the pen. Here we
set it to NoPen, meaning that there will be no special edge when we
draw something; the blue brush will go all the way to the edges of
the things we draw.
\skipto translate
\printline translate
The \l QPainter::translate() function translates the coordinate
system of the QPainter; i.e., it moves it by an offset. Here we set
the (0, 0) point to the bottom-left corner of the widget. The x and
y directions remain unchanged, i.e., all the y coordinates inside the
widget are now negative (see \link coordsys.html The Coordinate
System\endlink for more information about Qt's coordinate system).
\printline drawPie
The drawPie() function draws a pie shape inside the specified
rectangle using a start angle and an arc length. The angles are
specified in 1/16th of a degree. Zero degrees is at the 3 o'clock
position. The drawing direction is counter-clockwise. Here we draw a
quarter of a circle in the bottom-left corner of the widget. The pie
is filled with blue and has no outline.
\printline rotate
The QPainter::rotate() function rotates the coordinate system of the
QPainter around the origin. The rotation argument is a \c float given
in degrees (not given in 1/16th of a degree as above) and clockwise.
Here we rotate the coordinate system \c ang degrees counter-clockwise.
\printline drawRect
The QPainter::drawRect() function draws the specified rectangle. Here
we draw the barrel of the cannon.
It can often be difficult to envision the resulting drawing when the
coordinate system has been transformed (translated, rotated, scaled, or
sheared) as above.
In this case the coordinate system is first translated and then rotated.
If the rectangle QRect(33, -4, 15, 8) had been drawn in the translated
coordinate system, it would have looked like this:
\img t9_1.png The cannon translated but not rotated
Note that the rectangle is clipped by the border of the CannonField
widget. When we rotate the coordinate system, for instance 60
degrees, the rectangle will be rotated around (0, 0), which is the
bottom-left corner because we have translated the coordinate system.
The result looks like this:
\img t9_2.png The cannon translated and rotated
We're done, except that we haven't explained why Windows didn't dither
this time.
\quotefile t9/main.cpp
\skipto main
\printline main
\printline {
\printline CustomColor
\printline QApplication
We tell Qt that we want a different color-allocation strategy for this
program. There is no single correct color-allocation strategy. Because
this program uses an unusual yellow but not many colors, \c
CustomColor is best. There are several other allocation strategies; you can read about them in the \l QApplication::setColorSpec()
documentation.
Mostly you can ignore this, since the default is good. Occasionally
some applications with unusual color use look bad; changing the
allocation strategy often helps then.
\section1 Behavior
When the slider is operated the angle of the drawn cannon changes
accordingly.
The Q on the Quit button is now underlined, and Alt+Q does what you
think it does. If you do not know why, you didn't do the exercises in
Chapter 8.
You may notice that the cannon flickers annoyingly, especially on a
slow machine. We'll fix this in the next chapter.
(See \link tutorial1-07.html#compiling Compiling\endlink for how to create a
makefile and build the application.)
\section1 Exercises
Set a different pen instead of NoPen. Set a patterned brush.
Try "Q&uit" or "Qu&it" as button text instead of "&Quit". What
happens?
You're now ready for \link tutorial1-10.html Chapter 10.\endlink
[\link tutorial1-08.html Previous tutorial\endlink]
[\link tutorial1-10.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \file t10/lcdrange.h */
/*! \file t10/lcdrange.cpp */
/*! \file t10/cannon.h */
/*! \file t10/cannon.cpp */
/*! \file t10/main.cpp */
/*! \page tutorial1-10.html
\title Qt Tutorial - Chapter 10: Smooth as Silk
\img t10.png Screenshot of tutorial ten
In this example, we introduce painting in a pixmap to remove flickering.
We also add a force control.
\list
\i \l t10/lcdrange.h contains the LCDRange
class definition.
\i \l t10/lcdrange.cpp contains the LCDRange
implementation.
\i \l t10/cannon.h contains the CannonField class
definition.
\i \l t10/cannon.cpp contains the CannonField
implementation.
\i \l t10/main.cpp contains MyWidget and main.
\endlist
\section1 Line-by-line Walkthrough
\section2 \l t10/cannon.h
The CannonField now has a force value in addition to the angle.
\quotefile t10/cannon.h
\skipto angle
\printuntil forceChanged
The interface to the force follows the same practice as for the angle.
\skipto private
\printuntil cannonRect
We have put the definition of the cannon's enclosing rectangle in a
separate function.
\skipto ang
\printuntil };
The force is stored in the integer \c f.
\section2 \l t10/cannon.cpp
\quotefile t10/cannon.cpp
\skipto include
\skipto pixmap
\printline pixmap
We include the QPixmap class definition.
\skipto ::CannonField
\printuntil }
The force (\c f) is initialized to zero.
\skipto ::setAngle
\printuntil }
We have made a slight change in the setAngle() function. It repaints
only the portion of the widget that contains the cannon. The FALSE
argument indicates that the specified rectangle should not be erased
before a paint event is sent to the widget. This speeds up and smooths
the drawing a little bit.
\skipto ::setForce
\printuntil }
The implementation of setForce() is quite similar to that of
setAngle(). The only difference is that because we don't show the force
value, we don't need to repaint the widget.
\skipto ::paintEvent
\printuntil return
We have now optimized the paint event to repaint only the parts of the
widget that need updating. First we check whether we have to paint
anything at all, and we return if we don't.
\printline cannonRect
\printline pix
Then we create a temporary pixmap, which we use for flicker-free
painting. All the painting operations are done into this pixmap, and
then the pixmap is drawn on the screen in a single operation.
This is the essence of flicker-free drawing: Draw on each pixel
precisely once. Less, and you get drawing errors. More, and you get
flicker. It doesn't matter much in this example - when the code was
written there were still machines slow enough for it to flicker, but
not any more. We've kept the code for educational purposes.
\printline fill
We fill the pixmap with the background from this widget.
\printline QPainter
\printuntil end
We paint, as in Chapter 9, but now we paint in the pixmap.
At this point, we have a painter variable and a pixmap that looks
precisely right, but we still haven't painted on the screen.
\printline begin
\printline drawPixmap
So we open the painter on the CannonField itself and then draw the pixmap.
That's all. A couple of extra lines at the top and a couple at the
bottom, and the code is 100% flicker-free.
\skipto cannonRect
\printuntil }
This function returns the rectangle enclosing the cannon in widget
coordinates. First we create a rectangle with the size 50x50 and then
move it so its bottom left corner is equal to the widget's own bottom-
left corner.
The \l QWidget::rect() function returns the widget's enclosing
rectangle in the widget's own coordinates (where the top left corner
is 0, 0).
\section2 \l t10/main.cpp
\quotefile t10/main.cpp
\skipto MyWidget::MyWidget
\printuntil {
The constructor is mostly the same, but some new bits have been added.
\skipto force
\printline force
\printline force
We add a second LCDRange, which will be used to set the force.
\skipto force
\printline connect
\printline cannonField
\printline connect
\printline force
We connect the \c force widget and the \c cannonField widget, just like
we did for the \c angle widget.
\skipto QVBoxLayout
\printline QVBoxLayout
\printline addLayout
\printline addWidget
\printline addWidget
In Chapter 9 we put \c angle in the lower-left cell of the layout.
Now we want to have two widgets in that cell, so we make a vertical
box, put the vertical box in the grid cell, and put each of \c angle
and \c range in the vertical box.
\skipto force
\printline setValue
We initialize the force value to 25.
\section1 Behavior
The flicker has gone and we have a force control.
(See \link tutorial1-07.html#compiling Compiling\endlink for how to create a
makefile and build the application.)
\section1 Exercises
Make the size of the cannon barrel be dependent on the force.
Put the cannon in the bottom-right corner.
Try adding a better keyboard interface. For example, make + and -
increase and decrease the force and enter shoot. Hint: \l QAccel and
new addStep() and subtractStep() slots in LCDRange, like \l
QSlider::addStep(). If you're bothered by the way the left and right
keys work (I am!), change that too.
You're now ready for \link tutorial1-11.html Chapter 11.\endlink
[\link tutorial1-09.html Previous tutorial\endlink]
[\link tutorial1-11.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \file t11/lcdrange.h */
/*! \file t11/lcdrange.cpp */
/*! \file t11/cannon.h */
/*! \file t11/cannon.cpp */
/*! \file t11/main.cpp */
/*! \page tutorial1-11.html
\title Qt Tutorial - Chapter 11: Giving It a Shot
\img t11.png Screenshot of tutorial eleven
In this example we introduce a timer to implement animated shooting.
\list
\i \l t11/lcdrange.h contains the LCDRange
class definition.
\i \l t11/lcdrange.cpp contains the LCDRange
implementation.
\i \l t11/cannon.h contains the CannonField class
definition.
\i \l t11/cannon.cpp contains the CannonField
implementation.
\i \l t11/main.cpp contains MyWidget and main.
\endlist
\section1 Line-by-line Walkthrough
\section2 \l t11/cannon.h
The CannonField now has shooting capabilities.
\quotefile t11/cannon.h
\skipto shoot
\printline shoot
Calling this slot will make the cannon shoot if a shot is not in the air.
\printline private
\printline moveShot
This private slot is used to move the shot while it is in the air,
using a \l QTimer.
\skipto private
\printline private
\printline paintShot
This private function paints the shot.
\skipto shotRect
\printline shotRect
This private function returns the shot's enclosing rectangle if
one is in the air; otherwise the returned rectangle is undefined.
\skipto timerCount
\printuntil shoot_f
\printline };
These private variables contain information that describes the shot. The
\c timerCount keeps track of the time passed since the shot was fired.
The \c shoot_ang is the cannon angle and \c shoot_f is the cannon force
when the shot was fired.
\section2 \l t11/cannon.cpp
\quotefile t11/cannon.cpp
\skipto include
\skipto math
\printline math
We include the math library because we need the sin() and cos() functions.
\skipto ::CannonField
\printuntil }
We initialize our new private variables and connect the \l
QTimer::timeout() signal to our moveShot() slot. We'll move the
shot every time the timer times out.
\skipto ::shoot
\printuntil start
\printline }
This function shoots a shot unless a shot is in the air. The \c timerCount
is reset to zero. The \c shoot_ang and \c shoot_f are set to the current
cannon angle and force. Finally, we start the timer.
\skipto ::moveShot
\printuntil repaint
\printline }
moveShot() is the slot that moves the shot, called every 50
milliseconds when the QTimer fires.
Its tasks are to compute the new position, repaint the screen with the
shot in the new position, and if necessary, stop the timer.
First we make a \l QRegion that holds the old shotRect(). A QRegion
is capable of holding any sort of region, and we'll use it here to
simplify the painting. ShotRect() returns the rectangle where the
shot is now - it is explained in detail later.
Then we increment the \c timerCount, which has the effect of moving the
shot one step along its trajectory.
Next we fetch the new shot rectangle.
If the shot has moved beyond the right or bottom edge of the widget, we
stop the timer or we add the new shotRect() to the QRegion.
Finally, we repaint the QRegion. This will send a single paint event
for just the one or two rectangles that need updating.
\skipto ::paintEvent
\printuntil }
The paint event function has been split in two since the previous
chapter. Now we fetch the bounding rectangle of the region that
needs painting, check whether it intersects either the cannon and/or
the shot, and if necessary, call paintCannon() and/or paintShot().
\skipto ::paintShot
\printuntil drawRect
\printline }
This private function paints the shot by drawing a black filled rectangle.
We leave out the implementation of paintCannon(); it is the same as
the paintEvent() from the previous chapter.
\skipto ::shotRect
\printuntil return
\printline }
This private function calculates the center point of the shot and returns
the enclosing rectangle of the shot. It uses the initial cannon force and
angle in addition to \c timerCount, which increases as time passes.
The formula used is the classical Newtonian formula for frictionless
movement in a gravity field. For simplicity, we've chosen to
disregard any Einsteinian effects.
We calculate the center point in a coordinate system where y
coordinates increase upward. After we have calculated the center
point, we construct a QRect with size 6x6 and move its center point to
the point calculated above. In the same operation we convert the
point into the widget's coordinate system (see \link coordsys.html The
Coordinate System\endlink).
The qRound() function is an inline function defined in ntqglobal.h (included
by all other Qt header files). qRound() rounds a double to the closest
integer.
\section2 \l t11/main.cpp
\quotefile t11/main.cpp
\skipto class
\printuntil };
The only addition is the Shoot button.
\skipto ::MyWidget
\skipto shoot
\printuntil setFont
In the constructor we create and set up the Shoot button exactly like we
did with the Quit button. Note that the first argument to the constructor
is the button text, and the third is the widget's name.
\skipto connect
\printline connect
Connects the clicked() signal of the Shoot button to the shoot() slot
of the CannonField.
\section1 Behavior
The cannon can shoot, but there's nothing to shoot at.
(See \link tutorial1-07.html#compiling Compiling\endlink for how to create a
makefile and build the application.)
\section1 Exercises
Make the shot a filled circle. Hint: \l QPainter::drawEllipse() may
help.
Change the color of the cannon when a shot is in the air.
You're now ready for \link tutorial1-12.html Chapter 12.\endlink
[\link tutorial1-10.html Previous tutorial\endlink]
[\link tutorial1-12.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \file t12/lcdrange.h */
/*! \file t12/lcdrange.cpp */
/*! \file t12/cannon.h */
/*! \file t12/cannon.cpp */
/*! \file t12/main.cpp */
/*! \page tutorial1-12.html
\title Qt Tutorial - Chapter 12: Hanging in the Air the Way Bricks Don't
\img t12.png Screenshot of tutorial twelve
In this example, we extend our LCDRange class to include a text label.
We also provide something to shoot at.
\list
\i \l t12/lcdrange.h contains the LCDRange
class definition.
\i \l t12/lcdrange.cpp contains the LCDRange
implementation.
\i \l t12/cannon.h contains the CannonField class
definition.
\i \l t12/cannon.cpp contains the CannonField
implementation.
\i \l t12/main.cpp contains MyWidget and main.
\endlist
\section1 Line-by-line Walkthrough
\section2 \l t12/lcdrange.h
The LCDRange now has a text label.
\quotefile t12/lcdrange.h
\skipto QLabel
\printline QLabel
We name declare QLabel because we want to use a pointer to it in the class
definition.
\skipto class
\printuntil parent=0
\printline parent=0
\printline name=0
We have added a new constructor that sets the label text in addition to
the parent and name.
\skipto text
\printline text
This function returns the label text.
\skipto setText
\printline setText
This slot sets the label text.
\skipto private
\printuntil init
Because we now have two constructors, we have chosen to put the common
initialization in the private init() function.
\skipto QLabel
\printline label
We also have a new private variable: a QLabel. QLabel is one of Qt's
standard widgets and can show a text or a pixmap with or without a
frame.
\section2 \l t12/lcdrange.cpp
\quotefile t12/lcdrange.cpp
\skipto qlabel
\printline include
Here we include the QLabel class definition.
\skipto ::LCDRange
\printuntil }
This constructor calls the init() function, which contains the common
initialization code.
\skipto ::LCDRange
\printuntil }
This constructor first calls init() and then sets the label text.
\skipto ::init
\printuntil }
The setup of \c lcd and \c slider is the same as in the previous
chapter. Next we create a QLabel and tell it to align the contents
centered (both vertically and horizontally). The connect() statements
have also been taken from the previous chapter.
\skipto ::text
\printuntil }
This function returns the label text.
\skipto ::setText
\printuntil }
This function sets the label text.
\section2 \l t12/cannon.h
The CannonField now has two new signals: hit() and missed(). In addition
it contains a target.
\quotefile t12/cannon.h
\skipto slots
\skipto newTarget
\printline newTarget
This slot creates a target at a new position.
\skipto signals
\printuntil missed
The hit() signal is emitted when a shot hits the target. The missed()
signal is emitted when the shot moves beyond the right or bottom edge
of the widget (i.e., it is certain that it has not and will not
hit the target).
\skipto paintTarget
\printline paintTarget
This private function paints the target.
\skipto targetRect
\printline targetRect
This private function returns the enclosing rectangle of the target.
\skipto target
\printline target
This private variable contains the center point of the target.
\section2 \l t12/cannon.cpp
\quotefile t12/cannon.cpp
\skipto qdatetime
\printline qdatetime
We include the QDate, QTime, and QDateTime class definitions.
\skipto stdlib
\printline stdlib
We include the stdlib library because we need the rand() function.
\skipto newTarget
\printline newTarget
This line has been added to the constructor. It creates a "random"
position for the target. In fact, the newTarget() function will try
to paint the target. Because we are in a constructor, the CannonField
widget is invisible. Qt guarantees that no harm is done when calling
repaint() on a hidden widget.
\skipto ::newTarget
\printuntil repaint
\printline }
This private function creates a target center point at a new "random"
position.
We use the rand() function to fetch random integers. The rand() function
normally returns the same series of numbers each time you run a program.
This would make the target appear at the same position every time. To
avoid this, we must set a random seed the first time this function is
called. The random seed must also be random in order to avoid equal random
number series. The solution is to use the number of seconds that have
passed since midnight as a pseudo-random value.
First we create a static bool local variable. A static variable like
this one is guaranteed to keep its value between calls to the function.
The \c if test will succeed only the first time this function is called
because we set \c first_time to FALSE inside the \c if block.
Then we create the QTime object \c midnight, which represents the time
00:00:00. Next we fetch the number of seconds from midnight until
now and use it as a random seed. See the documentation for \l QDate,
\l QTime, and \l QDateTime for more information.
Finally we calculate the target's center point. We keep it within
the rectangle (x=200, y=35, width=190, height=255), (i.e., the
possible x and y values are x = 200..389 and y = 35..289) in a
coordinate system where we put y position 0 at the bottom edge of the
widget and let y values increase upwards X is as normal, with 0 at
the left edge and with x values increasing to the right.
By experimentation we have found this to always be in reach of the shot.
Note that rand() returns a random integer >= 0.
\skipto ::moveShot
\printuntil QRect
This part of the timer event has not changed from the previous chapter.
\printuntil hit
This \c if statement checks whether the shot rectangle intersects the
target rectangle. If it does, the shot has hit the target (ouch!).
We stop the shoot timer and emit the hit() signal to tell the outside
world that a target was destroyed, and return.
Note that we could have created a new target on the spot, but because the
CannonField is a component we leave such decisions to the user of the
component.
\printuntil missed
This \c if statement is the same as in the previous chapter, except that
it now emits the missed() signal to tell the outside world about the
failure.
\printuntil }
And the rest of the function is as before.
CannonField::paintEvent() is as before, except that this has been
added:
\skipto ::paintEvent
\skipto targetRect
\printline updateR
\printline paintTarget
These two lines make sure that the target is also painted when necessary.
\skipto ::paintTarget
\printuntil }
This private function paints the target; a rectangle filled with red and
with a black outline.
\skipto ::targetRect
\printuntil }
This private function returns the enclosing rectangle of the target.
Remember from newTarget() that the \c target point uses y coordinate 0 at
the bottom of the widget. We calculate the point in widget coordinates
before we call \l QRect::moveCenter().
The reason we have chosen this coordinate mapping is to fix the distance
between the target and the bottom of the widget. Remember that the widget
can be resized by the user or the program at any time.
\section2 \l t12/main.cpp
\quotefile t12/main.cpp
There are no new members in the MyWidget class, but we have slightly
changed the constructor to set the new LCDRange text labels.
\skipto ::MyWidget
\skipto angle
\printline ANGLE
We set the angle text label to "ANGLE".
\skipto force
\printline FORCE
We set the force text label to "FORCE".
\section1 Behavior
The LCDRange widgets look a bit strange - the built-in layout
management in QVBox gives the labels too much space and the rest not
enough. We'll fix that in the next chapter.
(See \link tutorial1-07.html#compiling Compiling\endlink for how to create a
makefile and build the application.)
\section1 Exercises
Make a cheat button that, when pressed, makes the CannonField display
the shot trajectory for five seconds.
If you did the "round shot" exercise from the previous chapter, try
changing the shotRect() to a shotRegion() that returns a \l QRegion so
you can have really accurate collision detection.
Make a moving target.
Make sure that the target is always created entirely on-screen.
Make sure that the widget cannot be resized so that the target isn't
visible. Hint: \l QWidget::setMinimumSize() is your friend.
Not easy; make it possible to have several shots in the air at the
same time. Hint: make a Shot object.
You're now ready for \link tutorial1-13.html Chapter 13.\endlink
[\link tutorial1-11.html Previous tutorial\endlink]
[\link tutorial1-13.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \file t13/lcdrange.h */
/*! \file t13/lcdrange.cpp */
/*! \file t13/cannon.h */
/*! \file t13/cannon.cpp */
/*! \file t13/gamebrd.h */
/*! \file t13/gamebrd.cpp */
/*! \file t13/main.cpp */
/*! \page tutorial1-13.html
\title Qt Tutorial - Chapter 13: Game Over
\img t13.png Screenshot of tutorial thirteen
In this example we start to approach a real playable game with a
score. We give MyWidget a new name (GameBoard) and add some slots.
We put the definition in gamebrd.h and the implementation in gamebrd.cpp.
The CannonField now has a game over state.
The layout problems in LCDRange are fixed.
\list
\i \l t13/lcdrange.h contains the LCDRange
class definition.
\i \l t13/lcdrange.cpp contains the LCDRange
implementation.
\i \l t13/cannon.h contains the CannonField class
definition
\i \l t13/cannon.cpp contains the CannonField
implementation.
\i \l t13/gamebrd.h contains the GameBoard
class definition.
\i \l t13/gamebrd.cpp contains the GameBoard
implementation.
\i \l t13/main.cpp contains MyWidget and main.
\endlist
\section1 Line-by-line Walkthrough
\section2 \l t13/lcdrange.h
\quotefile t13/lcdrange.h
\skipto include
\printuntil QWidget
We inherit QWidget rather than QVBox. QVBox is very easy to use, but
again it showed its limitations so we switch to the more powerful and
slightly harder to use QVBoxLayout. (As you remember, QVBoxLayout is
not a widget, it manages one.)
\section2 \l t13/lcdrange.cpp
\quotefile t13/lcdrange.cpp
\skipto layout
\printline layout
We need to include ntqlayout.h now to get the other layout management
API.
\printline LCDRange
\printline QWidget
We inherit QWidget in the usual way.
The other constructor has the same change. init() is unchanged,
except that we've added some lines at the end:
\skipto QVBoxLayout
\printline QVBoxLayout
We create a QVBoxLayout with all the default values, managing this
widget's children.
\printline addWidget
At the top we add the QLCDNumber with a non-zero stretch.
\printline addWidget
\printline addWidget
Then we add the other two, both with the default zero stretch.
This stretch control is something QVBoxLayout (and QHBoxLayout, and
QGridLayout) offers but classes like QVBox do not. In this case
we're saying that the QLCDNumber should stretch and the others should
not.
\section2 \l t13/cannon.h
The CannonField now has a game over state and a few new functions.
\quotefile t13/cannon.h
\skipto gameOver
\printline gameOver
This function returns TRUE if the game is over or FALSE if a game
is going on.
\skipto setGameOver
\printuntil restartGame
Here are two new slots: setGameOver() and restartGame().
\skipto canShoot
\printline canShoot
This new signal indicates that the CannonField is in a state where the
shoot() slot makes sense. We'll use it below to enable/disable the
Shoot button.
\skipto gameEnded
\printline gameEnded
This private variable contains the game state. TRUE means that the
game is over, and FALSE means that a game is going on.
\section2 \l t13/cannon.cpp
\quotefile t13/cannon.cpp
\skipto ::CannonField
\skipto gameEnded
\printline gameEnded
This line has been added to the constructor. Initially, the game is not
over (luckily for the player :-).
\skipto ::shoot
\printuntil }
We added a new isShooting() function, so shoot() uses it instead of
testing directly. Also, shoot tells the world that the CannonField
cannot shoot now.
\skipto ::setGameOver
\printuntil }
This slot ends the game. It must be called from outside CannonField,
because this widget does not know when to end the game. This is an
important design principle in component programming. We choose to
make the component as flexible as possible to make it usable with
different rules (for example, a multi-player version of this in which the
first player to hit ten times wins could use the CannonField unchanged).
If the game has already been ended we return immediately. If a game is
going on we stop the shot, set the game over flag, and repaint the entire
widget.
\skipto ::restartGame
\printuntil }
This slot starts a new game. If a shot is in the air, we stop shooting.
We then reset the \c gameEnded variable and repaint the widget.
moveShot() too emits the new canShoot(TRUE) signal at the same time as
either hit() or miss().
Modifications in CannonField::paintEvent():
\skipto ::paintEvent
\printuntil }
The paint event has been enhanced to display the text "Game Over" if
the game is over, i.e., \c gameEnded is TRUE. We don't bother to
check the update rectangle here because speed is not critical when
the game is over.
To draw the text we first set a black pen; the pen color is used
when drawing text. Next we choose a 48 point bold font from the
Courier family. Finally we draw the text centered in the widget's
rectangle. Unfortunately, on some systems (especially X servers with
Unicode fonts) it can take a while to load such a large font. Because
Qt caches fonts, you will notice this only the first time the font is
used.
\printuntil }
We draw the shot only when shooting and the target only when playing
(that is, when the game is not ended).
\section2 \l t13/gamebrd.h
This file is new. It contains the definition of the GameBoard class,
which was last seen as MyWidget.
\quotefile t13/gamebrd.h
\skipto include
\skipto class
\printuntil };
We have now added four slots. These are protected and are used internally.
We have also added two QLCDNumbers (\c hits and \c shotsLeft) which display
the game status.
\section2 \l t13/gamebrd.cpp
This file is new. It contains the implementation of the GameBoard
class, which was last seen as MyWidget.
\quotefile t13/gamebrd.cpp
We have made some changes in the GameBoard constructor.
\skipto ::GameBoard
\skipto cannonField
\printline cannonField
\c cannonField is now a member variable, so we carefully change the
constructor to use it. (The \e good programmers at Trolltech never
forget this, but I do. Caveat programmor - if "programmor" is Latin,
at least. Anyway, back to the code.)
\skipto hit
\printline connect
\printline hit
\printline connect
\printline missed
This time we want to do something when the shot has hit or missed the
target. Thus we connect the hit() and missed() signals of the
CannonField to two protected slots with the same names in this class.
\skipto shoot
\skipto connect
\printline fire
Previously we connected the Shoot button's clicked() signal directly
to the CannonField's shoot() slot. This time we want to keep track of
the number of shots fired, so we connect it to a protected slot in
this class instead.
Notice how easy it is to change the behavior of a program when you are
working with self-contained components.
\printline connect
\printline setEnabled
We also use the cannonField's canShoot() signal to enable or disable
the Shoot button appropriately.
\skipto restart
\printuntil connect
We create, set up, and connect the New Game button as we have done
with the other buttons. Clicking this button will activate the
newGame() slot in this widget.
\printuntil shotsLeftL
\printline QLabel
We create four new widgets. Note that we don't bother to keep the
pointers to the QLabel widgets in the GameBoard class because there's
nothing much we want to do with them. Qt will delete them when the
GameBoard widget is destroyed, and the layout classes will resize them
appropriately.
\skipto QHBoxLayout
\printuntil addStretch
\printline addWidget
The number of widgets in the top-right cell is getting large. Once it
was empty; now it's full enough that we group together the layout
setting for better overview.
Notice that we let all the widgets have their preferred sizes, instead
putting the stretch just to the left of the New Game button.
\skipto newGame
\printline newGame
\printline }
We're all done constructing the GameBoard, so we start it all using
newGame(). (NewGame() is a slot, but as we said, slots can be used as
ordinary functions, too.)
\skipto ::fire
\printuntil }
This function fires a shot. If the game is over or if there is a shot in the
air, we return immediately. We decrement the number of shots left and tell
the cannon to shoot.
\skipto ::hit
\printuntil }
This slot is activated when a shot has hit the target. We increment the
number of hits. If there are no shots left, the game is over. Otherwise,
we make the CannonField generate a new target.
\skipto ::missed
\printuntil }
This slot is activated when a shot has missed the target. If there are no
shots left, the game is over.
\skipto ::newGame
\printuntil }
This slot is activated when the user clicks the Restart button. It is
also called from the constructor. First it sets the number of shots
to 15. Note that this is the only place in the program where we set
the number of shots. Change it to whatever you like to change the
game rules. Next we reset the number of hits, restart the game, and
generate a new target.
\section2 \l t13/main.cpp
This file has just been on a diet. MyWidget is gone, and the only
thing left is the main() function, unchanged except for the name
change.
\section1 Behavior
The cannon can shoot at a target; a new target is automatically created
when one has been hit.
Hits and shots left are displayed and the program keeps track of them.
The game can end, and there's a button to start a new game.
(See \link tutorial1-07.html#compiling Compiling\endlink for how to create a
makefile and build the application.)
\section1 Exercises
Add a random wind factor and show it to the user.
Make some splatter effects when the shot hits the target.
Implement multiple targets.
You're now ready for \link tutorial1-14.html Chapter 14.\endlink
[\link tutorial1-12.html Previous tutorial\endlink]
[\link tutorial1-14.html Next tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
/*! \file t14/lcdrange.h */
/*! \file t14/lcdrange.cpp */
/*! \file t14/cannon.h */
/*! \file t14/cannon.cpp */
/*! \file t14/gamebrd.h */
/*! \file t14/gamebrd.cpp */
/*! \file t14/main.cpp */
/*! \page tutorial1-14.html
\title Qt Tutorial - Chapter 14: Facing the Wall
\img t14.png Screenshot of tutorial fourteen
This is the final example: a complete game.
We add keyboard accelerators and introduce mouse events to CannonField. We
put a frame around the CannonField and add a barrier (wall) to make the
game more challenging.
\list
\i \l t14/lcdrange.h contains the LCDRange
class definition.
\i \l t14/lcdrange.cpp contains the LCDRange
implementation.
\i \l t14/cannon.h contains the CannonField class
definition.
\i \l t14/cannon.cpp contains the CannonField
implementation.
\i \l t14/gamebrd.h contains the GameBoard
class definition.
\i \l t14/gamebrd.cpp contains the GameBoard
implementation.
\i \l t14/main.cpp contains MyWidget and main.
\endlist
\section1 Line-by-line Walkthrough
\section2 \l t14/cannon.h
The CannonField can now receive mouse events to make the user aim the
barrel by clicking on it and dragging. CannonField also has a barrier
wall.
\quotefile t14/cannon.h
\skipto CannonField
\skipto protected
\printuntil mouseReleaseEvent
In addition to the familiar event handlers, CannonField implements
three mouse event handlers. The names say it all.
\skipto paintBarrier
\printline paintBarrier
This private function paints the barrier wall.
\skipto barrierRect
\printline barrierRect
This private function returns the enclosing rectangle of the barrier.
\skipto barrelHit
\printline barrelHit
This private function checks if a point is inside the barrel of the cannon.
\skipto barrelPressed
\printline barrelPressed
This private variable is TRUE if the user has pressed the mouse on the
barrel and not released it.
\section2 \l t14/cannon.cpp
\quotefile t14/cannon.cpp
\skipto ::CannonField
\skipto barrelPressed
\printline barrelPressed
This line has been added to the constructor. Initially, the mouse is
not pressed on the barrel.
\skipto ::moveShot
\skipto else
\printuntil {
Now that we have a barrier, there are three ways to miss. We test for
the third, too.
\skipto ::mousePressEvent
\printuntil }
This is a Qt event handler. It is called when the user presses a
mouse button when the mouse cursor is over the widget.
If the event was not generated by the left mouse button, we return
immediately. Otherwise, we check if the position of the mouse cursor
is within the cannon's barrel. If it is, we set \c barrelPressed to
TRUE.
Notice that the pos() function returns a point in the widget's
coordinate system.
\skipto ::mouseMoveEvent
\printuntil setAngle
\printline }
This is another Qt event handler. It is called when the user already
has pressed the mouse button inside this widget and then moves/drags
the mouse. (You can make Qt send mouse move events even when no
buttons are pressed. See \l QWidget::setMouseTracking().)
This handler repositions the cannon's barrel according to the position of
the mouse cursor.
First, if the barrel is not pressed, we return. Next, we fetch the
mouse cursor's position. If the mouse cursor is to the left or below
the widget, we adjust the point to be inside the widget.
Then we calculate the angle between the bottom edge of the widget and
the imaginary line between the bottom-left corner of the widget and
the cursor position. Finally we set the cannon's angle to the new
value converted to degrees.
Remember that setAngle() redraws the cannon.
\skipto ::mouseReleaseEvent
\printuntil }
This Qt event handler is called whenever the user releases a mouse
button and it was pressed inside this widget.
If the left button is released, we can be sure that the barrel is no
longer pressed.
The paint event has two extra lines:
\skipto ::paintEvent
\skipto barrierRect
\printline barrierRect
\printline paintBarrier
paintBarrier() does the same sort of thing as paintShot(),
paintTarget(), and paintCannon().
\skipto ::paintBarrier
\printuntil }
This private function paints the barrier as a rectangle filled with
yellow and with a black outline.
\skipto ::barrierRect
\printuntil }
This private function returns the rectangle of the barrier. We fix
the bottom edge of the barrier to the bottom edge of the widget.
\skipto ::barrelHit
\printuntil }
This function returns TRUE if the point is in the barrel; otherwise it returns
FALSE.
Here we use the class \l QWMatrix. It is defined in the header file
ntqwmatrix.h, which is included by ntqpainter.h.
QWMatrix defines a coordinate system mapping. It can perform the same
transformations as the QPainter.
Here we perform the same transformation steps as we do when drawing
the barrel in the paintCannon() function. First we translate the
coordinate system and then we rotate it.
Now we need to check whether the point \c p (in widget coordinates) lies
inside the barrel. To do this, we invert the transformation matrix.
The inverted matrix performs the inverse transformation that we used
when drawing the barrel. We map the point \c p using the inverted
matrix and return TRUE if it is inside the original barrel rectangle.
\section2 \l t14/gamebrd.cpp
\quotefile t14/gamebrd.cpp
\skipto ntqaccel.h
\printline ntqaccel.h
We include the class definition of \l QAccel.
\skipto ::GameBoard
\skipto QVBox
\printline QVBox
\printline setFrameStyle
\printline cannonField
We create and set up a \l QVBox, set its frame style, and then create
\c CannonField as a child of that box. Because nothing else is in the
box, the effect is that the QVBox will put a frame around the
CannonField.
\skipto QAccel
\printline accel
\printline connectItem
\printline fire
\printline connectItem
\printline fire
Here we create and set up an accelerator. An accelerator is an object
that intercepts keyboard events to an application and calls slots if
certain keys are pressed. This mechanism is also called shortcut
keys. Note that an accelerator is a child of a widget and will be
destroyed when that widget is destroyed. QAccel is \e not a widget
and has no visible effect on its parent.
We define two shortcut keys. We want the slot fire() to be called
when the user presses Enter, and we want the application to quit when
key Ctrl+Q is pressed. Because Enter is sometimes Return and there
are even keyboards with \e both keys, we make both Enter and Return
invoke fire().
\printline connectItem
\printline quit
And then we set up Ctrl+Q to do the same thing as Alt+Q. Some
people are more used to Ctrl+Q (and anyway it shows how do do it).
CTRL, Key_Enter, Key_Return and Key_Q are all constants provided by
Qt. They're actually Qt::Key_Enter, etc., but practically all classes
inherit the \l Qt namespace class.
\printline QGridLayout
\printline addWidget
\printline addWidget
\printline setColStretch
We put \c box (the QVBox), not the CannonField, in the lower-right
cell.
\section1 Behavior
The cannon now shoots when you press Enter. You can also position the
cannon's angle using the mouse. The barrier makes it a little more
challenging to play the game. We also have a nice looking frame
around the CannonField.
(See \link tutorial1-07.html#compiling Compiling\endlink for how to create a
makefile and build the application.)
\section1 Exercises
Write a space invaders game.
(This exercise was first done by
\link mailto:igorr@ifi.uio.no Igor Rafienko\endlink. You can
\link http://www.stud.ifi.uio.no/~igorr/download.html
download his game\endlink.)
The new exercise is: Write a Breakout game.
Final exhortation: Go forth now and create \e {masterpieces of the
programming art!}
\omit
Cf. Chapter 27 of The TeXbook
\endomit
[\link tutorial1-13.html Previous tutorial\endlink]
[\link tutorial1-01.html First tutorial\endlink]
[\link tutorial.html Main tutorial page\endlink]
*/
|