-
Notifications
You must be signed in to change notification settings - Fork 7
/
ch07-03.htm
3609 lines (2418 loc) · 221 KB
/
ch07-03.htm
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
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<title>ch07-03</title>
<link href="css/style.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="thumbnailviewer.css" type="text/css">
<script src="thumbnailviewer.js" type="text/javascript">
/***********************************************
* Image Thumbnail Viewer Script- © Dynamic Drive (www.dynamicdrive.com)
* This notice must stay intact for legal use.
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/
</script> </head>
<body>
<div class="os1">7.3 文本流QTextStream</div>
<br>
标准 C++ 有三个常见的输入输出流:iostream 处理命令行输入输出、fstream 处理文件输出输出、sstream
处理内存字符串流的输入输出。通常将文本字符串转换成各种 C++ 变量的过程是输入,把内存中 C++ 变量表示成文本字符串的过程是输出。<br>
Qt 提供了强大的文本流 QTextStream ,同时实现了三种 C++
输入输出流的功能,并且还有功能增强,支持各种文本字符编码。QTextStream 一般用于操作各种编码格式的文本文件(QFile
对象)或字符串(QString、QByteArray),也可以打开 stdin、stdout 和 stderr 命令行的输入输出,并自动处理本地化编码和
Unicode 编码。<br>
本节先将 QTextStream 类的内容分成四个小节来讲解,然后动手编写两个例子,将 QTextStream
的三种用途全部实现一遍,最后附加一个技巧,就是图形界面程序和命令行输入输出的结合,虽然图形界面程序和命令行的协作很少,但多学一点也好。<br>
<br>
<div class="os2">7.3.1 QTextStream 构造函数和普通读写函数</div>
<br>
通常情况下 QTextStream 自己不会主动去打开一个文件,所以它的构造函数不接收文件名,而是接收 QFile 基类 QIODevice
的指针,可以用 QFile 对象的指针构造 QTextStream ,但需要注意在构造 QTextStream 之前要调用 QFile 对象的
open() 函数按需要的模式打开文件并检查是否正确打开。用于读写文件的 QTextStream 构造函数为:<br>
<div class="code"> QTextStream(QIODevice * device)</div>
设备指针 device 需要提前用 open() 函数打开。<br>
<br>
对于文件设备,还有个不常用的构造函数:<br>
<div class="code"> QTextStream(FILE * fileHandle,
QIODevice::OpenMode openMode = QIODevice::ReadWrite)</div>
fileHandle 是文件句柄,因为 Qt 里面的文件一般都用 QFile
处理,所以几乎不会用这个第二个函数处理文件。第二个构造函数的用途主要是和命令行的 stdin、stdout、stderr
三个文件句柄协作,处理命令行的输入输出。<br>
<br>
以上两个构造函数第一个用于文件读写(类似 fstream),第二个一般用于命令行输入输出(类似 iostream),而 QTextStream
第三个用途就是对内存字符串的格式化输入和输出(类似 sstream)。内存字符串输入输出,使用的构造函数为:<br>
<div class="code"> QTextStream(QString * string,
QIODevice::OpenMode openMode = QIODevice::ReadWrite)</div>
<div class="code"> QTextStream(QByteArray * array,
QIODevice::OpenMode openMode = QIODevice::ReadWrite)</div>
<div class="code"> QTextStream(const QByteArray &
array, QIODevice::OpenMode openMode = QIODevice::ReadOnly)</div>
注意后两个构造函数,如果传递 QByteArray 对象给构造函数,那么这个 QByteArray 对象是只读的。<br>
如果传递 QByteArray 指针给构造函数,那么默认是可读可写的。<br>
<br>
除了可以在构造函数指定文件设备或内存字符串,还可以在运行时修改:<br>
<div class="code">void QTextStream::setDevice(QIODevice * device)</div>
<div class="code">void QTextStream::setString(QString * string,
QIODevice::OpenMode openMode = QIODevice::ReadWrite)</div>
目前没有重新设置 QByteArray 的函数,只有修改文件设备和 QString 的函数。<br>
<br>
我们这里约定一下概念,无论 QTextStream 构造函数里是文件设备或内存字符串,本节后面都把 QTextStream 对象称为 文本流。<br>
如果我们需要从文本流提取各种 C++ 基本数值类型,如 short、int、long、double ,这些读操作一般用 7.3.2 节的操作子和运算符
<<、>>来实现,写入文本流时也一样。流操作子和运算符之外的读写函数就是本小节说的普通读写函数。<br>
读取一整行文本的函数:<br>
<div class="code">QString QTextStream::readLine(qint64 maxlen = 0)</div>
QTextStream::readLine() 读取一行文本的时候,返回字符串末尾剔除了换行符("\n" 或 "\r\n"),而上一节
QIODevice 和 QFile 的 readLine() 函数返回字符串末尾带有一个 "\n" ,要注意区分。<br>
如果要读取文本流中所有内容,可以用快捷函数:<br>
<div class="code">QString QTextStream::readAll()</div>
如果希望从文本流中读取指定长度的文本,可以用函数:<br>
<div class="code">QString QTextStream::read(qint64 maxlen)</div>
参数里是最多读取的字符数目,如果文本流里的数据不够,返回的字符串就是剩余的字符数。<br>
<br>
在使用 QFile 对象指针构造 QTextStream 的时候,一旦把 QFile 对象指针交给 QTextStream 之后,就不要再调用
QFile 对象自己的读写函数了,因为 QTextStream 使用自己缓存的文件游标,底层 QFile 对象自己又进行读写之后,二者的文件游标很可能不
一致,会造成读写的混乱。既然使用 QTextStream 读写文件,那就只用 QTextStream 的读写函数或输入输出运算符。<br>
<br>
QTextStream 的文件游标(其实应该叫文本流游标)可以用函数获取、移动,以及判断是否到达文件末尾:<br>
<div class="code">qint64 QTextStream::pos() const
//获取游标位置</div>
<div class="code">bool QTextStream::seek(qint64 pos)//移动游标到 pos</div>
<div class="code">bool QTextStream::atEnd() const //是否到达文
本流末尾</div>
<br>
对于文本流的写入操作,QTextStream 压根没有 write() 函数,写入操作全部是通过输出运算符 << 和流操作子实现的。<br>
我们下面看看流操作子和 <<、>> 运算符。<br>
<br>
<div class="os2">7.3.2 QTextStream 流操作子和运算符</div>
<br>
绝大多数情况下,QTextStream 都是利用 >> 运算符进行输入,利用 <<
运算符进行输出,与这两个运算符配合的有一大堆操作子,这些操作子和 iostream
的操作子很类似,而且名字也几乎一样。流操作子一般用于控制输入输出的格式,大部分流操作子不带参数,Qt 提供额外提供了三个带参数的全局操作子,等会都列出
来。<br>
<br>
QTextStream 支持所有 C++ 基本类型变量输入输出,并支持 Qt 自家的 QChar、QString、QByteArray,举例来说:<br>
<div class="code">QTextStream & QTextStream::operator<<(signed
int i)</div>
<div class="code">QTextStream & QTextStream::operator>>(signed
int & i)</div>
第一个是整型变量的输出运算符(或叫插入运算符)函数,第二个是整型变量的输入运算符(或叫提取运算符)函数。<br>
QTextStream 在代码里面进行输入输出,就与标准 C++ 的 cin 和 cout 一样用就可以了。例如:<br>
<div class="code"><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QString</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">strIn</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"100</span><span style=" color:#c0c0c0;">
</span><span style=" color:#008000;">29.88"</span><span style=" color:#000000;">);</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QTextStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span style=" color:#000000;">(&</span><span
style=" color:#000000;">strIn</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nNum</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dblVal</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//输入</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span
style=" color:#000000;">>></span><span style=" color:#000000;">nNum</span><span
style=" color:#000000;">>></span><span style=" color:#000000;">dblVal</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//打印</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">nNum</span><span
style=" color:#000000;"><<</span><span style=" color:#000000;">dblVal</span><span
style=" color:#000000;">;</span></pre>
</div>
这段代码执行后 nNum 就是数值 100, dblVal 就是浮点数 29.88 。qDebug()
其实就是获取调试输出流的对象,然后打印了两个数值。<br>
<br>
QTextStream 里面重载的 << 和 >> 运算符就不一个个列举了,讲一下关于字符串读取的三个:<br>
<div class="code">QTextStream & QTextStream::operator>>(QString
& str)</div>
<div class="code">QTextStream &
QTextStream::operator>>(QByteArray & array)</div>
<div class="code">QTextStream & QTextStream::operator>>(char * c)</div>
QTextStream 对于字符串的读取,其实只读取一个单词,而不是一整行。比如如果文本流原始为 "Hello world, aha
!",如果用上面三个函数从头读取,那么读取的都只是第一个单词 "Hello" ,在源头的文件或内存字符串中,文本流中间都没有字符串终结符 '\0',所以
QTextStream 在输入时按照空白字符切割单词,每个单词算作一个小字符串返回。空白字符包括空格、制表符、换行符等等。<br>
<br>
另外当文本流用 >> 读取逐个字符到 QChar 或 char 变量里面时,可以用 <br>
<div class="code">void QTextStream::skipWhiteSpace()</div>
跳过空白字符,如果不跳过空白字符,那么 QChar 和 char 也会接收到空白字符,如空格、制表符、换行符等等。<br>
<br>
对于字符串的输出就没有上面那些问题了,因为输出时可以明确知道参数里的 QString 、QByteArray 、char * 是以 '\0' 结尾的,在
'\0' 前面的字符串都会被写入到输出文本流中。<br>
<br>
输出文本流需要注意的是 QTextStream 有较大的输出缓冲区,如果用 stdout 或 stderr 构造 QTextStream
对象打印输出,要常用 flush 或 endl 操作子函数清空缓存,及时显示输出:<br>
<div class="code">tsOut<<flush;</div>
<div class="code">tsOut<<endl;</div>
flush 和 endl 的区别是 endl 会换行,flush 不换行。<br>
<br>
流的输入输出运算符用起来比较简单,下面重点看看控制格式的操作子,操作子本质都是函数,比如常用的换行 endl:<br>
<div class="code">QTextStream & endl(QTextStream & stream)</div>
<br>
我们这里把 QTextStream 的操作子大致列举并解释一下:<br>
① 数值的进制和符号、小数点<br>
<br>
<table class="tabel">
<tbody>
<tr class="d1">
<td style="width: 200px;" align="center"><b>操作子</b></td>
<td align="center"><b> 描述</b></td>
</tr>
<tr>
<td>bin</td>
<td> 读写二进制整数,等同于 setIntegerBase(2). </td>
</tr>
<tr class="d1">
<td>oct</td>
<td> 读写八进制整数,等同于 setIntegerBase(8). </td>
</tr>
<tr>
<td>dec</td>
<td> 读写十进制整数,等同于 setIntegerBase(10). </td>
</tr>
<tr class="d1">
<td>hex</td>
<td> 读写十六进制整数,等同于 setIntegerBase(16). </td>
</tr>
<tr>
<td>showbase</td>
<td> 输出时显示数值进制前缀,比如 "0x" 、"0"、"0b",等同于 setNumberFlags(numberFlags() |
ShowBase). </td>
</tr>
<tr class="d1">
<td>forcesign</td>
<td> 强制显示正号(正数和0前面),等同于 setNumberFlags(numberFlags() | ForceSign). </td>
</tr>
<tr>
<td>forcepoint</td>
<td> 强制显示整数末尾的小数点,等同于 setNumberFlags(numberFlags() | ForcePoint). </td>
</tr>
<tr class="d1">
<td>noshowbase</td>
<td> 不显示进制的前缀,等同于 setNumberFlags(numberFlags() & ~ShowBase). </td>
</tr>
<tr>
<td>noforcesign</td>
<td> 不强制显示正号,等同于 setNumberFlags(numberFlags() & ~ForceSign). </td>
</tr>
<tr class="d1">
<td>noforcepoint</td>
<td> 不强制显示小数点,等同于 setNumberFlags(numberFlags() & ~ForcePoint). </td>
</tr>
<tr>
<td>uppercasebase</td>
<td> 数值进制的前缀为大写,如 "0X" 、"0B",等同于 setNumberFlags(numberFlags() |
UppercaseBase). </td>
</tr>
<tr class="d1">
<td>uppercasedigits</td>
<td> 基数大于10进制的数值里面的字母大写,比如16进制的 "FE00",
等同于setNumberFlags(numberFlags() | UppercaseDigits). </td>
</tr>
<tr>
<td>lowercasebase</td>
<td> 数值进制的前缀小写,如 "0x" 、"0b",等同于 setNumberFlags(numberFlags() &
~UppercaseBase). </td>
</tr>
<tr class="d1">
<td>lowercasedigits</td>
<td> 基数大于10进制的数值里面的字母小写,比如16进制的 "fe00", 等同于
setNumberFlags(numberFlags() & ~UppercaseDigits). </td>
</tr>
</tbody>
</table>
<br>
② 浮点数格式<br>
<br>
<table class="tabel">
<tbody>
<tr class="d1">
<td style="width: 200px;" align="center"><b>操作子</b></td>
<td align="center"><b> 描述</b></td>
</tr>
<tr>
<td>fixed</td>
<td> 以定点数显示实数(比如 float、double 类型),比如 1024.1234,等同于
setRealNumberNotation(FixedNotation). </td>
</tr>
<tr class="d1">
<td>scientific</td>
<td> 以科学计数法显示实数,比如 1.0241234e3,等同于
setRealNumberNotation(ScientificNotation). </td>
</tr>
<tr>
<td>qSetRealNumberPrecision(int precision)</td>
<td> 这是全局操作子,带一个整型参数,指定实数显示的精度位数,等同于
QTextStream::setRealNumberPrecision(precision). </td>
</tr>
</tbody>
</table>
<br>
qSetRealNumberPrecision(int) 会对后续所有实数变量输出都生效,直到被改变为止,实数精度默认是 6
位,如果希望还原就设置精度为 6 。注意使用操作子 qSetRealNumberPrecision(int) 时最好一块明确指定使用 fixed 或者
scientific,这样显示结果才是符合预期的小数位精度。<br>
<br>
③ 域宽和对齐方式、填充字符<br>
<br>
<table class="tabel">
<tbody>
<tr class="d1">
<td style="width: 200px;" align="center"><b>操作子</b></td>
<td align="center"><b> 描述</b></td>
</tr>
<tr>
<td>qSetFieldWidth(int width)</td>
<td> 全局操作子,带一个整型参数,设定变量输出后的显示宽度,不足的用填充字符补齐(默认用空格补),等同于
QTextStream::setFieldWidth(width). </td>
</tr>
<tr class="d1">
<td>qSetPadChar(QChar ch)</td>
<td> 全局操作子,带一个字符参数,如果设置的域宽比变量显示需要的宽度更宽,就用这个填充字符填补(默认是空格 ' '),等同于
QTextStream::setPadChar(ch). </td>
</tr>
<tr>
<td>left</td>
<td> 设定域宽比变量显示需要的更宽时,变量显示时左对齐,右边空位补 PadChar, 等同于
setFieldAlignment(AlignLeft). </td>
</tr>
<tr class="d1">
<td>right</td>
<td> 设定域宽比变量显示需要的更宽时,变量显示时右对齐,左边空位补 PadChar, 等同于
setFieldAlignment(AlignRight). </td>
</tr>
<tr>
<td>center</td>
<td> 设定域宽比变量显示需要的更宽时,变量显示时居中对齐,两边空位补 PadChar, 等同于
setFieldAlignment(AlignCenter). </td>
</tr>
</tbody>
</table>
<br>
注意:qSetFieldWidth(int) 设置域宽之后,如果不重新设置,它就一直生效, 对后续所有变量输出都管用,包括 endl 都会补齐变为
指定宽 度。 如果要还原成不设置域宽的状态,就调用操作子 qSetFieldWidth(0) 。 <br>
qSetPadChar(QChar) 设置填充字符之后也是一直持续生效,直到被重新设置,如果还原成空格,就调用操作子
qSetPadChar(QChar(0x20)) 。<br>
<br>
④ 其他操作子<br>
<br>
<table class="tabel">
<tbody>
<tr class="d1">
<td style="width: 200px;" align="center"><b>操作子</b></td>
<td align="center"><b> 描述</b></td>
</tr>
<tr>
<td>endl</td>
<td> 添加换行符并清空输出缓存,把缓冲数据都写到输出文本流,等同于 stream << '\n' <<
flush; </td>
</tr>
<tr class="d1">
<td>flush</td>
<td> 清空输出缓冲区,把缓冲数据都写到输出文本流,等同于 QTextStream::flush() </td>
</tr>
<tr>
<td>reset</td>
<td> 把之前操作子或格式函数设定的格式全部重置,还原到流对象构建时的默认格式, 等同于 QTextStream::reset() </td>
</tr>
<tr class="d1">
<td>ws</td>
<td> 跳过输入文本流里的空白字符(包括空格、制表符、换行符等),直至遇到非空白字符, 等同于
QTextStream::skipWhiteSpace() </td>
</tr>
<tr>
<td>bom</td>
<td> 除非确定是写入 Unicode 文本文件否则不要设置,如果要设置,必须在所有写入操作之前调用该操作子, 等同于
setGenerateByteOrderMark(true). </td>
</tr>
</tbody>
</table>
<br>
bom(Byte Order Mark)只用于 Unicode 编码的文本文件,如果不是写入 Unicode
的字符编码格式(UTF-8、UTF-16、UTF-32)文本,就不要用 bom,后面的小节会讲到文本流和字符编码格式。<br>
<br>
<div class="os2">7.3.3 QTextStream 工作状态</div>
<br>
本小节说明一下文本流的工作状态,以输入文本流为例,源头文本为 "Hello world, aha !" ,我们如果执行:<br>
<div class="code"><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//文本源</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strSrc</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"Hello</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">world,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">aha</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">!"</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QTextStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strSrc</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//变量</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strTemp</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span
style=" color:#000000;">>></span><span style=" color:#000000;">strTemp</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">strTemp</span><span
style=" color:#000000;">;</span></pre>
</div>
这段代码会从文本流提取一个单词赋值给 strTemp ,这样的输入操作当然是对的。但如果强行从非数值字符串提取数值到整型或浮点数类型,那么会发生什么呢?<br>
<div class="code"><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//文本源</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strSrc</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"Hello</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">world,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">aha</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">!"</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QTextStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strSrc</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//变量</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nNum</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span
style=" color:#000000;">>></span><span style=" color:#000000;">nNum</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">nNum</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">tsIn</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">status</span><span
style=" color:#000000;">();</span></pre>
</div>
strSrc 里面压根没有整型数值对应的字符串,上面代码执行之后 nNum 会被设置成默认的数值 0,而这时候 tsIn
应该报错才对,输入流发生了错误,无法为整型数提供 nNum 提供数值。<br>
文本流是通过状态变化来反映刚才的输入或输出操作有无错误发生,获取当前文本流的状态就是用函数:<br>
<div class="code">Status QTextStream::status() const</div>
枚举类型 Status 目前共有 4 个不同的枚举值:<br>
<br>
<table class="tabel">
<tbody>
<tr class="d1">
<td style="width: 200px;" align="center"><b>Status 枚举常量</b></td>
<td style="width: 200px;" align="center"><b>数值</b></td>
<td align="center"><b> 描述</b></td>
</tr>
<tr>
<td>QTextStream::Ok</td>
<td> 0 </td>
<td> 正常操作状态,没出错。 </td>
</tr>
<tr class="d1">
<td>QTextStream::ReadPastEnd</td>
<td> 1 </td>
<td> 底层设备已到达末尾,比如文件末尾,无数据可读了。 </td>
</tr>
<tr>
<td>QTextStream::ReadCorruptData</td>
<td> 2 </td>
<td> 读入了腐化数据,典型的就是文本源内容与目标变量类型不匹配。 </td>
</tr>
<tr class="d1">
<td>QTextStream::WriteFailed</td>
<td> 3 </td>
<td> 无法向底层设备写入数据,比如文件是只读的。 </td>
</tr>
</tbody>
</table>
<br>
对于上面示例的代码,文本源没有整型变量对应的字符串,当 tsIn 向 nNum 输入数据时,就会发生
QTextStream::ReadCorruptData 错误,tsIn.status() 返回的数值就是 2 。<br>
在进行文本流的输入输出时,如果出现莫名奇妙的错误,一定要注意检查文本流 QTextStream
的状态,很可能发生内容字符串与变量类型不匹配,或者无法写入底层设备等。<br>
<br>
<span style="font-weight: bold; color: red;">编程时需要仔细考虑用户的输入和程序输出是否异常!</span><br>
<br>
对于错误的输入或输出应该如何处理呢?简单方法就是跳过错误的部分或用消息框提示,然后可以重新设置流的状态:<br>
<div class="code">void QTextStream::setStatus(Status
status) //把文本流设为指定状态</div>
<div class="code">void QTextStream::resetStatus()
//把状态重置为初始的 Ok 状态</div>
<br>
<div class="os2">7.3.4 QTextStream 与字符编码格式</div>
<br>
请读者回顾一下 3.1 节的字符编码格式,对于 Unix/Linux 系统,默认的本地化文本字符编码是 UTF-8,对于简体中文 Windows
默认文本字符编码是 GBK,繁体中文 Windows 默认是 Big5 。QTextStream
类是比较智能的,它可以自动检测文本字符的本地化编码,在输入时,它自动把本地化编码字符串转成 Qt 需要的类型,比如 QString 默认内码是
UTF-16 ;在输出时,QTextStream 也会把 QString 变量的内码 UTF-16 转成本地化的字符串写入输出文本流。<br>
<br>
QTextStream 不仅能对文本文件的本地化编码自动处理,也能与 操作系统本地的命令行交互,在交互过程中也会自动转码。QTextStream
还能自动检测 UTF-8、UTF-16、UTF-32 这些编码的文本,自动转为 Qt 默认的编码格式。使用 QTextStream
与操作系统里的文本文件、命令行等打交道,就不需要操心文本编码的问题。<br>
<br>
但是如果真的要手动指定 QTextStream 输入流或输出流的编码格式,那也是可行的。如果要获取当前文本流的字符编码格式,使用函数:<br>
<div class="code">QTextCodec * QTextStream::codec() const</div>
设置文本字符编码格式,使用函数:<br>
<div class="code">void QTextStream::setCodec(QTextCodec * codec)</div>
QTextCodec 对象指针一般都是用 QTextCodec 类的静态函数获取:<br>
<div class="code">QTextCodec * QTextCodec::codecForName(const char *
name) //静态函数</div>
<br>
QTextStream 类为方便程序员设定文本的字符编码格式,提供了一个更方便的 setCodec() 函数:<br>
<div class="code">void QTextStream::setCodec(const char * codecName)</div>
这个 setCodec() 函数直接以编码的名称字符串为构造函数,内部自己调用 QTextCodec 类的静态函数获取文本字符编码器。<br>
<br>
一般 QTextStream 不需要手动设置字符编码格式,当然,程序员如果知道应该用什么样的字符编码输入输出,就可以自己改,比如下面示范的就是按照
"UTF-8" 编码格式输出:<br>
<div class="code"><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QString</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">strSrc</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"Hello</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">world,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">aha</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">!"</span><span style=" color:#000000;">);</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//输出</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QFile</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">fileOut</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"test.txt"</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">fileOut</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">open</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QIODevice</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">WriteOnly</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QTextStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsOut</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&</span><span
style=" color:#000000;">fileOut</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsOut</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setCodec</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"UTF-8"</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsOut</span><span
style=" color:#000000;"><<</span><span style=" color:#000000;">strSrc</span><span
style=" color:#000000;">;</span></pre>
</div>
通常 UTF-8 格式不需要 bom,如果要为 UTF-16 或 UTF-32 编码的文本加 bom 头,一定要在所有的输出操作之前调用
tsOut<<bom ;<br>
<br>
改变 QTextStream 的文本字符编码格式只需要一句代码而已,但是要根据实际需求来定,一般不需要自己设定字符编码格式。<br>
<br>
QTextStream 还提供了与世界各国本地语言习惯 QLocale 相关的函数 locale() 和 setLocale(const QLocale
& locale),这个与各国的语言语种有关系,最好不要修改,用默认的即可,默认的 QLocale::C 不会影响数据输入输出。<br>
<br>
<div class="os2">7.3.5 读写文本文件示例</div>
<br>
本小节的例子主要实现读写自定义的文本格式,里面内容是这样的:<br>
<div class="code">#姓名 岁数 体重<br>
小明 18 50.5<br>
小萌 19 55.8<br>
小日 17 60.0<br>
小月 16 55.1<br>
小草 18 58.6</div>
里面内容相当于是一个表格,第一行是井号打头的注释行,是预先定义好的三列表头。<br>
然后从第二行开始是表格的数据,第一列是姓名,第二列是岁数,第三列是体重。每列数据之间用空格或者制表符分隔,每行的数据就用换行符分隔。我们下面开始编写示例
程序,能够读写这样的文本文件。<br>
<br>
我们打开 QtCreator,新建一个 Qt Widgets Application 项目,在新建项目的向导里填写:<br>
①项目名称 tableedit,创建路径 D:\QtProjects\ch07,点击下一步;<br>
②套件选择里面选择全部套件,点击下一步;<br>
③基类选择 QWidget,点击下一步;<br>
④项目管理不修改,点击完成。<br>
建好项目之后,先在项目文件夹里新建一个记事本文件,命名为 people.txt,把上面示范的文本内容保存到该文件里面,程序运行时会 用到。<br>
<br>
现在回到 QtCreator,打开窗体 widget.ui 文件,进入设计模式,把主窗体大小设置为 480 * 300,然后按照下图排布,拖入控件:<br>
<center><img src="images/ch07/ch07-03-01.png" alt="ui" width="800"></center>
上面控件从左边看是两大行:<br>
第一大行:左边是 QListWidget 控件,对象名为
listWidget,右边是一个垂直布局器,在垂直布局器里面有三个按钮和一个垂直弹簧条。竖排的第一个按钮,文本 "加载表格",对象名
pushButtonLoad,第二个按钮,文本 "保存表格",对象名 pushButtonSave ,然后是垂直的弹簧条
verticalSpacer,第三个按钮,文本 "删除行",对象名 pushButtonDelRow 。<br>
第一大行是按照水平布局器布局。<br>
<br>
第二大行:标签控件,文本 "姓名",单行编辑器,对象名 lineEditName;<br>
标签控件,文本 "岁数",单行编辑器,对象名 lineEditAge;<br>
标签控件,文本 "体重",单行编辑器,对象名 lineEditWeight;<br>
按钮控件,文本 "添加行",对象名为 pushButtonAddRow。<br>
第二大行也是按水平布局器排布。<br>
<br>
主窗体是以垂直布局器作为主布局。<br>
<br>
按照上面描述设置好界面和布局之后,首先分四次为四个按钮添加 clicked() 信号对应的槽函数:<br>
<center><img src="images/ch07/ch07-03-02.png" alt="slot1"></center>
四个按钮的用途比较明了,就是按钮文本显示的,上面两个按钮用于从文件加载表格和写入数据到文本文件;下面两个按钮用于从列表控件删除一行数据或者添加一行数据。<br>
然后我们为列表控件 listWidget 添加 currentRowChanged(int) 信号对应的槽函数:<br>
<center><img src="images/ch07/ch07-03-03.png" alt="slot2"></center>
当用户在列表控件选中某行时,我们利用这个信号对应的槽函数,把该行的数据同步显示到三个单行编辑器里面,方便用户编辑数据,然后添加行或删除行。<br>
<br>
按上面描述添加好槽函数之后,我们保存界面文件,关闭界面文件,回到 QtCreator 代码编辑模式。<br>
先来看看 widget.h 文件内容,这个头文件内容全是自动生成的,不需要修改:<br>
<div class="code"><span style=" color:#000080;">#ifndef</span><span style=" color:#c0c0c0;">
</span>WIDGET_H
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#define</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">WIDGET_H</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QWidget></span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">namespace</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Widget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">:</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">public</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">Q_OBJECT</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">public</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">explicit</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QWidget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>parent<span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">~</span><span style=" font-style:italic; color:#000000;">Widget</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">slots</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_pushButtonLoad_clicked</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_pushButtonSave_clicked</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_pushButtonDelRow_clicked</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_pushButtonAddRow_clicked</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_listWidget_currentRowChanged</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span>currentRow<span
style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Ui</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">Widget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">};</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#endif</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">WIDGET_H</span></pre>
</div>
<br>
然后我们打开源代码文件 widget.cpp,开始编写功能代码,首先编写头文件包含和构造函数的部分:<br>
<div class="code"><span style=" color:#000080;">#include</span><span style=" color:#c0c0c0;">
</span><span style=" color:#008000;">"widget.h"</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"ui_widget.h"</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QDebug></span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QMessageBox></span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QFileDialog></span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//打开或保存文件对话框</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QFile></span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//文件类</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QTextStream></span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//文本流输入输出</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QListWidgetItem></span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//列表控件条目</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">Widget</span><span style=" color:#000000;">(</span><span
style=" color:#800080;">QWidget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">new</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#000000;">::</span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">setupUi</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//设置列表控件的选中模式,一次只能选一行</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#800000;">listWidget</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">setSelectionMode</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QAbstractItemView</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">SingleSelection</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">::~</span><span
style=" font-style:italic; color:#000000;">Widget</span><span style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">delete</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
包含的 <QFileDialog>、<QFile> 是文件对话框和文件类,<QTextStream>
是本节的文本流,<QListWidgetItem> 是列表控件条目,用于从列表条目提取信息。<br>
<br>
构造函数只添加了一句代码,就是设置列表控件的选中模式,每次只能选中一行,这样简化我们 "删除行" 按钮的操作,每次只处理一行。<br>
<br>
接下来是 "加载表格" 按钮对应的槽函数:<br>
<div class="code"><span style=" color:#808000;">void</span><span style=" color:#c0c0c0;">
</span><span style=" color:#800080;">Widget</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">on_pushButtonLoad_clicked</span><span style=" color:#000000;">()</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//获取打开文件名</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strFile</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QFileDialog</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">getOpenFileName</span><span style=" color:#000000;">(</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">this</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"打开文件"</span><span
style=" color:#000000;">),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"."</span><span style=" color:#000000;">),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"Text</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">Files(*.txt);;All</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">files(*)"</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//判断文件名</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strFile</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">isEmpty</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//有文件名,定义文件对象并打开</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QFile</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">fileIn</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">strFile</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">fileIn</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">open</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QIODevice</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">ReadOnly</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"打开文件"</span><span style=" color:#000000;">),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"打开文件失败:"</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">+</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">fileIn</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">errorString</span><span
style=" color:#000000;">());</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//文件已经正确打开,定义文本流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QTextStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span style=" color:#000000;">(&</span><span
style=" color:#000000;">fileIn</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//表格的列数据类型</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strCurName</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nCurAge</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dblCurWeight</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//先清空旧的列表</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#800000;">listWidget</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">clear</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//加载自定义的表格数据</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">while</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">atEnd</span><span style=" color:#000000;">()</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//提取打头的字符串</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span
style=" color:#000000;">>></span><span style=" color:#000000;">strCurName</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//判断空行</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strCurName</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">isEmpty</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">skipWhiteSpace</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//跳过空白</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">continue</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//判断注释行</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strCurName</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">startsWith</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">'#'</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//是注释行,跳过这一行</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">readLine</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">continue</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//现在</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">strCurName</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">是正常的人名</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//提取后续的年龄、体重</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span
style=" color:#000000;">>></span><span style=" color:#000000;">nCurAge</span><span
style=" color:#000000;">>></span><span style=" color:#000000;">dblCurWeight</span><span
style=" color:#000000;">;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//原本可以用</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">arg</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">函数进行内存字符串格式化</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//这里用文本流格式化输出到内存字符串里面</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strOut</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QTextStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsOut</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strOut</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsOut</span><span
style=" color:#000000;"><<</span><span style=" color:#000000;">strCurName</span><span
style=" color:#000000;"><<</span><span style=" color:#008000;">"\t"</span><span
style=" color:#000000;"><<</span><span style=" color:#000000;">nCurAge</span><span
style=" color:#000000;"><<</span><span style=" color:#008000;">"\t"</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//定点数形式,精度为2,输出到内存字符串</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsOut</span><span
style=" color:#000000;"><<</span>fixed<span style=" color:#000000;"><<</span><span
style=" color:#000000;">qSetRealNumberPrecision</span><span style=" color:#000000;">(</span><span
style=" color:#000080;">2</span><span style=" color:#000000;">)<<</span><span
style=" color:#000000;">dblCurWeight</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//内存中输出字符串填充好了,添加到列表控件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#800000;">listWidget</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">addItem</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strOut</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//提示加载完毕</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">information</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"加载表格"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"加载自定义表格完毕。"</span><span style=" color:#000000;">));</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
这个槽函数前半部分代码是获取打开文件名 QFileDialog::getOpenFileName(),定义文件对象 fileIn
并以只读模式打开文件,然 后根据文件对象指针 定义 输入文本流 tsIn 。<br>
得到输入文本流 tsIn 之后,定义三个列的数据
strCurName、nCurAge、dblCurWeight,用这三个变量循环加载文本流里面的行。加载数据前,先清空了列表控件的内容
ui->listWidget->clear() 。<br>
<br>
函数后半部分代码就是用 while 循环加载数据:<br>
<br>
对于每行数据,先读取一个单词到 strCurName,如果单词为空,那么说明是空行,就跳过空白区域;<br>
如果单词 strCurName 以井号打头,说明注释行,用 tsIn.readLine() 跳过注释行;<br>
如果单词 strCurName 所在行不是空行也不是注释行,那么说明 strCurName 是姓名的列内容,读取该行后续的内容到两个变量 nCurAge
和 dblCurWeight,这样就把文件中的一行读取到三个变量里面了。<br>
<br>
对于三个变量 strCurName 、nCurAge 、dblCurWeight,我们需要构造一个内存字符串 strOut,把三项数据都打印到
strOut 里面,然后添加到列表控件显示。可以用 QString::arg() 函数实现格式化字符串,也可以用 QTextStream
格式化内存字符串,我们这里使用 QTextStream 的方法,根据 strOut 构造输出流 tsOut,然后把变量打印到输出流,变量之间用制表符