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