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