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