- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 565177 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174776
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
超全!Python图形界面框架PyQt5使用指南!3 y+ g* K I' s3 r; V0 z# b* R
3 d a8 U2 O$ ?# K% h; e, c
使用Python开发图形界面的软件其实并不多,相对于GUI界面,可能Web方式的应用更受人欢迎。但对于像我一样对其他编程语言比如C#或WPF并不熟悉的人来说,未必不是一个好的工具。5 c+ S9 @! Y2 G! k& T+ u
6 C7 W6 I0 H* r8 _& F
常见GUI框架! U# w" B2 F7 b' J' z1 ~! q8 Z2 N- T
% F: K1 n( C/ Z
PyQt5:Qt是一个跨平台的 C++图形用户界面库。QT一度被诺基亚拥,后出售给芬兰的软件公司Digia Oyj。PyQt5是基于Digia公司Qt5的Python接口,由一组Python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。9 z$ T3 F! y8 J8 t$ \
3 |; c H' U% H. ?0 g( D
Pyside6:Pyside是QT公司官方提供的Python包,上一版本为Pyside2,对应的是QT5,最新版命名规则进行了调整,更改为Pyside6,对应的是QT6版本。由于官方出品的比较看好,缺点是发布比较晚,网上的资料没有PyQt5多。0 l- C/ Z4 g3 Y/ R8 A2 ?$ o% _
4 v+ V9 J+ E4 k9 v, s% k, S9 b6 l3 xTkinter:Python内置的GUI框架,使用TCL实现,Python中内嵌了TCL解释器,使用它的时候不用安装额外的扩展包,直接import,跨平台。不足之处在于UI布局全靠代码实现,只有15种常用部件,显示效果简陋。, d0 r% J* e4 u
$ w7 s+ m' |3 {& K) r. r, u B4 cPySimpleGUI:PySimpleGUI 是 Tkinter 一层包装。使用 PySimpleGUI 实现自定义 GUI 所需的代码量要比使用 Tkinter 直接编写相同的 GUI 要少得多。$ ]7 _* K* P, V" r
# S. [0 P' U v$ xWxPython:wxPython是Python语言对流行的wxWidgets跨平台GUI工具库的绑定。用得比较广泛,跨平台,C++编写,文档少,用户可能就需要根据编程内容对不同平台中的GUI代码做一些调整。遇到问题不好解决,代码布局控件,不直观。
* J* T& D" o( K' u8 y& G, Z( x
1 p: {+ r8 e- jWax:基于wxPython ,为克服wxPython的问题而制作的一个包。
8 U/ U5 |- C- m: ~: R0 s1 V8 d: u9 @. d# ?
Kivy:主要针对多点触控程序,智能手机平板等,也可以在没有触屏功能的系统上,全平台支持(Windows, Linux, Mac OS X, Android and iOS.)使用Python和cython编写,中文支持差,需要自己下载中文库并且制定路径。
9 r- ]3 a. S" q' H/ v% k7 ?, O2 X+ [ }4 v1 X4 F
BeeWare:Write once. Deploy everywhere.需要与Kivy配合使用。
- ~& f# ]+ Q" u) G0 x' u# ~
9 Q R4 D5 w: y# l# ?Toga:一个使用Python开发原生APP的GUI工具包。Toga由一个具有共享接口的基础组件库组成,以简化与平台无关的GUI开发。Toga适用于Mac OS、Windows、Linux(GTK)以及Android和iOS等移动平台。
1 g0 R: t( T- ~/ t2 S0 P$ X$ ]; y0 k& y8 V( D
Eel:一个轻量的 Python 库,用于制作简单的类似于 Electron(但是比它更轻量) 的离线 HTML/JS GUI 应用程序,并具有对 Python 功能(capabilities)和库的完全访问权限。* t2 w' i- g0 @; h
" o0 C4 O5 ?3 ~5 Z! BFlexx:一个纯 Python 工具包,用来创建图形化界面应用程序。其使用 Web 技术进行界面的渲染。你可以用 Flexx 来创建桌面应用,同时也可以导出一个应用到独立的 HTML 文档。因为使用纯 Python 开发,所以 Flexx 是跨平台的。只需要有 Python 和浏览器就可以运行。
( r: J7 H% _# `, @4 ?( f
( A( `9 I; x( m7 \0 f z: L0 ypywebview是围绕 webview 组件的轻量型跨平台包装器(wrapper),它允许在其自己的本机 GUI 窗口中显示 HTML 内容。它使您可以在桌面应用程序中使用 Web 技术,同时尽最大可能隐藏使用浏览器构建GUI的事实。. K+ B2 U' F/ V8 x) C. ^7 |
e" A# K% E0 R, C& V! D+ r
enaml:一种能够让你用最小的努力就可以实现高质量GUI界面的的Python框架,也是一种独特的编程语言。enaml将声明性语言与基于约束的布局系统结合在一起,使用户可以轻松地定义灵活布局的UI。enaml应用程序可以在任何支持Python和Qt的平台上运行。1 p7 j! w, Q0 Q$ J) v
$ f: b5 m% q* y1 @+ R个人想法:太多学不完,先学PyQt5,原因是资料多,学有余力再学pyside6,最后看下PySimpleGUI,看能否解决一些简单问题。
7 r! i# D; H( N& f' S( Y2 {0 q# z& W! c) [* [$ y- k+ o
PyQt5简介
) L4 D6 ?5 { v* u$ m2 Y* \1 o/ j+ f6 V8 B# W7 @
PyQt是Qt框架的Python语言实现,由Riverbank Computing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件,因此PyQt的API接口与Qt的API接口很接近,但PyQt不再使用QMake系统和Q_OBJECT宏。9 Q0 H. a7 R N! O K' D1 |2 F
% G! A& ]. k% i; p
PyQt5提供GPL版和商业版证书,自由开发者可以使用免费的GPL许可,如果需要将PyQt用于商业应用,则必须购买商业许可。' R& {. F( _( S# e8 R" z# T2 N
, g+ Z. W$ F N4 C7 VPyQt5特性如下:
5 }; Z# p3 o# }. C6 u$ l
- H$ ^8 i) n3 I$ _5 w/ X- j基于高性能的Qt的GUI控件集。
. l2 _& ~1 i" Y: h% a: q6 h# M2 J D# t- F
能够跨平台运行在Linux、Window和Mac OS系统上。
$ ?! q) r1 w2 n* M8 q& B. _' x5 d- m$ y- [- f/ a! h
使用信号槽机制进行通信。9 g8 o, n% Z% I. @
7 P L. v8 b8 U; U5 _! u& T对Qt库进行完全封装。
/ @& o7 n: ~* Y/ a
& G* d; L' |; Y j可以使用成熟的IDE进行界面设计,并自动生成可执行的Python代码。" J' v/ @) j. q f) o4 c0 G) v
1 w5 U' A6 k' G# I% S提供一整套种类齐全的窗口控件。5 \6 b2 g* a k7 }" l5 U
& q6 |5 d0 j# U+ U
PyQt5是由一系列Python模块组成,有超过620个类,6000个函数和方法,主要模块如下:( L! d9 k1 G0 ~' @. B" _
`! t, D7 J( `# M( V3 V/ rQtCore:包含了核心的非 GUI 的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime 类文件、进程与线程一起使用。
4 v9 B# Y9 f2 w. ?+ E( ]5 l y9 C: O% B! H/ y
QtGui:包含了窗口系统、事件处理、2D 图像、基本绘画、字体和文字类。; ]' X7 }) F& x( g
3 `( V @* S5 {' DQtWidgets:包含了一系列创建桌面应用的 UI 元素。6 t7 E1 A% b" s; t4 `+ L# R
1 E l( i. z: M! SQtMultimedia:包含了处理多媒体的内容和调用摄像头 API 的类。
3 k. M& X/ ^: L6 \4 O& W3 {/ m7 g: l
QtBluetooth:包含了查找和连接蓝牙的类。' p' Z. ~5 A5 R6 |, p7 j
- ~* [/ T6 S @; ?. g
QtNetwork:包含了网络编程的类,这些工具能让 TCP/IP 和 UDP 开发变得更加方便和可靠。7 W h5 {0 V6 _$ R' d |5 F; x
+ D6 S5 ~" q/ B& g3 ~; g
QtPositioning:包含了定位的类,可以使用卫星、WiFi 甚至文本。
0 @6 @- M& u4 k! _6 o- ?& w
+ k) b5 H+ C5 d' t/ ~2 L; HEnginio:包含了通过客户端进入和管理 Qt Cloud 的类。
( c& D1 a4 P4 }5 M7 }$ U8 n0 y. ?3 X, X# g
QtWebSockets:包含了 WebSocket 协议的类。# w* a* K) N" X) p1 U8 K/ t
9 |& d$ {+ D) s2 K8 o; u! ~2 lQtWebKit:包含了一个基 WebKit2 的 web 浏览器。& N4 ?3 f- b! j! q6 N4 i
9 p* A, C2 N5 A! J. m9 l
QtWebKitWidgets:包含了基于 QtWidgets 的 WebKit1 的类。
4 N4 ~9 A& `4 n
: z r: \4 q% O5 W7 WQtXml:包含了处理 xml 的类,提供了 SAX 和 DOM API 的工具。3 s/ \9 B. V2 w1 Q
# e, g9 Y4 ~' M
QtSvg:提供了显示 SVG 内容的类,Scalable Vector Graphics (SVG) 是一种是一种基于可扩展标记语言 (XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。
0 t* E4 n0 ?6 P6 v: o7 @+ R* o
3 W0 L+ J( K' s' \. M/ fQtSql:提供了处理数据库的工具。
4 L- j. u) j2 E- w+ C2 @
, Y" q9 b6 F t: BQtTest:提供了测试 PyQt5 应用的工具。
( L& w) Q3 N- W& v5 W G! s) v* a/ d) |- F) A! f
PyQt5的安装8 I- W* k9 }: f% d+ m( y, E. p* }
* R. i9 z( e4 V: f8 V由于后期要使用fbs进行打包,fbs对Python 3.7以后的版本可能存在兼容问题,所以我选择了Python 3.6.8进行了整个环境的搭建。主要内容为:Python + PyCharm + PyQt5
9 X$ d, Q" M2 K' D1 j* w0 F8 G' M. o& r! z& R) Y+ P
安装PyQt52 o, p" G/ L/ x0 B
$ N" o( v& ?4 E7 i) I- N l& rpip install pyqt5
% Y9 t7 O6 A, c/ C
6 P1 A# U- b' h$ Upip install pyqt5-tools
* Q# s, a6 ~: Q" J( y* c其中pyqt5-tools为Qt Designer拖拽式的界面设计工具。安装过程中可能会报如下错误:6 I9 l) ~7 I/ f9 R' P
+ N& Y2 t3 ~# a9 p# x1 J% c: @
qt5-tools 5.15.2.1.2 has requirement click~=7.0, but you'll have click 8.0.1 which is incompatible.
* _3 X$ t' T2 h, X f7 j1 [% K解决方案:9 \) R; L7 v; m) b2 Q, [8 L, f
# Y; N' _5 x# J8 n8 E" D
pip install click~=7.0
. X+ |- n3 o4 [3 \Qt Designer的配置 l: n: ]7 z& }' R% }( G* C- |0 g
' }' s& a5 L3 D% k& j ?
Qt Designer 是通过拖拽的方式放置控件,并实时查看控件效果进行快速UI设计。0 W. X! o# e, x2 \# N) p% f _, ?' z
8 M- }+ S" h! e0 G* N7 `
, y* e7 {' ]2 B' J. Y' K& \
. }7 }, ]) q6 W整个画面的构成:8 h% Y* U" F% E' d+ W' [, h& S
* c9 M3 i. _( g0 o$ u左侧的“Widget Box”就是各种可以自由拖动的组件7 {, a3 S5 m3 q2 m3 P
% B- k" o6 X. H* n% f2 I中间的“MainWindow – untitled”窗体就是画布
7 P* X! t2 g( n3 n+ W
5 b2 m9 @( h) ~3 z/ {右上方的”Object Inspector”可以查看当前ui的结构
. \6 P P4 m7 {0 Z! m
2 G5 I3 N& j) y右侧中部的”Property Editor”可以设置当前选中组件的属性
1 F: f4 Y7 \: P; T8 j: r+ y+ Z# h' ]0 z. g% _- H5 C
右下方的”Resource Browser”可以添加各种素材,比如图片,背景等等
; ?: t' _7 x) {/ ?, X$ _# N$ a0 w/ d2 ^4 ~
最终生成.ui文件(实质上是XML格式的文件),可直接使用,也可以通过pyuic5工具转换成.py文件。
3 w+ x$ K9 ~ P. C
- b/ O" D4 p; _1 f$ \! r4 ]4 {2 l* QQtDisigner配置
; a4 q! x1 e7 ]8 N7 T/ O
/ R5 P! x/ `% |% q在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:- s. X0 ^, v4 b, @9 t! n
- K' k; h4 k3 j+ ^
Name: QtDisigner
, f2 y' g w) q$ g/ M/ \
0 Y2 z, Y6 t0 dProgram : D:\Program Files\Python36\Lib\site-packages\qt5_applications\Qt\bin\designer.exe # 请根据实际修改
% Z' S) M: k, H1 }
. d3 f$ {% L5 b5 U8 bWorking directory: $FileDir$0 { ]9 h' G" t l% ]
PyUIC配置
7 h3 L6 W0 n6 n; H" x+ A8 m6 B9 |9 @& X4 f7 P. C
PyUIC主要是把Qt Designer生成的.ui文件换成.py文件。
) ?6 r4 Q! w7 _( m- M" x1 N' K: ~5 B' R8 w# |' [3 |: F3 g& _
在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:- {& X7 e# P. Y* D; L
& x/ \: X+ Z6 \' e& Q" f2 u( X
Name: PyUIC4 O# I- F$ ~' _" W
" K$ l1 y( |+ _2 K% x. ^& i0 f2 pProgram : D:\Program Files\Python36\python.exe # 当前Python目录,请根据实际修改! Z+ R7 t" b, l. N
3 L- e6 p' A+ }) ^1 p
Arguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py7 e# G( B. t; l- y
7 Z7 Y' u8 ]/ i& N& E
Working directory: $FileDir$0 }6 J8 o2 ?; [" R
PyRCC配置
9 S1 `# z! {/ b" ]. \9 Q/ \, T& D G: g- Q' x. e
PyRCC主要是把编写的.qrc资源文件换成.py文件。在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
, e! _/ |! g- V; ]6 j" `( \
$ P( g9 }5 Y) e, Q% OName: PyRCC1 T p4 n D! Y. [/ v- V- H
0 ~4 u8 B4 l' s; Q
Program: D:\Program Files\Python36\pyrcc5.exe # 当前rcc工具目录,请根据实际修改
, d/ t- H5 D0 X7 H C+ L( t: ?! i8 i4 [5 w! h. t# _! E. ~
Arguments: $FileName$ -o $FileNameWithoutExtension$_rc.py
$ A' ^% ^: Q5 l6 ] I, q9 @( w2 _3 Z- I' i7 G* i: v, @, @
Working directory: $FileDir$
1 m, E$ i9 b/ V! W% JPyQt5使用示例! P& H" a$ k! |4 d+ R0 F% O* }; B
' q ]+ Z7 p3 \* Q6 A* L9 E创建一个空白的界面:. ~" k( U r+ k# C: O" v
/ h/ F2 I9 R: [7 j# ~3 Q
import sys8 p5 [* m/ z$ x& H
[2 u x6 T' n. Y, [/ \from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel0 D# o% z/ F+ N8 w4 i
5 Z9 [" a! W5 J/ ~; x3 n
app = QApplication(sys.argv)
, G5 W. O9 q, M r
P9 I2 I. }$ a1 m( C/ I- @win = QMainWindow(). l& I6 e4 J1 k+ }9 T
6 l3 `2 Z, Q" D4 l7 qwin.setGeometry(400, 400, 400, 300)
/ Q( h, W5 p/ A4 K& ]0 [' k0 o7 l) Y9 Y1 ^4 V; C' Z
win.setWindowTitle("Pyqt5 Tutorial")
( s! r* n% ]# O! f* C/ _: u/ Z% Y4 p# h% Q% _0 P5 ^
win.show()% f, y7 A. N) m2 [& q: {
4 E( T7 |" ~9 k7 }' |& [sys.exit(app.exec_())
# W: g! d& }' W# u5 m5 A
$ m9 Z9 g. O3 x3 m, u- F
' t! C( [0 }) ^/ a
5 b+ X P" O( K/ z' w5 A: w6 u其中:- }1 P" a1 _0 u) ~: k; z! l
. e1 r9 O2 Y) W7 y! i2 ^" F
Qapplication():每个GUI都必须包含一个Qapplication,argv表示获取命令行参数,如果不用获取,则可以使用[]代替。
4 L3 E1 N) N3 C [1 A+ X L A3 U' b3 g [: D/ {8 h
QMainWindow():类似一个容器(窗口)用来包含按钮、文本、输入框等widgets。arg标识可以获取命令行执行时的参数。- p( N! P2 ?" e3 O. I
; [5 E: n, l* |* t: m! x' USetGeometry是用来定义 QMainWindow() 窗口的尺寸, 语法:setGeometry(x, y, width, height ),其中x,y为屏幕上的坐标点。
$ L0 O+ B% n3 f. A/ x) P2 b3 o3 b& \$ a- H" e9 f7 Z6 t8 E
show():用来显示窗口! E! r( a6 C3 O; }& {0 f# d
- g/ Y+ S% T0 Y+ `) @exit(app.exec_()):设置窗口一直运行指导使用关闭按钮进行关闭+ U2 O% ~8 l8 E* C+ e( a
8 K. Y5 _6 N7 z$ i' R
PyQt5支持的常见Widgets有:
6 ~+ \6 [, ?6 v' o" d
9 t1 ~9 B6 Z" y. g& c. q) Y" O& Z. t8 e- P% U/ }
4 n' N5 G* r3 i从上到下,从左到右依次为:Qlabel、QcomboBox、QcheckBox、QradioButton、QpushButton、QtableWidget、QlineEdit、Qslider、QProgressBar8 n% m3 C" m( |+ o- E7 k
$ C2 i2 O, a" ~# H* F* B8 [( m对于使用Pyqt5设置文本内容,我们使用Qlabel:; x* e$ K- V" N% {1 d& l
0 Y _% } n9 I. s5 x. `6 Timport sys( d+ g }+ a( c& b4 \0 V
6 H- i- P7 ~7 T" qfrom PyQt5.QtWidgets import QApplication, QMainWindow, QLabel9 z& T+ x, d0 l2 P5 B/ B% E J x. Y u
7 _" @4 N7 i/ y; c; Y5 e$ h
app = QApplication(sys.argv)
0 E* Q) d5 j' V( R: k: M
2 s) Z5 h$ u: v( x0 _( V8 @win = QMainWindow()& @, h6 y' `2 t
6 Y7 \8 e8 u; T+ v( `, G' Awin.setGeometry(400, 400, 400, 300)# e; _) n7 U0 `; v0 n D
. J' {4 u; N5 [ q4 P; m
win.setWindowTitle("Pyqt5 Tutorial")! W U6 n# I* v; ?$ e+ |
# i* W) Y4 k1 S. a5 z* u
\# Label Text9 k# N4 @( v0 t, @7 w2 X# s, z
6 v. ?2 Z: v5 K: J9 P- V
label = QLabel(win)+ H: g/ z: a5 }6 @! O: p
, w C: ~! B3 |+ f9 B( O9 S
label.resize(200, 100)
5 m7 h" Q" x+ D0 ?+ {3 b; z! }$ r- x+ j0 d7 Y% `
label.setText("Hi this is Pyqt5")5 G! O/ r7 e6 S/ W# [( r
0 x) T( J/ P3 I" m& zlabel.move(100, 100) Z) Q' {5 ~4 L
0 j' h3 i0 c1 N0 D# V' C( Rwin.show(), r2 ^- u* i: @/ Q+ n$ N, n
- o6 v) r/ h6 l0 u) F% ^2 esys.exit(app.exec_())
9 E# \1 m1 e$ x% I% l' m9 `$ `% f: ]+ v8 }6 o0 M9 |
1 B( X( e3 j( D& @
0 @0 G, R5 I0 m5 J5 I按钮与事件:
; d4 k C3 F% {7 I8 j8 ~
# X6 D, g7 d; E( Himport sys' ]/ n3 w6 z; p$ A- Y4 `' H
+ b. A7 Q( @; e. B, g5 z
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
+ b2 F/ U7 I0 T: _( A! @0 t
# B2 X- f5 p: fdef click():2 u8 J4 y1 ]4 s5 y9 q" T3 y
( I7 Z" h, f/ N. D; j ~+ O, g5 l% x print("Hy Button is clicked!")) j) e" d& V( {* V
0 g8 W$ L. r9 O3 {9 C" ^6 | J3 ?app = QApplication(sys.argv)4 c& h8 Q0 n9 K
# q! m6 L& F5 v
win = QMainWindow()
5 ~+ W$ X' u6 V8 x" G$ ]. ^6 c& o0 W. n$ p' g9 r( b; Z8 f
win.setGeometry(400, 400, 400, 300)$ b7 t, j0 d" K4 B+ d% H
# ?' w) C4 {6 B* |1 t
win.setWindowTitle("Pyqt5 Tutorial")' R8 ?# y9 Q( p# y: L
; w' i e8 e# |+ V\# Button3 p0 u( J+ {$ Q1 Q( Y/ ^
3 F; K! j5 G0 l. _ |5 d
button = QPushButton(win)
! d9 r4 C8 C u, T; e( b" W7 _# i( X' a/ g
button.resize(200, 100)3 w/ v9 T7 v0 \1 b* ?
l3 L& G0 K e" S3 nbutton.setText("Hi! Click Me")
, o' h L! y0 x+ g( r
$ e7 ]6 }/ n* hbutton.move(100, 100)4 G9 S, N1 X3 P$ s
3 n0 ^2 p' U3 I% ?! A8 x
button.clicked.connect(click)
, P9 U- \5 u q% N% |
. R. w4 G% O. jwin.show()
% Z# c0 c& ?8 Z0 a* H# L% m9 t* ]( ^* V8 T* w0 x7 w$ f# H
sys.exit(app.exec_())
6 k$ n& A: V" y9 o3 V1 ?/ B! H5 g$ F% i) }
# D; R* y8 Q8 O: c: J
4 E5 j4 n, ^1 v
button.clicked.connect() 在按钮点击后执行特定的事件。) p9 A6 {5 @& s! f
! W- ~% s( ~1 \( {# nPyQt5实战
( E8 _! {. e( ~+ f" w' x
- l) |. X2 B1 t3 h" y8 x* f实战项目:简易的天气查询软件
: E- h8 M7 a) H5 g
+ V9 \! h$ @7 E( ^9 W4 \' k3 N; g1、使用Qt Designer设计一个界面( P# s. h, g; D. K h( Q
9 b4 ^+ _8 k' R( d6 @' {
& c' F7 B. v7 v5 I9 Q
4 ?8 o2 l+ B% ~2 K1 i用到的控件有Button, GroupBox, Label,ComboBox,TextEdit,同时定义了两个按钮queryBtn及clearBtn,分别用来查询及清空天气数据。我们需要绑定槽函数,方法如下:. |# T" [6 O1 w) ^' x R5 ~
6 p1 w$ E" }' h' b& x) M3 ~在Qt Designer右下角选择 信号/槽编辑器,点击+号新增1 E; N( F P, M
; k5 M- ? l1 ^" _1 p7 ^6 {) D* I分别选择queryBtn及clearBtn,选择信号 clicked(), 接收者 Dialog 及槽 accept(),(槽函数这里不知道如何定义,后期在代码里再进行修改). w X1 o8 z o4 N! r+ G, F) ]7 c! o+ s x
% B Q" p* `# _3 F% X7 ]* }1 s% D以上完成后保存为Weather.ui文件。4 c, h$ d9 z4 S1 t2 @- U/ e$ J3 t" A
, z% I2 C) ?; f0 o- P6 e M1 D
2、转换.ui文件为.py文件
. l, _- y5 r( Z2 |6 K- d. W- C I! l7 ]- D
PyQt5支持直接使用.ui文件:
5 _: {' f" Z) O# U3 J! L( v' a
" b/ x: A9 M8 S( R% X) B8 J$ [import sys$ j" l d( q7 _/ }8 N
* ?! D6 L) z: K T/ h1 Kfrom PyQt5 import QtWidgets, uic, n+ r5 c" i3 n1 H+ a3 g/ R
& {; U* M1 q0 f* M& \& |
app = QtWidgets.QApplication(sys.argv)
9 w% m$ ^' w' I% B* ?* d0 Q7 W0 |# r+ b9 k
window = uic.loadUi("mainwindow.ui")" {0 b/ Q% w' p8 u' \ [( L
) k7 b0 h8 Y2 w% A, g9 f, r7 |
window.show()
1 d8 W# I* I8 q5 o3 P; _% C& p5 @- d$ ?2 W% n0 L
app.exec()1 b+ P& u8 n5 a% x; d9 z
但是为了更好的自定义及修改上面的槽函数,可以使用External Tools – PyUIC,即可生成Weather.py,实际运行命令如下:
3 v% x5 ^/ R& }) e$ W' t6 t8 c& L; q- N. ~
D:\Program Files\Python36\python.exe -m PyQt5.uic.pyuic Weather.ui -o Weather.py
% x$ d6 ~3 N" q7 a: j" |& v m( L+ e+ ~其中,我们需要把两个按钮绑定的槽函数:2 y! _, p$ O( `# |7 r7 p, _* p' ]
' u3 d" ^9 X; M' d7 }# |) T
\# self.queryBtn.clicked.connect(Dialog.accept)
6 J) M% L) s, P+ ]4 t. q
5 K& p9 @& ]' \9 \, B. A\# self.clearBtn.clicked.connect(Dialog.accept)
) i+ U- B3 a D/ b* _. f' c9 k3 G6 H3 r$ o9 F% F
\# 修改为:
8 a1 U7 a, c; j2 R' s( L3 K% c+ _; d7 z2 B- |$ ~
self.queryBtn.clicked.connect(Dialog.queryWeather)7 w& R: X" @" Y" E
1 u4 J ?1 k1 c h t
self.clearBtn.clicked.connect(Dialog.clearText)) G9 j3 I/ [0 a0 z& f1 \
最终的Weather.py内容如下:
9 L. U. M: m: k0 N
: P% z" ]. u2 N( R2 n5 U9 A" q! ~\# -*- coding: utf-8 -*-2 Z& a ^5 O4 I; W4 N4 z, \; x
5 T% }; \! n- r* Q9 G* G$ [\# Form implementation generated from reading ui file 'Weather.ui'5 U7 }4 @0 C* ~ Z/ ?2 z
" i! ^7 P7 o* w
\#
3 w P0 {3 ~! L3 E$ N1 E8 r
3 F% T4 Q7 z/ t O0 M\# Created by: PyQt5 UI code generator 5.15.4
+ X5 b, W; i/ g3 l0 G0 Z" t. A& d- [ K+ a& t1 c
\#+ ~- [, k. h" q3 q: v, B1 z
2 F" J% X: B' w3 p8 B6 H7 f$ z
\# WARNING: Any manual changes made to this file will be lost when pyuic5 is4 [) { t, Q- r9 d9 x0 t: p
4 U: l; A0 b5 h8 a1 ~3 k
\# run again. Do not edit this file unless you know what you are doing.
/ e: K$ p( i! f1 F) U! J7 H
% p, ] `! z' tfrom PyQt5 import QtCore, QtGui, QtWidgets* n" M: u4 Q1 V, |
9 m" M+ P. @& J1 ^ dclass Ui_Dialog(object):' r6 d M1 Y: N+ T( a0 F; ]& N
3 U4 \6 ]4 ~9 m! r% d2 k
def setupUi(self, Dialog):
9 z D1 T# i! k, E- o& o# x' e" D- n- H; t
Dialog.setObjectName("Dialog")0 J9 Y+ N( a! u4 W) s4 O9 E
6 U T, b B$ B7 ^" X% `" V Dialog.resize(600, 600)
( b" {3 ]: u$ D4 k' Q" p" z
( m7 Y( V$ p' `3 G) K. T self.groupBox = QtWidgets.QGroupBox(Dialog)
' _" R! z4 ]/ j! I ^* K: R6 u a0 O7 B8 P$ u
self.groupBox.setGeometry(QtCore.QRect(30, 20, 551, 511))1 Q# t+ c* h$ t8 a" G
4 I7 P; R C3 p" h
self.groupBox.setObjectName("groupBox") s1 b! ]* V0 A: }
$ C8 n, w. r; `. c self.label_2 = QtWidgets.QLabel(self.groupBox)0 b! K( g: u) C/ m- r, N/ g
, G* x8 B& N) }3 N* l self.label_2.setGeometry(QtCore.QRect(20, 30, 31, 16))
! I' D% i6 o7 ^) L3 a( }6 P" C1 z l- _& T. Z/ U7 O
self.label_2.setObjectName("label_2")+ k; l- T, P! M$ v- C: c7 x
0 @) s" T1 a" \5 \" a$ B self.comboBox = QtWidgets.QComboBox(self.groupBox)
( S1 H! h8 q2 ]) d0 H( R) V4 o! M) M% Y; }
self.comboBox.setGeometry(QtCore.QRect(70, 30, 87, 22))
* p5 F* L" F: y# y& Y9 \ N; K* T2 w$ ~: {6 M. k
self.comboBox.setObjectName("comboBox")
0 O9 w* ]/ q: W' e: h9 {( u
# e1 Z6 \; L- R8 z self.comboBox.addItem("")
$ O7 d; Q8 k) {8 o& |3 t p; d; F4 j2 ~
self.comboBox.addItem(""). d$ m0 R+ l% N+ s; O, Y* v
! m! v3 r* @- F
self.comboBox.addItem("")
' k$ F: v* p$ U$ p! M1 y$ n' P5 m* f6 c, K) y" C5 Y" |5 Y
self.textEdit = QtWidgets.QTextEdit(self.groupBox)) B- {" [. U! P0 h
1 a- |# t5 k7 M4 \0 a4 H
self.textEdit.setGeometry(QtCore.QRect(20, 70, 491, 411))
1 ?3 c! [+ s6 v- Y! D) M1 ?3 T0 g2 R- W
self.textEdit.setObjectName("textEdit")
$ O$ g7 c+ f8 M [7 Y9 D" u
) |' K6 M: b% n' W* Q0 `6 O self.queryBtn = QtWidgets.QPushButton(Dialog)$ |, X; t; f3 u2 f, ~0 o- a" F) _+ x
- ^; |! B0 k0 v# W& O self.queryBtn.setGeometry(QtCore.QRect(490, 560, 93, 28))/ _' I) U/ Y2 l! l9 }- u/ J# k
+ R! ^0 _. T9 a. x x5 p, [9 @ self.queryBtn.setObjectName("queryBtn")
% w7 _9 N6 x8 _. Z* O4 x1 U6 I) h$ W& m; f: d) e
self.clearBtn = QtWidgets.QPushButton(Dialog)
# ]- J- d2 l9 U2 G. l9 u5 R$ U6 n# k0 V. i! \
self.clearBtn.setGeometry(QtCore.QRect(30, 560, 93, 28))& J: C: ?- Y3 [: v. C+ }: k. K6 y
. l m- {4 v$ b1 ]
self.clearBtn.setObjectName("clearBtn")' }+ ?2 Q% K4 p5 a* _) z
* h$ P( x5 ^& n3 a self.retranslateUi(Dialog)# L. P5 k5 P) ~( `. Y
) _5 V; f, |; Y: W/ n8 h
self.clearBtn.clicked.connect(Dialog.clearText). G4 I. C6 c8 C% f% R% I4 A
+ |! x' G' g2 L+ A
self.queryBtn.clicked.connect(Dialog.queryWeather)! g Q/ s: c, f6 ?# ~& e+ n
8 K; M/ G- l# d8 B! b+ O QtCore.QMetaObject.connectSlotsByName(Dialog)7 s, s/ i6 r" V& H$ c* E
& W: |+ \! Y" ^7 B& Y, P: u# }4 S" ] def retranslateUi(self, Dialog):
3 ?5 y% e! C n( U
& ~9 k% Z% x! f) A, r, J8 L _translate = QtCore.QCoreApplication.translate* I) t& J" r& z$ d4 W
4 i( X9 b0 M4 {- U5 Z Dialog.setWindowTitle(_translate("Dialog", "Dialog"))& ]( W- E, @( E! [/ K/ Q: I5 ~& j
- z% P$ ?& H. m7 B: z+ b1 T self.groupBox.setTitle(_translate("Dialog", "城市天气预报"))9 q9 t" S7 G) ^4 ~+ s$ o
* a9 }+ h7 D! K v self.label_2.setText(_translate("Dialog", "城市"))
|/ i8 u) Q# t8 ]! n; A( T2 Y8 }5 S# X* p- j6 A
self.comboBox.setItemText(0, _translate("Dialog", "北京"))$ D) l" b8 v- e/ K( p+ }
' t- F/ N$ H2 t- P0 F
self.comboBox.setItemText(1, _translate("Dialog", "苏州")); W; H5 j& D- d( h5 i
( j/ A% p, h, R$ q, D self.comboBox.setItemText(2, _translate("Dialog", "上海"))
7 x2 p. ]3 y' \! j8 f
5 F8 m7 Y7 Q, E! B9 s4 ^ self.queryBtn.setText(_translate("Dialog", "查询"))6 d2 K; s$ V6 z+ z1 D
4 Z4 u+ d" N6 B/ |9 @2 b, I
self.clearBtn.setText(_translate("Dialog", "清空"))
- c, }, A; J' R- {" }8 ^% p0 P' g# }) C n% @( i0 m6 R. Z1 T
3、调用MainDialog7 E( @$ X3 D/ f& D! J5 {. V9 c
8 I5 F" h+ Y) } \在MainDialog中调用界面类Ui_Dialog,然后在其中中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。新增demo.py文件, 在MainDialog类中定义了两个槽函数queryWeather()和clearText(),以便在界面文件Weather.ui中定义的两个按钮(queryBtn 和clearBtn) 触发clicked 信号与这两个槽函数进行绑定。7 d! ^' p' {, B' x
- R: ?1 z( a/ h) R2 i/ W2 N完整代码如下:
# u/ ?4 T8 P6 o2 j* v0 [' ~$ c+ u9 A1 Z; k1 ]) L6 i
import sys/ B5 M+ Z$ I- A
5 X6 T7 N. e6 p9 w+ c1 fimport Weather0 u! q( f& S+ M7 l
* w0 l9 Z$ @5 q5 Y6 [. `from PyQt5.QtWidgets import QApplication, QDialog; v' G! [9 Q1 T: [
) z1 y4 M3 }; y& himport requests- ?+ m. {% m8 r6 S5 m
9 C7 P8 G. U1 iclass MainDialog(QDialog):/ T0 N. T$ V- ^4 K/ ?4 F k, L- A- k
0 ^2 G9 {# e9 M2 z
def __init__(self, parent=None):
" _( \6 D7 n1 m" z5 U" p, N! Y) k! R" Y7 G2 `! {. o4 ?% M
super(QDialog, self).__init__(parent)% L9 p/ }7 E! `( t! M/ L
4 S8 U8 S% u6 c/ O; p9 h: m
self.ui = Weather.Ui_Dialog()
+ g* {4 {* C* `7 ?
3 a( g7 d( u9 g+ P F0 L& Q! E self.ui.setupUi(self)) L9 U! j8 N2 T! ~
" K) h1 v- G T6 T" P
def queryWeather(self):: o$ G+ l- y! l4 X5 j
6 p9 c1 {4 ^6 C8 `9 o3 E
cityName = self.ui.comboBox.currentText()
+ o2 A( J* A g% R7 u" l1 A% h, K1 ~( z# V
cityCode = self.getCode(cityName)0 r8 {% S) Z& {4 T
9 X2 z% g9 d ?- _5 o
r = requests.get(" T c" Y3 g" D3 Z3 i. X
& m7 I9 \2 b9 R1 A) B \" Q
"https://restapi.amap.com/v3/weather/weatherInfo?key=f4fd5b287b6d7d51a3c60fee24e42002&city={}".format(
# I9 P) @1 w `7 Y' b+ k$ o! ?. C) U; u6 o2 F* }
cityCode))
1 Y6 [- V5 p! |8 u' d
" W/ l0 G- p4 ?+ W& g9 x if r.status_code == 200:
, M, I A( f7 P. C3 K/ v& i: Y, y3 I, z2 E4 m O- k, Q# b o1 O
data = r.json()['lives'][0]0 @/ `2 H9 f* @- M
. R* x i" k9 H! x \6 z weatherMsg = '城市:{}\n天气:{}\n温度:{}\n风向:{}\n风力:{}\n湿度:{}\n发布时间:{}\n'.format(
( z/ i; P; B! i" T
0 I" c" M5 s* n data['city'], J$ i9 G+ q+ Z
" z, [# W- X! P, E5 d L: L8 e
data['weather'],6 O# @& P8 B+ _5 @6 h
# p$ W/ x m! J% y
data['temperature'],) }$ @5 [. S, C0 }+ N+ R) |" x
9 u% q# K2 j$ d0 n" I
data['winddirection'],1 _' y& y& Y4 P2 g$ J, N/ I
' ^$ z' r0 t g* P8 S" g
data['windpower'],
$ a! `5 @ i4 H& q- Y" @
% Z7 X/ e- O) U3 [( P+ V( B data['humidity'], Y, ^/ g2 W& n1 ~
; H) B2 X" V, x4 r/ ~$ d# G5 }
data['reporttime'],; M: w; n+ V* l# q5 ?
# H4 Z9 L! E' M% k: b# P3 `$ E
)% Y5 Z. l1 a9 d6 k: i0 a
2 z" M- T8 {) _$ {+ t
else:! G& Y' N, H/ u. A, z: g6 J
7 r, T. A, ~' A; F ]$ x* y
weatherMsg = '天气查询失败,请稍后再试!'9 U* H, F9 i! k1 _: E" R
- m1 N8 _+ q! ~ self.ui.textEdit.setText(weatherMsg)
( K6 w' C. N: y3 a0 `4 _% h& a9 t
1 H# j$ p! M# g* M def getCode(self, cityName):. ^2 o/ @( y) X2 l/ a+ Y' x! T% u
4 C0 {# T7 ^( N; ?' {: x0 ~. i
cityDict = {"北京": "110000",
8 x. A! s& }- B' ]& B( P" m p
. L' l1 t( S0 H9 H( ^5 M9 w "苏州": "320500",5 l( S( X, @+ e' w1 b
# ?: u+ k/ Z" ^+ f
"上海": "310000"}
: }% A) {( Q0 p8 C) F3 P8 [2 z3 E: n
**return** cityDict.get(cityName, '101010100')& \& j# B! P, }- e- L
, v g8 ~( ]5 }( x5 ]
def clearText(self):6 X1 t& g) p. m v. p9 Y7 p
8 T# D. _, r3 ~! u
self.ui.textEdit.clear()
# d; u! T# s+ L
* q( P$ i5 R' v* ^' bif __name__ == '__main__':
( ~6 V" s5 ?2 H( V3 \7 P& X& K. j( ^/ M
myapp = QApplication(sys.argv)
8 s9 g" c; g1 {, C' e. O) P2 k7 V% u x9 p( }* V
myDlg = MainDialog()0 s) M& D: J7 _" j2 ]7 X, l
7 b& Q! @, `" g4 z0 f1 n
myDlg.show()) I/ _. I, L# J! b$ j/ L# ~2 D A
) v. `6 V% R1 c0 t& t
sys.exit(myapp.exec_())
" |& q( I4 x$ |$ `
' {6 h" H( j% m8 S7 N, N运行demo.py并执行查询后的效果:
M2 q5 @" `6 `4 C9 W' s$ `2 @+ @3 ^$ d5 I5 T w& u+ H6 f: b( j
, C1 N% n& }, v s
" |& t0 v* M, m) h+ M) T
4、将代码打包成exe文件
6 O% N5 W. M* F; S: Z* a5 J- S
5 Z: Z7 |! H. B: A' \! X将.py文件打包成可执行的exe在Python中称为freezing,常用的工具有:PyInstaller, py2exe, cx_Freeze, bbfreze, py2app等。功能对比:
# I' ^. W* C; E. Q+ D4 Y
' A, q2 m7 i5 I% I* F* Y- J4 u& a) T; D) ~* `0 l
0 Q% S7 e* c6 @+ H( J# E! L: p s2 npy2exe:软件更新已经不活跃,因此也就略过。9 T" ^2 B# l. Q9 d/ Q
5 |, f4 `; W& Q2 W& Hpyinstaller:明确支持win8、win10、理论上支持win7,,支持apple Macos, linux。pyinsaller可以打包成文件夹形式内含exe入口执行文件的形式,也可以是一个单独的exe文件。
0 M; B/ B) _- j( V" Q2 V. b6 g9 v) J S* t: r1 V; N! W
fbs:基于PyInstaller,使用起来更加方便
. p z' F( r4 ?- G8 V q
5 u9 p# ^- W0 x这里选择了fbs来打包。fbs的安装方法:
/ m$ ]6 P, m' ?2 \: G5 y; x
1 O. a! k) i. z* \pip install fbs
' ^( q1 f) ]1 i; O" S使用方法,在命令行中输入:( Z" w6 ^; H- r5 r6 S
$ Q& ~% f- b/ L6 _# J. _& y! Mfbs startproject$ }6 d+ ^( Z- y3 w& f
执行完成后需要输入一些APP的名称等。完成后会生成如下目录:
$ }9 w! a/ f9 G5 L5 s8 }% t. I7 B% e9 D
8 C4 W" B# M7 ]& K- R( k$ o+ E) j' R g( t+ c8 G4 C! @7 t
将刚才编写的PyQt5的代码(demo.py和Weather.py)拖到src/main/python文件夹下,删除原有的main.py,并将demo.py修改为main.py。然后打开 main.py,在文件头部添加如下代码:/ v, ?, S9 K2 {2 E& L0 v
, u) ?2 n% R' N, T( k- g
from fbs_runtime.application_context.PyQt5 import ApplicationContext
2 E; s4 T' x" H+ h7 K# Q$ j```
6 ^+ [# W, {1 S+ Y9 O完成后执行:
\( a9 Y# V8 i% Z" v0 N```0 S/ C1 f+ A& U( Z
fbs freeze7 d* c7 \1 ^$ M1 b
```) D+ P, m: N4 e% x: m& b
即可实现打包。生成的exe可执行文件在\target\MyApp文件下。
) @! _% i- c6 k+ i8 c- R, c6 m/ {! c( E! r
————————————————
0 N3 l* Z, m2 H( C( i" d* n版权声明:本文为CSDN博主「宋宋讲编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
8 o3 c0 V% X# f: [( t+ b原文链接:https://blog.csdn.net/qiqi1220/article/details/126289667
J+ i( G- a4 v. b5 w
' t2 `7 z- }. q9 X1 j5 }$ X N. e% j V. d* E2 Q
& I+ A- a& [( j* M" Y/ K+ m* v |
zan
|