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