QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2222|回复: 0
打印 上一主题 下一主题

超全!Python图形界面框架PyQt5使用指南!

[复制链接]
字体大小: 正常 放大
杨利霞        

5273

主题

82

听众

17万

积分

  • TA的每日心情
    开心
    2021-8-11 17:59
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    网络挑战赛参赛者

    网络挑战赛参赛者

    自我介绍
    本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。

    群组2018美赛大象算法课程

    群组2018美赛护航培训课程

    群组2019年 数学中国站长建

    群组2019年数据分析师课程

    群组2018年大象老师国赛优

    跳转到指定楼层
    1#
    发表于 2022-9-15 12:26 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    超全!Python图形界面框架PyQt5使用指南!& C0 Q9 b! ^; ]( B' s" W
    : k6 s! j' ~% l. D- U
    使用Python开发图形界面的软件其实并不多,相对于GUI界面,可能Web方式的应用更受人欢迎。但对于像我一样对其他编程语言比如C#或WPF并不熟悉的人来说,未必不是一个好的工具。
      O0 O' }, @. {. c" h3 i  N! \& p" R# w; F6 S
    常见GUI框架
    / l$ I7 |: n2 ?. d5 `3 N* V% t* }6 \' h) Z: z; e- G
    PyQt5:Qt是一个跨平台的 C++图形用户界面库。QT一度被诺基亚拥,后出售给芬兰的软件公司Digia Oyj。PyQt5是基于Digia公司Qt5的Python接口,由一组Python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。# \1 Z0 A, r& `1 ?) }
    ( p- P0 @# e, d8 h
    Pyside6:Pyside是QT公司官方提供的Python包,上一版本为Pyside2,对应的是QT5,最新版命名规则进行了调整,更改为Pyside6,对应的是QT6版本。由于官方出品的比较看好,缺点是发布比较晚,网上的资料没有PyQt5多。5 Z" H$ Z% }& y: r' ?

    ( n8 n8 T! s7 eTkinter:Python内置的GUI框架,使用TCL实现,Python中内嵌了TCL解释器,使用它的时候不用安装额外的扩展包,直接import,跨平台。不足之处在于UI布局全靠代码实现,只有15种常用部件,显示效果简陋。. `9 r0 v, V2 @5 v4 P7 ?& C+ l7 k
    , `" d. W5 ~- d& S5 ~" g/ q
    PySimpleGUI:PySimpleGUI 是 Tkinter 一层包装。使用 PySimpleGUI 实现自定义 GUI 所需的代码量要比使用 Tkinter 直接编写相同的 GUI 要少得多。9 q8 Z9 t0 R5 Y& g; V

    ( c8 q8 x1 l7 ?WxPython:wxPython是Python语言对流行的wxWidgets跨平台GUI工具库的绑定。用得比较广泛,跨平台,C++编写,文档少,用户可能就需要根据编程内容对不同平台中的GUI代码做一些调整。遇到问题不好解决,代码布局控件,不直观。
    5 n8 `: O+ b, K. W$ i# U7 W, G/ U+ c# J2 d8 Q; W' C1 I
    Wax:基于wxPython ,为克服wxPython的问题而制作的一个包。
    * _2 A! E& Z# ]3 i: E' J, n
    9 |) b- W# ^2 U0 p6 s5 k$ W2 u& ?0 CKivy:主要针对多点触控程序,智能手机平板等,也可以在没有触屏功能的系统上,全平台支持(Windows, Linux, Mac OS X, Android and iOS.)使用Python和cython编写,中文支持差,需要自己下载中文库并且制定路径。, n! P, J1 A* j7 T7 U4 S7 K

    9 W& \% Z9 i- L0 TBeeWare:Write once. Deploy everywhere.需要与Kivy配合使用。* L2 h" `: L4 }; A
    $ h: p) F3 r* Z
    Toga:一个使用Python开发原生APP的GUI工具包。Toga由一个具有共享接口的基础组件库组成,以简化与平台无关的GUI开发。Toga适用于Mac OS、Windows、Linux(GTK)以及Android和iOS等移动平台。. L1 W+ G( c. f/ e/ p

    / b3 x' p! h% p  v! S. @( TEel:一个轻量的 Python 库,用于制作简单的类似于 Electron(但是比它更轻量) 的离线 HTML/JS GUI 应用程序,并具有对 Python 功能(capabilities)和库的完全访问权限。
    " U+ r. y: y& O$ h
    4 ], ^$ v% F( Y: Y) C) v- qFlexx:一个纯 Python 工具包,用来创建图形化界面应用程序。其使用 Web 技术进行界面的渲染。你可以用 Flexx 来创建桌面应用,同时也可以导出一个应用到独立的 HTML 文档。因为使用纯 Python 开发,所以 Flexx 是跨平台的。只需要有 Python 和浏览器就可以运行。- }( y0 \" U5 p; E) T! l  p
    . }* h8 k, V' J( F( ~* m& \
    pywebview是围绕 webview 组件的轻量型跨平台包装器(wrapper),它允许在其自己的本机 GUI 窗口中显示 HTML 内容。它使您可以在桌面应用程序中使用 Web 技术,同时尽最大可能隐藏使用浏览器构建GUI的事实。2 O- h8 r/ I( P: _

    9 n. f% }7 G1 Renaml:一种能够让你用最小的努力就可以实现高质量GUI界面的的Python框架,也是一种独特的编程语言。enaml将声明性语言与基于约束的布局系统结合在一起,使用户可以轻松地定义灵活布局的UI。enaml应用程序可以在任何支持Python和Qt的平台上运行。0 i1 X) c! d1 F
    % S5 m8 y  n" ^( i1 k; }- C
    个人想法:太多学不完,先学PyQt5,原因是资料多,学有余力再学pyside6,最后看下PySimpleGUI,看能否解决一些简单问题。
    4 n3 L2 Y$ B4 A
    9 d$ r) z/ l8 L: ^* a% P, ]: tPyQt5简介$ y$ i; X- V9 ]' Z3 @! F! @; H
    5 `8 s) {( A* y! w4 G5 S
    PyQt是Qt框架的Python语言实现,由Riverbank Computing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件,因此PyQt的API接口与Qt的API接口很接近,但PyQt不再使用QMake系统和Q_OBJECT宏。
    . y3 S/ @+ {0 z! F- q8 d
    0 ?( ]! k5 H9 c. {5 j# n2 oPyQt5提供GPL版和商业版证书,自由开发者可以使用免费的GPL许可,如果需要将PyQt用于商业应用,则必须购买商业许可。
    0 b' u( K# Q% k! p, _$ o7 A9 u8 ~0 v$ ?" `, k9 K
    PyQt5特性如下:; f: ]2 {7 V: `& U- B: d2 j8 b
    * g9 j% b+ y3 t  Q$ \  b
    基于高性能的Qt的GUI控件集。0 c" V* o+ B* M5 u5 v; x
    , v5 q1 l3 l$ h
    能够跨平台运行在Linux、Window和Mac OS系统上。
    8 b0 n1 l; p! @  H0 R, ^) E4 E! K
    使用信号槽机制进行通信。
    1 y3 {0 g5 K" y1 q5 g$ l' Y/ z, L% j: Q' n
    对Qt库进行完全封装。
    3 C) p( J6 Z( u% ]7 J) n6 Z
    # ~' z8 n! x7 F可以使用成熟的IDE进行界面设计,并自动生成可执行的Python代码。
    9 k* v% C* }; G6 ]4 A* c! \4 |' T# o( O: y0 W2 j) K
    提供一整套种类齐全的窗口控件。) R" K7 \4 T8 j* G- B- _
    2 v% M( J' c# ~, a8 I  E
    PyQt5是由一系列Python模块组成,有超过620个类,6000个函数和方法,主要模块如下:" u$ n( F# G' X/ s; b/ n) u0 _7 N

    + [4 q& w. {% J8 `9 OQtCore:包含了核心的非 GUI 的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime 类文件、进程与线程一起使用。, i, z; b; V0 j* `# E
    9 v1 m' d7 T7 m9 t' k% ?: @8 ~, `0 ~
    QtGui:包含了窗口系统、事件处理、2D 图像、基本绘画、字体和文字类。: `, I: ^/ D  r! a( i" ~

    # x. j# |* x$ u$ \1 hQtWidgets:包含了一系列创建桌面应用的 UI 元素。
    9 }4 I4 c! f/ b: ~6 n3 u, P# \0 g! _9 q' @2 V; ^- B; o
    QtMultimedia:包含了处理多媒体的内容和调用摄像头 API 的类。5 i% }) w# X+ m' }

    ' l7 W. U4 A5 l+ J  R7 GQtBluetooth:包含了查找和连接蓝牙的类。
    $ Y2 G2 _* g! T$ n  v7 S, s+ V) e; _$ P* k3 z# l  L# }
    QtNetwork:包含了网络编程的类,这些工具能让 TCP/IP 和 UDP 开发变得更加方便和可靠。" `- }% d; m6 ?8 e7 X0 |: j+ S
    / b# S* M1 G5 x% E5 V
    QtPositioning:包含了定位的类,可以使用卫星、WiFi 甚至文本。
    3 `- N) L2 T. ~- `; i# M1 O7 f  Z9 n* R
    Enginio:包含了通过客户端进入和管理 Qt Cloud 的类。. s% y! w1 t! f3 w. G& O

    , e* [4 A* S# y4 rQtWebSockets:包含了 WebSocket 协议的类。5 P/ _  J1 {* O/ m  S: A6 s0 U

    3 i6 u  H2 D' M: m" WQtWebKit:包含了一个基 WebKit2 的 web 浏览器。
    . b2 [8 j+ F0 o7 s3 }6 `4 J
    0 X+ U" D) L2 B; F# EQtWebKitWidgets:包含了基于 QtWidgets 的 WebKit1 的类。- @* c$ ~% \& ]6 ]6 l, Q  q) z" k

    8 G! Y' Q8 B( F2 Z: R9 oQtXml:包含了处理 xml 的类,提供了 SAX 和 DOM API 的工具。. W% h5 V( Z% Y
    4 n) k. w! H. X/ x! T- T! x
    QtSvg:提供了显示 SVG 内容的类,Scalable Vector Graphics (SVG) 是一种是一种基于可扩展标记语言 (XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。& G. L' }1 u4 [8 ?/ L

    ! J$ z$ ?% ?* @1 E# J. |QtSql:提供了处理数据库的工具。
    ; k8 U% X+ k7 [+ i
    4 ]: k/ [8 |/ K+ [0 H) VQtTest:提供了测试 PyQt5 应用的工具。+ M) z# u/ N; ?5 h# D" K- G

    . z6 b, ~# b  {0 ^* ZPyQt5的安装
    9 o7 {1 p8 u) t4 d; q, r6 Q) ^' m/ {# T( G
    由于后期要使用fbs进行打包,fbs对Python 3.7以后的版本可能存在兼容问题,所以我选择了Python 3.6.8进行了整个环境的搭建。主要内容为:Python + PyCharm + PyQt5
      d% d! \2 g( y  B+ L& b# {: q4 Q0 D7 @0 M) U
    安装PyQt5' V2 i' c  O# f: L
    # A- B5 q: M, y/ r8 k7 U% C
    pip install pyqt5) K& v+ g6 o. r7 E" w/ J( H8 F1 S3 X

    , Q# }7 L- s+ ]6 Y  upip install pyqt5-tools& j" g+ U- e, E. Y5 e" Q
    其中pyqt5-tools为Qt Designer拖拽式的界面设计工具。安装过程中可能会报如下错误:
    3 g9 k+ t! |0 ~8 z5 z& I
    - X+ G# {, F+ N2 uqt5-tools 5.15.2.1.2 has requirement click~=7.0, but you'll have click 8.0.1 which is incompatible.
    / Z* d3 o* H. K7 C+ Z; T解决方案:
    1 j5 D% b+ N) ?: G3 M4 f
    6 v: ?" }* S" {: j  [; Mpip install click~=7.0& q1 W) `/ Y/ x2 c
    Qt Designer的配置
    ; ?( R4 x0 V4 Q/ m2 H  y9 R/ }$ M3 o8 S/ X) y
    Qt Designer 是通过拖拽的方式放置控件,并实时查看控件效果进行快速UI设计。3 r4 |" U4 U) x' f* g' H. `0 |
    $ z1 _) `" B4 Y+ |' P( u7 H- c

    9 t+ Q! @1 X/ x( u$ g" Y' ~5 f" e3 B7 A' W3 k
    整个画面的构成:
    , R) |( e# |3 P# S1 ~/ V( ~$ j: D) B6 Z. f! \. U3 ^
    左侧的“Widget Box”就是各种可以自由拖动的组件
    / C6 Z, Y0 k' [7 a* r) A- g# x2 i1 A; E7 p* D4 `  X- Q
    中间的“MainWindow – untitled”窗体就是画布
    9 [. A9 N  n& K. p$ m- u: R- x# o) S* M8 \/ W
    右上方的”Object Inspector”可以查看当前ui的结构) A2 }6 X7 O: W/ m7 S6 }& H& o
    $ N) d2 z6 k/ G4 o5 X+ O
    右侧中部的”Property Editor”可以设置当前选中组件的属性
    + ]% c$ I1 S1 M* Y& E6 @# O- I
    ( |5 O5 [5 o" w2 G4 f右下方的”Resource Browser”可以添加各种素材,比如图片,背景等等# [* o2 e+ l, c# [
    : a1 c& I) c1 r8 l9 M$ E
    最终生成.ui文件(实质上是XML格式的文件),可直接使用,也可以通过pyuic5工具转换成.py文件。- ~; g5 k5 P, ~. i8 O) c2 S

    ( t" |4 n! K; ?- J3 X/ M9 pQtDisigner配置, ]( G2 S1 U0 M

    3 ^: o8 A) e* c) n; n9 l4 T" g. Q, g在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    1 u5 t1 V' Q9 h3 Z( `( B4 k; ^, {$ U' U+ H% ]0 ?% d
    Name: QtDisigner
    9 y+ g! c8 f1 I) Y4 H: x
    % E8 S2 j2 Z4 a$ E2 J; o- DProgram : D:\Program Files\Python36\Lib\site-packages\qt5_applications\Qt\bin\designer.exe # 请根据实际修改; U  E+ X8 ^& f9 Q2 G

    3 v) S" N0 w- CWorking directory: $FileDir$
    " v( Z4 X' Z3 @PyUIC配置
    3 }5 h, {1 I2 ]* \3 P. s
    & d# p( U) N" q$ \* wPyUIC主要是把Qt Designer生成的.ui文件换成.py文件。5 p) {9 d. F$ l; N
    * E& K  K" t& k+ }9 {# Q/ Y6 Z
    在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:8 Q1 W7 J5 H& v6 \3 f2 E8 z
    3 e7 T1 J, d* B+ v
    Name: PyUIC# h: C& b' q2 u2 \2 e. l

      G; A3 [% w# j5 P( X: H" L' t* b+ ?Program : D:\Program Files\Python36\python.exe # 当前Python目录,请根据实际修改
    0 F- Q2 Z" L& Z/ w) V/ g. P' F. x, R) I4 C4 |8 I
    Arguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py% A" Z9 I& i7 ^0 y% ?
    3 r) ~8 o- Z+ J! R) x: d
    Working directory: $FileDir$
    ; |/ Y2 `) t' [PyRCC配置+ B8 c' |3 A6 A2 M1 ]; P1 G
    " e  o% b3 [  ^9 _
    PyRCC主要是把编写的.qrc资源文件换成.py文件。在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:! b+ c' `! F! w0 {& O6 _( i( L# o3 j

    % ^0 u5 P$ `5 H2 c! S# m# xName: PyRCC
    7 E) C2 p  N$ a. J1 i8 l& H3 O6 F  Q3 U  i
    Program: D:\Program Files\Python36\pyrcc5.exe # 当前rcc工具目录,请根据实际修改* r1 c: i+ x5 d2 N
    1 m( G% |2 u0 d2 J1 _
    Arguments: $FileName$ -o $FileNameWithoutExtension$_rc.py/ |6 w1 H1 ?3 z5 y

    / M- A; j3 {  X( sWorking directory: $FileDir$& q+ |; J7 s; N0 l6 M
    PyQt5使用示例
    1 O7 p5 e7 A5 r
    6 f: h9 i# R; }/ l' f& g创建一个空白的界面:8 {* c# y- y7 o9 a9 F3 ~$ {4 Y8 \

    : Y( v5 ]- `" d' Z& _4 U3 h. J; ~import sys: j* n! S3 G  l: _
    & u( o; u  ?' [5 [3 ~9 a  G- I
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel; P* M7 u$ d7 A) b& h* b" [  ~

    2 b( A" Z3 N# A$ d' @app = QApplication(sys.argv)
    ( f5 _3 P* N- I3 C$ y; l
    $ ]: g# T, d! m0 J4 n, u2 qwin = QMainWindow()
    - G! m0 y. l& B) {# H
    " {: K% ~! u# t& i) H/ x9 _  Bwin.setGeometry(400, 400, 400, 300)
    # }6 p! w( Z* A2 Q- J+ s9 C' |3 g. V4 e
    win.setWindowTitle("Pyqt5 Tutorial")- }$ k; i4 E: m$ [. Y
    # E2 }$ [7 t- e7 z
    win.show()9 G' \% w" W9 O7 B8 |. j

    6 V! T  S- |! l- d8 _. |8 esys.exit(app.exec_())
    ! y# X4 Z9 L2 r2 I, l5 K' w9 C# j/ g) _: }

    1 R5 E; D6 @. \4 @9 c6 v
    2 v$ H) p9 G1 h) m) A  }/ V其中:
    ' q3 G2 q! P  ]0 Q% g) Y- Q
    8 f  r# V7 N6 L5 k, L; G. dQapplication():每个GUI都必须包含一个Qapplication,argv表示获取命令行参数,如果不用获取,则可以使用[]代替。
    ( j4 O$ ^& M' Y4 \4 g7 ^+ B" i
    " k7 n9 Q: z8 `) AQMainWindow():类似一个容器(窗口)用来包含按钮、文本、输入框等widgets。arg标识可以获取命令行执行时的参数。
    % [% x2 v$ T7 V5 T
      H" j( K, }4 r* M, E' S% m5 sSetGeometry是用来定义 QMainWindow() 窗口的尺寸, 语法:setGeometry(x, y, width, height ),其中x,y为屏幕上的坐标点。
    8 e2 R" A% |% V- |. U. H" q1 h! Z) p7 o8 B7 M; f- v' D2 ]2 F
    show():用来显示窗口
    9 ~( L7 s8 J  U/ o
    8 g+ q9 e' C$ l4 a3 v& Z: s2 ~exit(app.exec_()):设置窗口一直运行指导使用关闭按钮进行关闭6 s7 s0 B$ j& a! J% B' {+ H& r
    7 v8 s- W" f# h$ ^$ Q6 Z2 i8 M
    PyQt5支持的常见Widgets有:: F- A2 K2 ^" {/ A: J3 `" \7 s
    0 b; o3 W4 _6 D4 @1 `4 k
    $ l+ r9 m4 l  n% g

    & b+ S+ Y, N7 g& j2 v从上到下,从左到右依次为:Qlabel、QcomboBox、QcheckBox、QradioButton、QpushButton、QtableWidget、QlineEdit、Qslider、QProgressBar6 j8 @/ q( {) \  X4 |
    , V; u0 E; u; P
    对于使用Pyqt5设置文本内容,我们使用Qlabel:
    & W6 ^7 c. G: m4 @2 u
    4 u3 o7 r! n% o2 z4 ]  w& K, g- fimport sys& U) ^& r: b; g/ `4 }

    4 f* n1 [1 ~% kfrom PyQt5.QtWidgets import QApplication, QMainWindow, QLabel" b, \. }, Y& v5 j+ @' e
    , P8 X" s+ g9 u& N' f
    app = QApplication(sys.argv)3 ^% q7 _4 z$ w0 F- q4 u- B

    & J* f4 Z# r% q0 lwin = QMainWindow()
    9 \5 [) S2 \' z2 t0 M, t% R% b2 ^7 |( T7 K, T& ]! S( K
    win.setGeometry(400, 400, 400, 300)
    ! Q. \! u3 E% d7 q. ^  k0 p. w1 E) V% w' J$ ~/ T) F& B7 \
    win.setWindowTitle("Pyqt5 Tutorial")
    : j+ r2 x& I; P# {9 A
    $ r4 ]0 m0 F* m\# Label Text4 V& j& B6 t" ~2 ^  \1 K( [

    + ~6 \" @+ J7 j. a8 Y: G6 ^4 elabel = QLabel(win)2 X" g, H: g+ M8 D# k8 w

    2 g0 M% d- _' N: @' ?+ j9 \  rlabel.resize(200, 100)/ s( j8 ^9 V- E
    ' z7 t" V# M8 s' O  k
    label.setText("Hi this is Pyqt5")
    # Z) ?* f4 m& v4 u1 j8 O- P% b6 a7 Q- t: s4 f3 E, C
    label.move(100, 100)
    0 m! O/ z# |+ I
    & c3 ~  \+ d& f, q# Cwin.show()8 O/ Q% y6 c3 o% v. T( M2 E6 j
    ( p; F: T* r3 t, ~
    sys.exit(app.exec_())
    $ R+ M* V7 H$ `& L) K1 m' Q1 x3 `+ U4 `
    / }1 ^$ P1 e/ d

      N0 z: ~% ~& |; C按钮与事件:
    7 B0 i! Z6 K1 J: v4 ^( s
    + ~3 u8 u: H; C/ ]/ h" G; \import sys" m. z9 D8 X# |% E+ L4 p

      e2 I6 x4 V9 X# D/ X; afrom PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
    ! Q  d% \3 k3 _' \2 h; D, i/ S/ J1 p& ~% ^% b( l+ E
    def click():
    9 U' ^0 ?8 |% U  Q& W( v, j/ \( O6 Y9 {# v0 S7 O! x1 B
        print("Hy Button is clicked!")" E1 p. ~" b! X5 s9 t

    4 j; R' p& s) mapp = QApplication(sys.argv). _$ u* M- V- z) k3 V, `
      ^4 m# U! z( s3 c& f7 z2 \
    win = QMainWindow()
    , F1 S  H/ ]! Q( I7 Y9 x3 l
    2 t' \* d+ M4 [0 q# dwin.setGeometry(400, 400, 400, 300)
    5 \" {( ]+ d) |9 x4 e5 J& F
    " A- }$ p' V9 [* j' @5 P2 Cwin.setWindowTitle("Pyqt5 Tutorial")
    5 E6 ?, C+ p1 p& X
      i$ p2 M& P" W, s9 i- E6 o, a\# Button
    7 j/ D: ~: G5 j4 \6 U0 X
    / t, N: s2 U5 Q7 ^# ebutton = QPushButton(win)
    0 j" N' ?+ K5 n8 R( R/ n+ d5 Q9 P4 r9 A  V
    button.resize(200, 100)
    2 {! j9 q- j8 G$ g5 T7 h( H1 U4 t# u: y* _. y3 J6 s6 V: Z
    button.setText("Hi! Click Me"); W9 Z$ z" Y( ]. v' C. `+ v
    " X$ h8 C; U' H3 k  ?
    button.move(100, 100)
    $ ?% P; x7 n; ^* B. v# I
    2 l# [7 Z8 L  ^button.clicked.connect(click)& [/ c* r4 U; b) W) ~( r/ Z; l6 z
    , [0 W3 B# ~$ R% n0 t  B- A. r
    win.show()
    9 [: m$ b  h; c  g* P8 @
    4 |, E* O$ y% U' P: m: esys.exit(app.exec_())
    " n1 q1 [- C. Y( s9 Y
    * U1 _& k* ^5 e+ z  [/ F
    9 {- ?% ^! w* Y% J2 p; l, D; D  ^5 ?' ]0 R" E  O* ?; m
    button.clicked.connect() 在按钮点击后执行特定的事件。1 Q3 }: H+ h8 V
    1 I& t$ [+ A7 @
    PyQt5实战  F* o3 N" c. p% A! s# U

    4 u4 N- A8 Q3 I# t5 @实战项目:简易的天气查询软件
    % N/ v3 s9 Z9 @/ X% W& z0 n# V$ _! ^9 R4 `# i
    1、使用Qt Designer设计一个界面1 d/ r% y/ U. t; }9 s
    1 P; b; @( H- |6 B# j

    # P" z  V! E: O! x
      C% u; O' {8 I7 d" R5 E' J用到的控件有Button, GroupBox, Label,ComboBox,TextEdit,同时定义了两个按钮queryBtn及clearBtn,分别用来查询及清空天气数据。我们需要绑定槽函数,方法如下:1 ^2 \- s5 w! |! Q8 [+ y6 I1 B: {

    # O8 r, C7 D2 p: I8 Z: z4 P1 o6 e在Qt Designer右下角选择 信号/槽编辑器,点击+号新增: @/ v( v' E5 G" G* ?8 \

    + `5 s$ I) k) r分别选择queryBtn及clearBtn,选择信号 clicked(), 接收者 Dialog 及槽 accept(),(槽函数这里不知道如何定义,后期在代码里再进行修改)/ W+ g4 B' q' H' i1 O
      y5 v* h; @4 k8 e& M9 A( R; U; x
    以上完成后保存为Weather.ui文件。: S- Q2 y- A* a% C
    : m# m7 I3 `/ ^0 q
    2、转换.ui文件为.py文件+ F/ X8 c/ B. U) D$ }8 Y& }. B
    . }: b) e9 _! R: C1 ^  {
    PyQt5支持直接使用.ui文件:1 O0 a- A+ d0 i) [2 Q

    % c# @: J" t" j9 Rimport sys9 p, t/ `3 J+ _" _- S9 a1 u, C$ y

    - q. X2 Z6 h) H# efrom PyQt5 import QtWidgets, uic
    # H4 B- C) H7 ~" C# G7 r, g. L7 [$ K; H6 `
    app = QtWidgets.QApplication(sys.argv)
    # b2 A/ m6 h0 b! O5 w1 }* h% f- G( m( L1 l4 e8 A
    window = uic.loadUi("mainwindow.ui")
    5 `; y/ H5 [& Y
    ) C. |- ~6 m2 r7 k6 X' Pwindow.show()
    5 }6 Z. _$ L! ^3 `, Z  A7 o$ `# k, O$ t, b4 {8 ^; ~
    app.exec()
    9 ^2 G  T! {3 @4 t& D5 }* j但是为了更好的自定义及修改上面的槽函数,可以使用External Tools – PyUIC,即可生成Weather.py,实际运行命令如下:7 L0 o  b. o, P+ F0 u# E% v/ ^
    # x' k! D1 i/ r: E
    D:\Program Files\Python36\python.exe -m PyQt5.uic.pyuic Weather.ui -o Weather.py6 i! w) e4 E% D, o4 ]: ]" w
    其中,我们需要把两个按钮绑定的槽函数:
    5 N* _& W0 L( O# [
    / W# P: {. W( j& _4 ?\# self.queryBtn.clicked.connect(Dialog.accept)
    ) {2 B* K5 ~# E' n( [) S
    . h+ p# ^8 Y, O\# self.clearBtn.clicked.connect(Dialog.accept)
    9 J) x  B0 M* E% A( t- M9 N  K
    " C% l, s& t) f\# 修改为:
    3 l+ q+ R8 A) T& m2 u( E) c; ^( L+ O: U9 }
    self.queryBtn.clicked.connect(Dialog.queryWeather)+ X/ T2 Z' o; j  s/ F1 i4 v
    & ?' g; Q& d1 H+ y- I. S6 p
    self.clearBtn.clicked.connect(Dialog.clearText)
    3 }) K6 a: D0 O最终的Weather.py内容如下:
    ; Q4 R7 l" N; _* i; d  a4 c) x' ~- n+ x/ i, z7 U
    \# -*- coding: utf-8 -*-
    8 q7 \% ^4 G# S( k! O  `
    # V  ?+ l# j' B  ?% {. z4 T' E\# Form implementation generated from reading ui file 'Weather.ui'% s% w& |; H. L+ k& S
    7 S# S2 c: v/ S. P7 M6 |* I8 T! x6 W
    \#
    . @( K: V- P: Y
    4 p( t' I6 \( z- C0 \" c; w+ x\# Created by: PyQt5 UI code generator 5.15.43 U" f: n1 x. w4 z( o

    ; x% R- Z$ m0 h  a\#0 Z# O4 |( D$ b+ L

    1 f8 r, O; y# g" h/ a\# WARNING: Any manual changes made to this file will be lost when pyuic5 is
    7 ^* q. s) x$ L# F0 g. G9 z
    , _! K% b- M- V. ]2 T\# run again.  Do not edit this file unless you know what you are doing.0 O' e1 f- S9 Y! p# l+ @
    - J/ p5 e3 d9 x" ]* d( P
    from PyQt5 import QtCore, QtGui, QtWidgets& T3 |( \8 l  }1 l/ D! i" q
    , U" b( f$ G6 O
    class Ui_Dialog(object):
    ; l) v  {3 s6 v# m) Q$ q" ^' k: t( O0 ?
        def setupUi(self, Dialog):
    ; g/ u2 c1 h! P  a3 V% W: W8 i9 E8 c- w( A5 ]' r( g% p' _
            Dialog.setObjectName("Dialog")
    7 m5 q- X. u7 Q" t; t
    : {' p4 t  M9 C# W9 f7 S' k        Dialog.resize(600, 600)
    ' A7 ?. c  ^: K# P- D# d
    ; v( T2 F$ y9 V8 Q        self.groupBox = QtWidgets.QGroupBox(Dialog), h5 j, a! e: _  x; @2 p, ~5 L
    6 R6 m3 ~0 m1 \$ ]
            self.groupBox.setGeometry(QtCore.QRect(30, 20, 551, 511))
    ! |5 ^$ p8 d1 E
    & `. |) U, A( M' X        self.groupBox.setObjectName("groupBox")# i; m& O5 y6 [  Y! t  u4 X
    ( u1 O/ L# A- q6 t) ^5 M4 J5 j
            self.label_2 = QtWidgets.QLabel(self.groupBox)
    : O" C9 l! O" |; |- C6 A
    ! m% d- v" m' x: ]3 t0 z  |        self.label_2.setGeometry(QtCore.QRect(20, 30, 31, 16))
    9 Y& Q7 `* E) o/ n6 Q  |4 I: H* M( x' g
            self.label_2.setObjectName("label_2")7 V" V" t7 d  {2 l8 N/ _; x/ R

    / R6 y. b3 B. ^5 |        self.comboBox = QtWidgets.QComboBox(self.groupBox)! z- I, g9 G; {1 y
    6 S- ^: }# @  h
            self.comboBox.setGeometry(QtCore.QRect(70, 30, 87, 22))9 `; }" z" i1 d) x

    . a. Y7 g5 D0 t) K  e1 l" m& B        self.comboBox.setObjectName("comboBox")5 u8 ~, n# x# _9 t2 o' h+ \2 _! E

    , t& M0 ], M. x7 [9 Q8 ^; n# e! C        self.comboBox.addItem("")
    5 q1 ?+ I8 J& G/ T% M1 m& E
    8 ^" ]! ?# m% Q0 |4 }2 O' m        self.comboBox.addItem("")' r9 p8 t8 W7 F/ h( z6 H
    + P# `, X: y- q* i
            self.comboBox.addItem("")$ ~( y1 C) J) c  z: ?
    7 J0 S: q( U# I5 _4 R5 x
            self.textEdit = QtWidgets.QTextEdit(self.groupBox)
    3 e! X$ S8 R9 \4 |7 Q8 d' }
    4 c- @& l! O" K4 q        self.textEdit.setGeometry(QtCore.QRect(20, 70, 491, 411))0 T$ g) @( @7 [, [/ t
    , a8 T/ ]: m8 `! u) a; I( _/ U
            self.textEdit.setObjectName("textEdit")
    8 Q; j' ?% }6 ]: R+ g4 k
    * r4 C$ w% G7 K        self.queryBtn = QtWidgets.QPushButton(Dialog)
    4 K4 r$ ]+ y- ~5 T7 [0 G3 r* o2 A% j; b
            self.queryBtn.setGeometry(QtCore.QRect(490, 560, 93, 28))6 I) T  i* k* H0 a

    ( ^, S$ p- X/ l2 ?        self.queryBtn.setObjectName("queryBtn")
    " C1 c# m2 w. K) G
    ' I# G; g: L) ?$ D- V+ E        self.clearBtn = QtWidgets.QPushButton(Dialog)
    6 {" p0 S) q" M2 e  i1 H. i6 T& o1 m
            self.clearBtn.setGeometry(QtCore.QRect(30, 560, 93, 28))
    # h0 e; c7 F- [6 S; ^/ L$ W8 p2 J! \( n4 ]: e. i% f$ y
            self.clearBtn.setObjectName("clearBtn")
    3 [% P% ~! {5 E) p+ C+ I" [. a) e0 X: u0 P& o; a9 e
            self.retranslateUi(Dialog)& s. M" g' j' P$ x
    + D1 I# y2 {! t2 e
            self.clearBtn.clicked.connect(Dialog.clearText)2 ~" v& W/ m* N7 ^0 y4 m/ X
    7 @# C5 W! B$ g: H' `( k" H/ i
            self.queryBtn.clicked.connect(Dialog.queryWeather)
    1 R" R4 j: \: K& V) Z( P" K
    9 M6 L( x, a# N/ a+ u7 y        QtCore.QMetaObject.connectSlotsByName(Dialog)
    2 H( l$ q: f, d2 ]& z  V6 q
    4 T3 n4 i: N- }& }6 _    def retranslateUi(self, Dialog):2 A2 b2 \& Q: E. |  d5 Y

    ) C) |5 R2 o7 N        _translate = QtCore.QCoreApplication.translate
    % J% O: q7 [$ o0 K7 B
    6 R0 ?7 b$ U% J& ^        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
    $ Y, J- Y6 A* y4 X3 M* y  U  B, y) s7 G
            self.groupBox.setTitle(_translate("Dialog", "城市天气预报"))
    0 d/ C) r2 S/ w7 n, L" B4 b2 r* A8 t/ v* a9 x& q
            self.label_2.setText(_translate("Dialog", "城市"))
      Z) f8 g! i4 q+ o4 z8 M" T* ^2 i5 L) f* g
            self.comboBox.setItemText(0, _translate("Dialog", "北京"))* @# v$ H8 o8 S0 l

    & w0 s9 k& W! M; j: o0 [0 K        self.comboBox.setItemText(1, _translate("Dialog", "苏州"))  H  F( d: |$ Z

    8 n$ v7 I3 |! u! I9 F, Q        self.comboBox.setItemText(2, _translate("Dialog", "上海"))# ^3 B  e0 [  o' P; ?1 P6 e8 _
    ' H& y) @+ h9 n3 C
            self.queryBtn.setText(_translate("Dialog", "查询"))4 T. Y$ m/ R" u- B+ F! x3 h- ^3 N, d
    " I* s+ q9 y0 A5 N
            self.clearBtn.setText(_translate("Dialog", "清空"))
    2 r. F, n9 q/ i! \1 n
    7 D+ b% M; `  V3、调用MainDialog
    2 w: y) `0 R; w; @3 c
    # a, Q9 V; i, v在MainDialog中调用界面类Ui_Dialog,然后在其中中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。新增demo.py文件, 在MainDialog类中定义了两个槽函数queryWeather()和clearText(),以便在界面文件Weather.ui中定义的两个按钮(queryBtn 和clearBtn) 触发clicked 信号与这两个槽函数进行绑定。
    0 M# ^3 v4 |9 a' m! U( [4 f" \. h6 `1 |' }/ g2 L3 k
    完整代码如下:4 ^! f% v8 ^9 E- X' s5 G
    & R7 ~9 q! i2 [- F
    import sys
    , f( i* \4 ^  s/ W* s4 K/ z# n
    7 }7 X4 u- B6 Yimport Weather9 G2 q1 z3 \: }+ Z" ?
      }* Z/ ^( O- L% q0 C: ]
    from PyQt5.QtWidgets import QApplication, QDialog
      {1 k4 Q$ v3 _1 T& C' |
    + \6 R9 I, G/ l- Pimport requests
    % Z7 @* x! L  F& n0 \" s6 ]
    3 ?3 _0 B! r/ Z6 kclass MainDialog(QDialog):% @. A  D, W- G  Q& m  I) Y- m

    3 ^2 Q3 j0 F2 c9 U; g. J, O    def __init__(self, parent=None):5 }* o$ X. p: D9 H
    - k" s3 C( e) `" @1 l
            super(QDialog, self).__init__(parent)
    % p, ?8 V8 V2 r3 o2 p( g7 }
    ) d8 e* W: o- D0 z- ^6 I6 x        self.ui = Weather.Ui_Dialog()
    8 u$ {* s4 ?/ P( j7 l
    - X+ E. y, o! Z' t* x        self.ui.setupUi(self)2 h) W1 c! a6 Z3 H1 ]! V% r
    9 G$ f7 q6 e% x4 [- J6 }& m9 Y7 I
        def queryWeather(self):
    ' ^$ p  h1 t# Z$ `3 j
    ; _: r6 K# z' w/ ~. c- V  \' }2 ]        cityName = self.ui.comboBox.currentText()
    ) t; b" N8 O3 I# x8 O1 m& h
    ( O- _2 C' S3 R8 }' k3 k5 G0 i        cityCode = self.getCode(cityName)
    $ w& f! b6 t+ k0 K+ o/ @( o7 b& ~; ^
    $ w3 }+ @* T0 n% ~        r = requests.get(3 L4 e/ U! A' ?9 v/ V+ c
    " W" _+ ?3 S* c
                "https://restapi.amap.com/v3/weather/weatherInfo?key=f4fd5b287b6d7d51a3c60fee24e42002&city={}".format(7 E) b, j! [$ Y* s$ R! v# D! ~

    8 h- O5 K, y6 ?# T! o; g2 U$ q                cityCode))7 K% x" U3 {4 W9 N6 y, v( `7 \
    2 i7 R* g) T0 z: L2 ?/ u5 ]
            if r.status_code == 200:0 T) L- w  n$ t0 t

      h1 M* T9 r8 e, S" X* }: ~            data = r.json()['lives'][0]$ g9 S, H$ {7 e( Z2 ]. s4 k# `

    " N; H9 X: ?9 Z- C/ S% {3 k& \% Q            weatherMsg = '城市:{}\n天气:{}\n温度:{}\n风向:{}\n风力:{}\n湿度:{}\n发布时间:{}\n'.format(, W# U% F- s- s4 b' q

    : ?1 j2 A. ~6 i- }4 m! l& M4 s, K                data['city'],5 c( z3 d# }1 |7 c8 l! f
    5 [4 k4 A" m& z) e" ]6 s
                    data['weather'],
    & i: a9 J! Z( X) p! `( \3 |: C: A* @. B0 X2 d
                    data['temperature'],
    6 d  a7 d: e1 M/ ^" p' e" O9 q6 `3 E' F- Z
                    data['winddirection'],
    8 F( Y% G0 T3 u, ~4 G" |3 h7 N
    2 W- S0 Q9 x. m# W, u                data['windpower'],
    1 o! ~8 o+ G" h; ~5 p3 X9 S/ w9 L3 S3 Y1 r! E
                    data['humidity'],
    ; _1 H# B+ n1 t' |
      |6 g& _: H7 c6 s                data['reporttime'],1 ~2 \2 Z* w! b7 c: @, o- o. M
    ! X% ?! r. X. `7 y* J5 O' ?
                )
    % \" \1 t. V# A" L+ Y4 i- K; h& |4 L3 p, a4 h8 ]
            else:- o- O2 k1 }: i. a5 ]

    * O4 g0 c6 o' C0 L+ L. H' D            weatherMsg = '天气查询失败,请稍后再试!'
      e7 F# g, r9 h8 Y/ a" {2 T1 r4 H, J# m+ ]" I
            self.ui.textEdit.setText(weatherMsg)8 @0 Y$ V8 x5 y1 B4 C6 o
    4 v* P! X& I* f6 `
        def getCode(self, cityName):
    2 [, K3 Y. i6 J7 G
    ; [, Z% q; U- W2 h/ I3 f        cityDict = {"北京": "110000",
    . y* o& }2 G; e+ N& f/ J/ }& I$ `" z; A: U$ c! {/ T
                        "苏州": "320500",
    & r7 X" }4 [- w3 H: Z) [2 p
    # [- a1 n8 |- o                    "上海": "310000"}; s( C5 n7 E+ b0 z4 Q9 h& e1 C# D

    ' T" q' R$ k; G, U) h* k$ I        **return** cityDict.get(cityName, '101010100')0 X- h& D: t0 X6 m/ J: B. ~. V
    * Z9 U" ~- w1 [1 W- D1 X0 L8 k
        def clearText(self):
    " x1 x6 }: q; F7 `0 N8 T% K4 G- i
            self.ui.textEdit.clear()
    9 A" @0 g' F0 b+ n4 L' f) R+ T' Z! A
    if __name__ == '__main__':) T9 y2 m0 J4 R( Z! `: `9 M

    ( [1 }5 R+ X4 J$ G$ B3 k    myapp = QApplication(sys.argv)( @, h, Y# X- _! P* \7 S9 C
    5 `! p+ p) f, X# t
        myDlg = MainDialog()) ?1 W; H- `0 W$ A, w2 c$ ~- x: F6 k

    4 g9 O. A( u6 o1 T2 L# A+ J    myDlg.show()8 j% b5 |9 a* d! n' j2 x
    + M2 V- Z9 [  Z
        sys.exit(myapp.exec_())
    / e# X3 ?* r9 Q. P# |9 ~! c) Z4 R6 i. n& G
    运行demo.py并执行查询后的效果:0 \. A$ D6 _  |

    ; u( T9 e- o, \1 F( R  ]- J, G/ h. S7 N9 x' W' c/ q$ R

    3 Q" C- z7 l. R8 H: x2 d' k4、将代码打包成exe文件1 `+ q* m( Q, o0 G( K7 F# `8 D
    # t, I8 k2 r0 G$ @2 x" j
    将.py文件打包成可执行的exe在Python中称为freezing,常用的工具有:PyInstaller, py2exe, cx_Freeze, bbfreze, py2app等。功能对比:
    * r& ]7 H, C1 d) B6 m
    : r0 b! J8 n0 ~6 ^. W; b
    3 g3 m: w9 L! s8 b" V9 F* g6 ?/ E6 v- `# I) \
    py2exe:软件更新已经不活跃,因此也就略过。7 i& s) Y  n2 r) E8 k4 M

    + {& ]# q0 G5 l/ B) s+ \2 Jpyinstaller:明确支持win8、win10、理论上支持win7,,支持apple Macos, linux。pyinsaller可以打包成文件夹形式内含exe入口执行文件的形式,也可以是一个单独的exe文件。7 s1 g; @7 d2 s0 N  b0 g! c
    ) {, \2 j( e% X6 l2 V
    fbs:基于PyInstaller,使用起来更加方便+ b5 W  s1 H2 {7 E- E' I

    5 {& {3 b5 U( V: W7 ^3 A7 Q这里选择了fbs来打包。fbs的安装方法:
    0 Q$ Z# \0 g9 _4 L. _0 r
    - E* Y' _% J' Gpip install fbs
    . w1 h* A$ y. N' J4 Q9 y使用方法,在命令行中输入:
    & U% i8 V, U& g) n5 H4 k" l$ n9 c% i- ^0 J0 V  \
    fbs startproject
    3 @4 d2 a5 l+ ?" K2 _7 Z执行完成后需要输入一些APP的名称等。完成后会生成如下目录:1 H' [/ H' c) A  x( ~( ]
    : ^) d; d0 W4 ^, v& j3 s6 B$ h
      z/ l; J; e( _% A5 z8 o7 t3 S
    5 \! C, s+ A& }5 a8 o& K
    将刚才编写的PyQt5的代码(demo.py和Weather.py)拖到src/main/python文件夹下,删除原有的main.py,并将demo.py修改为main.py。然后打开 main.py,在文件头部添加如下代码:
    ! d' v& O' N5 H9 Y% W$ d+ p! l' E. h+ M3 m
    from fbs_runtime.application_context.PyQt5 import ApplicationContext. {$ U# R# A0 v, @& w1 \
    ```1 S* D; u+ i4 F; J; s# H; `+ D0 I
    完成后执行:" \6 g3 `. w$ v. V
    ```' P9 ^, T* j$ G* m; U& p
    fbs freeze# a: e$ |  c+ G0 E
    ```8 K+ n2 Z( f, z& F) k+ I
    即可实现打包。生成的exe可执行文件在\target\MyApp文件下。
    0 D% [7 ?% g( c) F
    / p8 {& i0 |" t% X$ m3 E————————————————6 o) {( A. U9 p$ {# e: p
    版权声明:本文为CSDN博主「宋宋讲编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。- B: I7 V- a* T: ^- r, _, V* y
    原文链接:https://blog.csdn.net/qiqi1220/article/details/126289667
      _, f; w6 P" f, N$ v  z, D% g* t2 u( m
    , s# ?% ?& n0 V1 Y- ^' M
    & v' \- W5 @# ^: o
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-8-6 20:36 , Processed in 0.552413 second(s), 51 queries .

    回顶部