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