-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.xml
4702 lines (4702 loc) · 415 KB
/
index.xml
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
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>初等記憶體</title><link>https://axionl.me/</link><description>Recent content on 初等記憶體</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Wed, 23 Nov 2022 00:00:00 +0000</lastBuildDate><atom:link href="https://axionl.me/index.xml" rel="self" type="application/rss+xml"/><item><title>About</title><link>https://axionl.me/about/</link><pubDate>Wed, 23 Nov 2022 00:00:00 +0000</pubDate><guid>https://axionl.me/about/</guid><description><h2 id="記憶體自述">記憶體自述</h2>
<div style="position: relative; text-align: center; height: auto;">
<iframe
src="//music.163.com/outchain/player?id=1903723794&auto=0&amp;height=66&amp;type=2"
frameborder="no"
>
</iframe>
</div>
<p>直到一切都消失不见,才发现曾经近在眼前。</p>
<p>无法阻止,也无法释怀。</p>
<p>唯有记录,</p>
<p>在我身边。</p>
<p style="text-align: right">
<img src="https://axionl.me/img/sign.svg"/>
</p>
<blockquote>
<p>其餘資訊</p>
<ul>
<li><a class="link" href="https://t.me/loving4ever" target="_blank" rel="noopener"
>Telegram: 言文</a></li>
<li><a class="link" href="https://github.com/axionl.gpg" target="_blank" rel="noopener"
>GPG: 1FDB DCE2 D26B D8F1 00EE 2E73 B1B9 AAD8 BE7E 7326</a></li>
<li><a class="link" href="https://amane-live.fars.ee/" target="_blank" rel="noopener"
>余忆留声机: 一种相思,两处闲愁</a></li>
</ul>
</blockquote></description></item><item><title>Photos</title><link>https://axionl.me/photos/</link><pubDate>Wed, 23 Nov 2022 00:00:00 +0000</pubDate><guid>https://axionl.me/photos/</guid><description/></item><item><title>Maddy 自建邮件服务</title><link>https://axionl.me/p/maddy-%E8%87%AA%E5%BB%BA%E9%82%AE%E4%BB%B6%E6%9C%8D%E5%8A%A1/</link><pubDate>Mon, 10 Jan 2022 22:15:41 +0800</pubDate><guid>https://axionl.me/p/maddy-%E8%87%AA%E5%BB%BA%E9%82%AE%E4%BB%B6%E6%9C%8D%E5%8A%A1/</guid><description><img src="https://axionl.me/p/maddy-%E8%87%AA%E5%BB%BA%E9%82%AE%E4%BB%B6%E6%9C%8D%E5%8A%A1/banner.png" alt="Featured image of post Maddy 自建邮件服务" /><p>从白嫖 Yandex 域名邮箱到 FastMail 付费托管邮箱,一直在找适合自己的域名邮件服务,传统的自建方式模块过于分散,上手难度较大,后在 NickCao 老师推荐下尝试了 Maddy。Maddy 目前只提供了命令行运行的 Linux 服务端,WebUI 或者本地客户端需自行选择,仅需手动配置一下 POP3/IMAP(收) 和 SMTP(发) 服务端地址即可。我目前使用的是 <a class="link" href="https://www.thunderbird.net/" target="_blank" rel="noopener"
>Thunderbird</a> (电脑)和 <a class="link" href="https://k9mail.app/" target="_blank" rel="noopener"
>K-9 Mail</a>(Android)。</p>
<blockquote>
<p>下载:<a class="link" href="https://github.com/foxcpp/maddy/releases" target="_blank" rel="noopener"
>Github</a> | <a class="link" href="https://maddy.email/builds/" target="_blank" rel="noopener"
>上游服务器</a>
文档:<a class="link" href="https://maddy.email" target="_blank" rel="noopener"
>maddy.email</a></p>
</blockquote>
<h2 id="服务器">服务器</h2>
<p>部分 VPS 提供商会为了防止广告等原因会禁用 25 号 TCP 端口的 SMTP 端口,但多数情况下(比如 Google Cloud 就不允许)也可以开工单说明邮箱用途和性质,对于个人性质的域名邮箱来说一般不会有太多限制。如果机器本身或者 VPS 提供商还配有防火墙,请打开对应端口(<code>25</code>,<code>465</code>,<code>993</code>)。</p>
<p>使用邮件服务需要关闭 CDN 代理,故存在机器 IP 暴露风险,在选择机器时候注意<strong>避开其它敏感数据服务</strong>。</p>
<h2 id="配置">配置</h2>
<p>可以从 docker 拉取,但这里以 binary + 自己配置方式为主。</p>
<h3 id="maddyconf">maddy.conf</h3>
<blockquote>
<p><a class="link" href="https://github.com/foxcpp/maddy/blob/master/maddy.conf" target="_blank" rel="noopener"
>完整版配置</a></p>
</blockquote>
<p>一般放在 <code>/etc/maddy/maddy.conf</code></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span><span class="lnt">140
</span><span class="lnt">141
</span><span class="lnt">142
</span><span class="lnt">143
</span><span class="lnt">144
</span><span class="lnt">145
</span><span class="lnt">146
</span><span class="lnt">147
</span><span class="lnt">148
</span><span class="lnt">149
</span><span class="lnt">150
</span><span class="lnt">151
</span><span class="lnt">152
</span><span class="lnt">153
</span><span class="lnt">154
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-nginx" data-lang="nginx"><span class="line"><span class="cl"><span class="c1"># 预设了三个变量,方便后续使用
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">$(hostname)</span> <span class="p">=</span> <span class="s">mail.example.com</span>
</span></span><span class="line"><span class="cl">$<span class="s">(primary_domain)</span> <span class="p">=</span> <span class="s">example.com</span>
</span></span><span class="line"><span class="cl">$<span class="s">(local_domains)</span> <span class="p">=</span> $<span class="s">(primary_domain)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 如果要使用 nginx 反代,这里可以选择 tls off,但如此一来没法生成 dkim 密钥对
</span></span></span><span class="line"><span class="cl"><span class="c1"># 在之后检查时日志内会有安全警告,故推荐直接用 maddy 管理
</span></span></span><span class="line"><span class="cl"><span class="c1"># tls off
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="s">tls</span> <span class="s">file</span> <span class="s">/etc/letsencrypt/live/</span>$<span class="s">(local_domains)/fullchain.pem</span> <span class="s">/etc/letsencrypt/live/</span>$<span class="s">(local_domains)/privkey.pem</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 数据用 SQLite3 存储较为简单、轻量
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="s">auth.pass_table</span> <span class="s">local_authdb</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">table</span> <span class="s">sql_table</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">driver</span> <span class="s">sqlite3</span>
</span></span><span class="line"><span class="cl"> <span class="s">dsn</span> <span class="s">credentials.db</span>
</span></span><span class="line"><span class="cl"> <span class="s">table_name</span> <span class="s">passwords</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"><span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="s">storage.imapsql</span> <span class="s">local_mailboxes</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">driver</span> <span class="s">sqlite3</span>
</span></span><span class="line"><span class="cl"> <span class="s">dsn</span> <span class="s">imapsql.db</span>
</span></span><span class="line"><span class="cl"><span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ----------------------------------------------------------------------------
</span></span></span><span class="line"><span class="cl"><span class="c1"># SMTP endpoints + message routing
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="s">hostname</span> $<span class="s">(hostname)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="s">table.chain</span> <span class="s">local_rewrites</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">optional_step</span> <span class="s">regexp</span> <span class="s">&#34;(.+)\+(.+)@(.+)&#34;</span> <span class="s">&#34;</span><span class="nv">$1@$3&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="s">optional_step</span> <span class="s">static</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">entry</span> <span class="s">postmaster</span> <span class="s">postmaster@</span>$<span class="s">(primary_domain)</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="s">optional_step</span> <span class="s">file</span> <span class="s">/etc/maddy/aliases</span>
</span></span><span class="line"><span class="cl"><span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="s">msgpipeline</span> <span class="s">local_routing</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">destination</span> <span class="s">postmaster</span> $<span class="s">(local_domains)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">modify</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">replace_rcpt</span> <span class="s">&amp;local_rewrites</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">deliver_to</span> <span class="s">&amp;local_mailboxes</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">default_destination</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">reject</span> <span class="mi">550</span> <span class="mi">5</span><span class="s">.1.1</span> <span class="s">&#34;User</span> <span class="s">doesn&#39;t</span> <span class="s">exist&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"><span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># smtp 使用 25 号端口发送邮件
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="s">smtp</span> <span class="s">tcp://[::]:25</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># tls self_signed
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kn">limits</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># Up to 20 msgs/sec across max. 10 SMTP connections.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kn">all</span> <span class="s">rate</span> <span class="mi">20</span> <span class="s">1s</span>
</span></span><span class="line"><span class="cl"> <span class="s">all</span> <span class="s">concurrency</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">dmarc</span> <span class="s">yes</span>
</span></span><span class="line"><span class="cl"> <span class="s">check</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">require_mx_record</span>
</span></span><span class="line"><span class="cl"> <span class="s">dkim</span> <span class="c1"># 若无则不检查
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="s">spf</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">source</span> $<span class="s">(local_domains)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">reject</span> <span class="mi">501</span> <span class="mi">5</span><span class="s">.1.8</span> <span class="s">&#34;Use</span> <span class="s">Submission</span> <span class="s">for</span> <span class="s">outgoing</span> <span class="s">SMTP&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="s">default_source</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">destination</span> <span class="s">postmaster</span> $<span class="s">(local_domains)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">deliver_to</span> <span class="s">&amp;local_routing</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="s">default_destination</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">reject</span> <span class="mi">550</span> <span class="mi">5</span><span class="s">.1.1</span> <span class="s">&#34;User</span> <span class="s">doesn&#39;t</span> <span class="s">exist&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"><span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 如果使用 nginx 反代则这里监听到本地端口即可 tcp://127.0.0.1:587
</span></span></span><span class="line"><span class="cl"><span class="c1"># 不使用则邮件客户端以 SSL/TLS 方式直接访问该地址
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="s">submission</span> <span class="s">tls://[::]:465</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">limits</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># Up to 50 msgs/sec across any amount of SMTP connections.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kn">all</span> <span class="s">rate</span> <span class="mi">50</span> <span class="s">1s</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">auth</span> <span class="s">&amp;local_authdb</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">source</span> $<span class="s">(local_domains)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">check</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">authorize_sender</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">prepare_email</span> <span class="s">&amp;local_rewrites</span>
</span></span><span class="line"><span class="cl"> <span class="s">user_to_email</span> <span class="s">identity</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">destination</span> <span class="s">postmaster</span> $<span class="s">(local_domains)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">deliver_to</span> <span class="s">&amp;local_routing</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="s">default_destination</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">modify</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">dkim</span> $<span class="s">(primary_domain)</span> $<span class="s">(local_domains)</span> <span class="s">default</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="s">deliver_to</span> <span class="s">&amp;remote_queue</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="s">default_source</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">reject</span> <span class="mi">501</span> <span class="mi">5</span><span class="s">.1.8</span> <span class="s">&#34;Non-local</span> <span class="s">sender</span> <span class="s">domain&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"><span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="s">target.remote</span> <span class="s">outbound_delivery</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">limits</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># Up to 20 msgs/sec across max. 10 SMTP connections
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1"># for each recipient domain.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kn">destination</span> <span class="s">rate</span> <span class="mi">20</span> <span class="s">1s</span>
</span></span><span class="line"><span class="cl"> <span class="s">destination</span> <span class="s">concurrency</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="s">mx_auth</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">dane</span>
</span></span><span class="line"><span class="cl"> <span class="s">mtasts</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">cache</span> <span class="s">fs</span>
</span></span><span class="line"><span class="cl"> <span class="s">fs_dir</span> <span class="s">mtasts_cache/</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="s">local_policy</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">min_tls_level</span> <span class="s">encrypted</span>
</span></span><span class="line"><span class="cl"> <span class="s">min_mx_level</span> <span class="s">none</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"><span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="s">target.queue</span> <span class="s">remote_queue</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">target</span> <span class="s">&amp;outbound_delivery</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">autogenerated_msg_domain</span> $<span class="s">(primary_domain)</span>
</span></span><span class="line"><span class="cl"> <span class="s">bounce</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">destination</span> <span class="s">postmaster</span> $<span class="s">(local_domains)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">deliver_to</span> <span class="s">&amp;local_routing</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="s">default_destination</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">reject</span> <span class="mi">550</span> <span class="mi">5</span><span class="s">.0.0</span> <span class="s">&#34;Refusing</span> <span class="s">to</span> <span class="s">send</span> <span class="s">DSNs</span> <span class="s">to</span> <span class="s">non-local</span> <span class="s">addresses&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"> <span class="err">}</span>
</span></span><span class="line"><span class="cl"><span class="err">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ----------------------------------------------------------------------------
</span></span></span><span class="line"><span class="cl"><span class="c1"># IMAP endpoints
</span></span></span><span class="line"><span class="cl"><span class="c1"># 同上,使用 nginx 反代则改为监听本地端口 tcp://127.0.0.1:143
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="s">imap</span> <span class="s">tls://[::]:993</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">auth</span> <span class="s">&amp;local_authdb</span>
</span></span><span class="line"><span class="cl"> <span class="s">storage</span> <span class="s">&amp;local_mailboxes</span>
</span></span><span class="line"><span class="cl"><span class="err">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="nginx-config可选">Nginx Config(可选)</h3>
<p>如果是由 Maddy 自身直接处理 TLS 则不需要该项配置</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-nginx" data-lang="nginx"><span class="line"><span class="cl"><span class="k">upstream</span> <span class="s">maddy_imaps</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># 指向本地 Maddy IMAP 监听服务端口
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kn">server</span> <span class="n">127.0.0.1</span><span class="p">:</span><span class="mi">143</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">upstream</span> <span class="s">maddy_smtps</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># 指向本地 Maddy SMTP 服务监听端口
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kn">server</span> <span class="n">127.0.0.1</span><span class="p">:</span><span class="mi">587</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">server</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">listen</span> <span class="mi">993</span> <span class="s">ssl</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kn">proxy_pass</span> <span class="s">maddy_imaps</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kn">ssl_certificate</span> <span class="s">/etc/letsencrypt/live/&lt;example.com&gt;/fullchain.pem</span><span class="p">;</span> <span class="c1"># 换成自己的域名证书
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kn">ssl_certificate_key</span> <span class="s">/etc/letsencrypt/live/&lt;example.com&gt;/privkey.pem</span><span class="p">;</span> <span class="c1"># 换成自己的域名证书
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kn">ssl_protocols</span> <span class="s">SSLv3</span> <span class="s">TLSv1.1</span> <span class="s">TLSv1.2</span> <span class="s">TLSv1.3</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kn">ssl_ciphers</span> <span class="s">HIGH:!aNULL:!MD5</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kn">ssl_session_timeout</span> <span class="s">4h</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kn">ssl_handshake_timeout</span> <span class="s">30s</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">server</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kn">listen</span> <span class="mi">465</span> <span class="s">ssl</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kn">proxy_pass</span> <span class="s">maddy_smtps</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kn">ssl_certificate</span> <span class="s">/etc/letsencrypt/live/&lt;example.com&gt;/fullchain.pem</span><span class="p">;</span> <span class="c1"># managed by Certbot
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kn">ssl_certificate_key</span> <span class="s">/etc/letsencrypt/live/&lt;example.com&gt;/privkey.pem</span><span class="p">;</span> <span class="c1"># managed by Certbot
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kn">ssl_protocols</span> <span class="s">SSLv3</span> <span class="s">TLSv1.1</span> <span class="s">TLSv1.2</span> <span class="s">TLSv1.3</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kn">ssl_ciphers</span> <span class="s">HIGH:!aNULL:!MD5</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kn">ssl_session_timeout</span> <span class="s">4h</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kn">ssl_handshake_timeout</span> <span class="s">30s</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="注册账户">注册账户</h3>
<p>maddy 的 systemd service 正常启动后可以使用:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo -u maddy -s <span class="c1"># 切换到 maddy 用户</span>
</span></span><span class="line"><span class="cl">$ maddyctl creds create &lt;[email protected]&gt; --password &lt;YourPassword&gt;
</span></span><span class="line"><span class="cl">$ maddyctl creds list <span class="c1"># 查看你刚创建的用户名</span>
</span></span><span class="line"><span class="cl">$ maddyctl imap-acct create &lt;[email protected]&gt; <span class="c1"># 创建一个邮件储存账户</span>
</span></span><span class="line"><span class="cl">$ maddyctl imap-acct list <span class="c1"># 查看刚创建的 imap 储存账户</span>
</span></span><span class="line"><span class="cl">$ maddyctl imap-mboxes list &lt;[email protected]&gt; <span class="c1"># 可以看到该账户下有哪些分类</span>
</span></span><span class="line"><span class="cl">$ maddyctl imap-msgs list &lt;[email protected]&gt; &lt;INBOX&gt; <span class="c1"># 可以查看当前账户对应分类接收到的邮件,一般收件在 INBOX 中</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="dns-设置">DNS 设置</h2>
<p>这里以 Cloudflare 托管 DNS 服务为例,其它应该也能找到对应 DNS 设置面板。使用了子域名 <code>mail.example.com</code> 作为邮件服务专用。</p>
<table>
<thead>
<tr>
<th style="text-align:center">类型</th>
<th style="text-align:center">名称</th>
<th style="text-align:center">内容</th>
<th>代理状态</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">A</td>
<td style="text-align:center">mail</td>
<td style="text-align:center">服务器实际 IPv4 地址</td>
<td>仅限 DNS</td>
</tr>
<tr>
<td style="text-align:center">AAAA</td>
<td style="text-align:center">mail</td>
<td style="text-align:center">服务器实际 IPv6 地址(如果有)</td>
<td>仅限 DNS</td>
</tr>
<tr>
<td style="text-align:center">MX</td>
<td style="text-align:center">@</td>
<td style="text-align:center">mail.example.com</td>
<td>仅限 DNS</td>
</tr>
<tr>
<td style="text-align:center">TXT</td>
<td style="text-align:center">mail</td>
<td style="text-align:center">v=spf1 mx ~all</td>
<td>仅限 DNS</td>
</tr>
</tbody>
</table>
<p>spf 值这里推荐使用仅允许 mx,若有其他来源也可以添加。</p>
<h2 id="reverse-dns">Reverse DNS</h2>
<p>为了避免拒收,进一步提高邮件投递率,需要配置 rDNS 以便收信方邮件服务商溯源。</p>
<p>以 Vultr 为例,其 Reverse DNS 页面在 <code>机器详情 &gt; Settings &gt; IPv4 / IPv6</code> 选项卡内,在 Reverse DNS 中填入自己的邮件服务域名即可,如 mail.example.com,如果存在多条公共 IP 地址,则都需要填写。</p>
<h2 id="多域名配置-如无可跳过">多域名配置 (如无可跳过)</h2>
<ol>
<li>在 <code>local_domains</code> 后面加上新的域名</li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-nginx" data-lang="nginx"><span class="line"><span class="cl"><span class="k">$(primary_domain)</span> <span class="p">=</span> <span class="s">example.com</span>
</span></span><span class="line"><span class="cl">$<span class="s">(secondary_domain)</span> <span class="p">=</span> <span class="s">example.org</span>
</span></span><span class="line"><span class="cl">$<span class="s">(local_domains)</span> <span class="p">=</span> $<span class="s">(primary_domain)</span> $<span class="s">(secondary_domain)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ol start="2">
<li>在 tls file 后面添加对应的证书,如果用 nginx 反代的话则添加对应的 host 路由和域名。</li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-nginx" data-lang="nginx"><span class="line"><span class="cl"><span class="k">tls</span> <span class="s">file</span> <span class="s">/etc/letsencrypt/live/</span>$<span class="s">(primary_domain)/fullchain.pem</span> <span class="s">/etc/letsencrypt/live/</span>$<span class="s">(primary_domain)/privkey.pem</span> <span class="s">/etc/letsencrypt/live/</span>$<span class="s">(secondary_domain)/fullchain.pem</span> <span class="s">/etc/letsencrypt/live/</span>$<span class="s">(secondary_domain)/privkey.pem</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ol start="3">
<li>
<p>将新域名的 dkim 密钥内容也添加到 DNS 的 TXT 记录中</p>
</li>
<li>
<p>dmarc 和 rDNS 同理</p>
</li>
</ol>
<h2 id="客户端">客户端</h2>
<p>客户端有诸多选择,不变的是手动设置方式:</p>
<ul>
<li>IMAP 和 SMTP 服务器地址都设置为 <code>mail.example.com</code>,连接方式均为 <code>SSL/TLS</code>,用户名和密码均为先前所设置,认证方式均为 <code>Normal Password</code>。</li>
<li>IMAP 端口为 <code>993</code>,</li>
<li>SMTP 端口为 <code>465</code></li>
</ul>
<h2 id="小结">小结</h2>
<p><img src="https://axionl.me/p/maddy-%E8%87%AA%E5%BB%BA%E9%82%AE%E4%BB%B6%E6%9C%8D%E5%8A%A1/oh_my_yandex.jpg"
width="300"
height="300"
srcset="https://axionl.me/p/maddy-%E8%87%AA%E5%BB%BA%E9%82%AE%E4%BB%B6%E6%9C%8D%E5%8A%A1/oh_my_yandex_hu01f01a67232b7fa6f27a9ebc9f5bf054_12968_480x0_resize_q75_box.jpg 480w, https://axionl.me/p/maddy-%E8%87%AA%E5%BB%BA%E9%82%AE%E4%BB%B6%E6%9C%8D%E5%8A%A1/oh_my_yandex_hu01f01a67232b7fa6f27a9ebc9f5bf054_12968_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
alt="Oh My Yandex"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
></p>
<p>可以写一些稍微正经的内容,发送到 <a class="link" href="https://www.mail-tester.com" target="_blank" rel="noopener"
>https://www.mail-tester.com</a> 内所给的邮件地址,来测试自己的邮箱评分。</p>
<p>虽然说自建邮箱可能还是存在邮件投递到垃圾箱里的问题,但有了 Maddy 后搭建一个自己的域名邮箱确实变成了相对简单的工作。</p></description></item><item><title>[OhMyQt 系列] _00__搭建环境</title><link>https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/</link><pubDate>Sat, 24 Jul 2021 00:39:13 +0800</pubDate><guid>https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/</guid><description><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/banner.png" alt="Featured image of post [OhMyQt 系列] _00__搭建环境" /><h2 id="前言">前言</h2>
<blockquote>
<p>项目地址: <a class="link" href="https://github.com/axionl/OhMyQt" target="_blank" rel="noopener"
>axionl/OhMyQt</a></p>
</blockquote>
<ul>
<li>项目在 Windows 11 和 ArchLinux 下进行测试</li>
<li>Qt 版本: 5.15.2</li>
</ul>
<p>本文是 OhMyQt 系列的第 00 章节,主要介绍在 Windows 11 和 ArchLinux 下如何搭建一个可用的 Qt 开发环境。</p>
<h2 id="在-archlinux-上搭建">在 ArchLinux 上搭建</h2>
<h3 id="基本软件安装">基本软件安装</h3>
<p>首先你需要安装 qt5-base,同时推荐安装对应的文档包 qt5-doc</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo pacman -S qt5-base
</span></span><span class="line"><span class="cl">$ sudo pacman -S qt5-doc <span class="c1"># 可选</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>然后安装一个合用的编辑器,这里推荐使用 qtcreator</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo pacman -S qtcreator
</span></span></code></pre></td></tr></table>
</div>
</div><p>因为本教程主要是介绍 QML 的开发,所以还需要安装 qt5-declarative</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo pacman -S qt5-declarative
</span></span></code></pre></td></tr></table>
</div>
</div><p>安装完成之后验证版本信息</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ qmake -v
</span></span><span class="line"><span class="cl">QMake version 3.1
</span></span><span class="line"><span class="cl">Using Qt version 5.15.2 in /usr/lib
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">$ pacman -Qs qt5-declarative
</span></span><span class="line"><span class="cl">local/qt5-declarative 5.15.2+kde+r29-1 <span class="o">(</span>qt qt5<span class="o">)</span>
</span></span><span class="line"><span class="cl"> Classes <span class="k">for</span> QML and JavaScript languages
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">$ qtcreator -version
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Qt Creator 4.15.2 based on Qt 5.15.2
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="软件配置">软件配置</h3>
<p>首先打开 qtcreator,新建一个 QtQuick 项目</p>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator1.png"
width="1901"
height="1039"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator1_hu9cc792a18713befa1403035370c08e65_117515_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator1_hu9cc792a18713befa1403035370c08e65_117515_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="新建项目"
class="gallery-image"
data-flex-grow="182"
data-flex-basis="439px"
></p>
<p>然后输入名称和路径</p>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator2.png"
width="791"
height="519"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator2_hu82ebd35a7a537086a44dfe1df5c51482_34221_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator2_hu82ebd35a7a537086a44dfe1df5c51482_34221_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="项目名和路径"
class="gallery-image"
data-flex-grow="152"
data-flex-basis="365px"
></p>
<p>下一步编译系统建议选择 cmake</p>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator3.png"
width="801"
height="528"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator3_hu83a700fec5c8bc92f5882469d3c9647c_24219_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator3_hu83a700fec5c8bc92f5882469d3c9647c_24219_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="编译系统"
class="gallery-image"
data-flex-grow="151"
data-flex-basis="364px"
></p>
<p>QT 版本保持默认</p>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator4.png"
width="802"
height="527"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator4_hu4e4328150d0e1974479982c49c290434_27008_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator4_hu4e4328150d0e1974479982c49c290434_27008_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="QT 版本"
class="gallery-image"
data-flex-grow="152"
data-flex-basis="365px"
></p>
<p>因为暂时是教学项目,暂时不添加语言文件</p>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator5.png"
width="797"
height="526"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator5_hub4baf059e27fe7b35971168e3ae803de_34446_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator5_hub4baf059e27fe7b35971168e3ae803de_34446_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="语言文件"
class="gallery-image"
data-flex-grow="151"
data-flex-basis="363px"
></p>
<p>kit 保持默认的 Desktop 就好,因为我们最终也是要做一个桌面应用</p>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator6.png"
width="795"
height="527"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator6_hu5d51efb104b39963d45195934fa21366_29308_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator6_hu5d51efb104b39963d45195934fa21366_29308_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="Kit"
class="gallery-image"
data-flex-grow="150"
data-flex-basis="362px"
></p>
<p>会创建的文件如下所示,你也可以选择加入 git 作为版本控制</p>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator7.png"
width="793"
height="524"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator7_hu6a73af58d9accf7d29cff1cb151119d5_41002_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator7_hu6a73af58d9accf7d29cff1cb151119d5_41002_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="summary"
class="gallery-image"
data-flex-grow="151"
data-flex-basis="363px"
></p>
<p>点击左下角的运行按钮,就可以看到运行的 HelloWorld 窗口了</p>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator8.png"
width="1899"
height="1036"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator8_hu17238bd37e7d8ec27abbdccce7f9c34e_89297_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/qtcreator8_hu17238bd37e7d8ec27abbdccce7f9c34e_89297_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="HelloWorld"
class="gallery-image"
data-flex-grow="183"
data-flex-basis="439px"
></p>
<p>恭喜你,已经搭建好了本教程的开发环境!</p>
<h2 id="在-windows-11-上搭建">在 Windows 11 上搭建</h2>
<h3 id="通过-installer-安装">通过 Installer 安装</h3>
<blockquote>
<p><a class="link" href="https://www.qt.io/download" target="_blank" rel="noopener"
>https://www.qt.io/download</a></p>
</blockquote>
<p>注册账号并下载开源版本(需遵守 GPL 许可并限于个人使用)</p>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/installation_folder.png"
width="952"
height="632"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/installation_folder_hu65d40ae02004ed0aec9f4b6e8006dc1d_233150_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/installation_folder_hu65d40ae02004ed0aec9f4b6e8006dc1d_233150_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="installation folder"
class="gallery-image"
data-flex-grow="150"
data-flex-basis="361px"
></p>
<p><strong>此处安装路径至今未支持带空格</strong>,故不要选择常见的 <code>C:\Program Files</code> 等目录</p>
<p>手动最小化安装则选择 <code>Custom Installation</code></p>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/select_components.png"
width="1187"
height="632"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/select_components_hue6768a7fe11425ee2810af592f8759dd_307295_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/select_components_hue6768a7fe11425ee2810af592f8759dd_307295_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="select components"
class="gallery-image"
data-flex-grow="187"
data-flex-basis="450px"
></p>
<p>至少需要选择一个版本的 Qt 支持(如 <code>MinGW 8.1.0 64-bit</code> 包含了 Qt 和其他所需的一些环境),而 <code>QtCreator</code> 作为 IDE 在下方已经被默认勾选了,还有 <code>CMake</code> 如果需要或是已经手动安装则可消去。等待联网装好后即可使用</p>
<h3 id="通过第三方包管理器安装">通过第三方包管理器安装</h3>
<p><code>chocolately</code> 也提供了 <a class="link" href="https://community.chocolatey.org/packages/qtcreator" target="_blank" rel="noopener"
>QtCreator</a> 的安装脚本和基本的 <a class="link" href="https://community.chocolatey.org/packages/qt5-default" target="_blank" rel="noopener"
>Qt5 SDK</a> 环境</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-PowerShell" data-lang="PowerShell"><span class="line"><span class="cl"><span class="n">choco</span> <span class="n">install</span> <span class="n">-y</span> <span class="nb">qt5-default</span> <span class="n">qtcreato</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>脚本会自动下载安装,默认路径为 <code>C:\Qt</code></p>
<h3 id="配置工具链">配置工具链</h3>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/toolkits.png"
width="993"
height="714"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/toolkits_hu4d86a381a539d2b3e5022c6c05038585_42673_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/toolkits_hu4d86a381a539d2b3e5022c6c05038585_42673_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="toolkits"
class="gallery-image"
data-flex-grow="139"
data-flex-basis="333px"
></p>
<p>QtCreator 左边 <code>Projects</code> 有配置工具链的地方,通常来说会自动检测是否已经安装对应工具并设置,如果需要自定义或者不在查找范围内的目录,则可以手动进行指定。</p>
<p>若在开发时终端需要运行 Qt 程序,则需要将库所在目录添加到环境变量 <code>PATH</code> 中(如 <code>C:\Qt\5.15.2\mingw81_64\bin</code>)</p>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/environment.png"
width="618"
height="585"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/environment_hu3b5b6aaa656ce69f1077215323465e69_28183_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-_00__%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83/environment_hu3b5b6aaa656ce69f1077215323465e69_28183_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="environment"
class="gallery-image"
data-flex-grow="105"
data-flex-basis="253px"
></p>
<p>若是打包和分发的话则需要带上对应的动态链接库。</p>
<h2 id="小结">小结</h2>
<p>Linux 平台上开发相对方便,而 Windows 平台上开发则受到没有合适包管理的限制,需要自己折腾一下。下一节将会正式开始教程中的第一个 Demo,一个用于展示自己内容的 Hello World 程序。</p></description></item><item><title>[OhMyQt 系列] 01_HelloWorld</title><link>https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-01_helloworld/</link><pubDate>Tue, 20 Jul 2021 10:58:40 +0800</pubDate><guid>https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-01_helloworld/</guid><description><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-01_helloworld/banner.png" alt="Featured image of post [OhMyQt 系列] 01_HelloWorld" /><h2 id="前言">前言</h2>
<blockquote>
<p>项目地址: <a class="link" href="https://github.com/axionl/OhMyQt" target="_blank" rel="noopener"
>axionl/OhMyQt</a></p>
</blockquote>
<ul>
<li>项目在 Windows 11 和 ArchLinux 下进行测试</li>
<li>Qt 版本: 5.15.2</li>
</ul>
<p>本文以项目构建的角度介绍一个简单 Qt 应用的开发,其余具体的环境安装和配置稍后会在第 0 节内容中放出。</p>
<h2 id="从看见到设计">从看见到设计</h2>
<p>我们需要一个简单的展示页面作为上手的第一个项目:</p>
<ul>
<li>一个醒目的标题</li>
<li>一段用于描述的文字</li>
<li>还有一个好看的背景</li>
</ul>
<p>假设我们已经做了出来,它长下面这个样子,你需要做的是把它保留在你的想象中,我们再回过头来考虑如何实现。</p>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-01_helloworld/preview.png"
width="1920"
height="1080"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-01_helloworld/preview_hu85caa472e9bc90ba71d5339c7711fdd3_1488388_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-01_helloworld/preview_hu85caa472e9bc90ba71d5339c7711fdd3_1488388_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="preview"
class="gallery-image"
data-flex-grow="177"
data-flex-basis="426px"
></p>
<h3 id="布局">布局</h3>
<p>我们把窗口想象成一个盒子(而不是一个平面或者一张桌子,因为盒子横看有四壁,俯瞰有纵深),而所需要填入的内容当成另一个小些的盒子,套入到窗口这个大盒子中。结合我们多年糊 PPT 的水平,可以对界面有如下设计要求:</p>
<ul>
<li>内容整体居中</li>
<li>标题和描述上下排布</li>
<li>内容之间最好有一定的间距</li>
</ul>
<p><img src="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-01_helloworld/layout.png"
width="730"
height="549"
srcset="https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-01_helloworld/layout_hua50c8d7697c036278e5e2f296d277e31_33333_480x0_resize_box_3.png 480w, https://axionl.me/p/ohmyqt-%E7%B3%BB%E5%88%97-01_helloworld/layout_hua50c8d7697c036278e5e2f296d277e31_33333_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="layout"
class="gallery-image"
data-flex-grow="132"
data-flex-basis="319px"
></p>
<p>如上图所示,我们把这一些要求的集合称为 “布局” 也即 Layout,它决定了我们软件设计的基本框架。上面的每一项具体内容称为 “元素” 即 Element / Item。有的人设计 PPT 的时候会说:“应甲方要求,标题一定要大!”,那这属于元素的“属性”,即 Property。于是我们来抽象实现一下这个布局(<strong>注意不是直接能用的代码</strong>):</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-qml" data-lang="qml"><span class="line"><span class="cl"><span class="c1">// 基本元素如下
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">Window</span> <span class="p">{</span> <span class="c1">// 窗口一个大盒子
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">Box</span> <span class="p">{</span> <span class="c1">// 里面套个小盒子
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">Title</span> <span class="p">{}</span> <span class="c1">// 盒子里面有标题
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">Description</span> <span class="p">{}</span> <span class="c1">// 标题下面有描述
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>进一步加上居中对齐和间距:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-qml" data-lang="qml"><span class="line"><span class="cl"><span class="nx">Window</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Box</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">anchors.centerIn:</span> <span class="nx">parent</span> <span class="c1">// 居中对齐大盒子
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"> <span class="nx">Title</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">anchors.horizontalCenter:</span> <span class="nx">parent</span><span class="p">.</span><span class="nx">horizontalCenter</span> <span class="c1">// 水平对齐小盒子
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">Description</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">anchors.horizontalCenter:</span> <span class="nx">parent</span><span class="p">.</span><span class="nx">horizontalCenter</span> <span class="c1">// 水平对齐小盒子
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>可以看到,这里引用了一个 <code>parent</code> 的概念,实际上指代上一层父级元素,套娃套在里面的才是娃,文字和描述的父级元素是小盒子,小盒子的父级元素是大窗口。再补上元素的属性和间距:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-qml" data-lang="qml"><span class="line"><span class="cl"><span class="nx">Window</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">width:</span> <span class="mi">960</span> <span class="c1">// 窗口宽度
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">height:</span> <span class="mi">720</span> <span class="c1">// 窗口高度
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"> <span class="nx">Box</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">anchors.centerIn:</span> <span class="nx">parent</span>
</span></span><span class="line"><span class="cl"> <span class="k">implicitWidth:</span> <span class="mi">360</span> <span class="c1">// 宽度 360 单位(多数情况下理解为像素)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">implicitHeight:</span> <span class="mi">128</span> <span class="c1">// 高度 128 单位
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"> <span class="nx">Title</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">anchors.horizontalCenter:</span> <span class="nx">parent</span><span class="p">.</span><span class="nx">horizontalCenter</span> <span class="c1">// 水平对齐小盒子
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">font.pixelSize:</span> <span class="mi">24</span> <span class="c1">// 标题一定要大
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">Box</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">visible:</span> <span class="kc">false</span> <span class="c1">// 一个看不见的盒子
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">implicitHeight:</span> <span class="mi">16</span> <span class="c1">// 用于拉开标题和描述的间距
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">Description</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">anchors.horizontalCenter:</span> <span class="nx">parent</span><span class="p">.</span><span class="nx">horizontalCenter</span> <span class="c1">// 水平对齐小盒子
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">font.pixelSize:</span> <span class="mi">16</span> <span class="c1">// 精致的描述用小字
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>这些具体元素我们以后会写到如何实现,现在需要用 <code>QtQuick.Controls</code> 提供的一些默认元素替代:</p>
<ul>
<li>Box-&gt;Rectangle</li>
<li>Title / Description -&gt; Text</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-qml" data-lang="qml"><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">QtQuick</span> <span class="mf">2.12</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">QtQuick</span><span class="p">.</span><span class="nx">Window</span> <span class="mf">2.12</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">QtQuick</span><span class="p">.</span><span class="nx">Controls</span> <span class="mf">2.12</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">Window</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">width:</span> <span class="mi">960</span>
</span></span><span class="line"><span class="cl"> <span class="k">height:</span> <span class="mi">720</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">Rectangle</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">anchors.centerIn:</span> <span class="nx">parent</span>
</span></span><span class="line"><span class="cl"> <span class="k">implicitWidth:</span> <span class="mi">360</span>
</span></span><span class="line"><span class="cl"> <span class="k">implicitHeight:</span> <span class="mi">128</span>
</span></span><span class="line"><span class="cl"> <span class="k">color:</span> <span class="s2">&#34;#ef7e9ceb&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">Text</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">id: title</span>
</span></span><span class="line"><span class="cl"> <span class="k">anchors.horizontalCenter:</span> <span class="nx">parent</span><span class="p">.</span><span class="nx">horizontalCenter</span>
</span></span><span class="line"><span class="cl"> <span class="k">text:</span> <span class="s2">&#34;这是一个大标题&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="k">font.pixelSize:</span> <span class="mi">48</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">Rectangle</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">color:</span> <span class="s2">&#34;transparent&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="k">implicitHeight:</span> <span class="mi">16</span>