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