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