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