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