QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2210|回复: 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使用指南!# n0 j3 n% S; ?2 q* R% O: ]" q

    " c( y$ U# _5 L8 {. h2 W* ?# v使用Python开发图形界面的软件其实并不多,相对于GUI界面,可能Web方式的应用更受人欢迎。但对于像我一样对其他编程语言比如C#或WPF并不熟悉的人来说,未必不是一个好的工具。
    ( V; m: k3 B+ |3 o+ i5 d3 U5 v
    : ]+ D, ?2 Q8 F% z% j" N, A常见GUI框架
    / q4 w3 S& Q. A* T: b6 A; `: e4 |2 G  `; s& C2 u( r2 K# O6 k2 ^
    PyQt5:Qt是一个跨平台的 C++图形用户界面库。QT一度被诺基亚拥,后出售给芬兰的软件公司Digia Oyj。PyQt5是基于Digia公司Qt5的Python接口,由一组Python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。
    6 `$ I: X, D$ m) D" J" x/ k% p# l: g
    Pyside6:Pyside是QT公司官方提供的Python包,上一版本为Pyside2,对应的是QT5,最新版命名规则进行了调整,更改为Pyside6,对应的是QT6版本。由于官方出品的比较看好,缺点是发布比较晚,网上的资料没有PyQt5多。) D7 p4 N. h( E9 F
    - C5 O/ K7 v! Q7 \2 n
    Tkinter:Python内置的GUI框架,使用TCL实现,Python中内嵌了TCL解释器,使用它的时候不用安装额外的扩展包,直接import,跨平台。不足之处在于UI布局全靠代码实现,只有15种常用部件,显示效果简陋。: j3 X" t& C+ K  W: R" [

    5 i4 a; F9 `( \PySimpleGUI:PySimpleGUI 是 Tkinter 一层包装。使用 PySimpleGUI 实现自定义 GUI 所需的代码量要比使用 Tkinter 直接编写相同的 GUI 要少得多。
    + b/ t, ]6 j: _4 |
    7 N$ S4 _$ Q/ F& X. b4 n9 O5 m  tWxPython:wxPython是Python语言对流行的wxWidgets跨平台GUI工具库的绑定。用得比较广泛,跨平台,C++编写,文档少,用户可能就需要根据编程内容对不同平台中的GUI代码做一些调整。遇到问题不好解决,代码布局控件,不直观。
    . b" `3 k* @# I0 W; {9 w9 E
    ( U# _. U; a! y/ D( \Wax:基于wxPython ,为克服wxPython的问题而制作的一个包。8 D! A9 X& Z1 x3 y; ^# G" f7 I' w
    4 R: I, Z# d, U8 b
    Kivy:主要针对多点触控程序,智能手机平板等,也可以在没有触屏功能的系统上,全平台支持(Windows, Linux, Mac OS X, Android and iOS.)使用Python和cython编写,中文支持差,需要自己下载中文库并且制定路径。
    - L4 \9 b2 `1 C3 A8 ]! G5 G7 m3 J+ R# {. u% q
    BeeWare:Write once. Deploy everywhere.需要与Kivy配合使用。
    6 ~7 }# X6 m! H- G* c( c; a* n  d! @5 U/ p! Y0 X9 R: L% ~
    Toga:一个使用Python开发原生APP的GUI工具包。Toga由一个具有共享接口的基础组件库组成,以简化与平台无关的GUI开发。Toga适用于Mac OS、Windows、Linux(GTK)以及Android和iOS等移动平台。
    - O$ r" H$ M' j$ P
      u5 {' {* r7 A- p" d0 q5 }Eel:一个轻量的 Python 库,用于制作简单的类似于 Electron(但是比它更轻量) 的离线 HTML/JS GUI 应用程序,并具有对 Python 功能(capabilities)和库的完全访问权限。% g7 z! g  t1 V" G" [3 h# y/ O$ x
    . }" X$ L, N2 b" P: ]. o- `" F
    Flexx:一个纯 Python 工具包,用来创建图形化界面应用程序。其使用 Web 技术进行界面的渲染。你可以用 Flexx 来创建桌面应用,同时也可以导出一个应用到独立的 HTML 文档。因为使用纯 Python 开发,所以 Flexx 是跨平台的。只需要有 Python 和浏览器就可以运行。; l% N% O# t) O( \
    , e9 B9 `$ z8 D4 _5 e* z
    pywebview是围绕 webview 组件的轻量型跨平台包装器(wrapper),它允许在其自己的本机 GUI 窗口中显示 HTML 内容。它使您可以在桌面应用程序中使用 Web 技术,同时尽最大可能隐藏使用浏览器构建GUI的事实。# d/ y& ~0 u  x3 G. t' B

    " B0 ~' F9 L3 P5 V0 Lenaml:一种能够让你用最小的努力就可以实现高质量GUI界面的的Python框架,也是一种独特的编程语言。enaml将声明性语言与基于约束的布局系统结合在一起,使用户可以轻松地定义灵活布局的UI。enaml应用程序可以在任何支持Python和Qt的平台上运行。- l5 A6 H' |; I. P' i. s( D

    7 I7 U1 f1 z9 M2 s/ }个人想法:太多学不完,先学PyQt5,原因是资料多,学有余力再学pyside6,最后看下PySimpleGUI,看能否解决一些简单问题。, b, e$ y3 P+ S0 e9 w

    1 B% j8 }" s) sPyQt5简介
      i# T! w7 N; h4 `' {  \/ x- A% E# a! u1 v- A# t2 r5 \' d: {
    PyQt是Qt框架的Python语言实现,由Riverbank Computing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件,因此PyQt的API接口与Qt的API接口很接近,但PyQt不再使用QMake系统和Q_OBJECT宏。8 i- z+ F  h4 k5 }& q2 q8 c% b

      b# g9 ]( K, kPyQt5提供GPL版和商业版证书,自由开发者可以使用免费的GPL许可,如果需要将PyQt用于商业应用,则必须购买商业许可。$ W4 x9 e, q/ O* ]% V9 X$ V( u/ j+ M
    ( y0 M, Y4 S) t1 f+ Q. N
    PyQt5特性如下:
    ) a. F7 k( ~+ n( X/ n7 |6 w: E2 v" |5 v. p6 Q
    基于高性能的Qt的GUI控件集。
    , c9 u2 W) M7 P- i7 d6 k; W0 z! i# ~" \6 i$ n, {9 m
    能够跨平台运行在Linux、Window和Mac OS系统上。8 |- C! Z( n7 q( q

    8 u2 M7 h" ?, n% b0 a) t3 C# n使用信号槽机制进行通信。8 e9 N! U0 {& J. S/ {

    ' G) O! e- }. N' r7 _1 P" e/ q$ L对Qt库进行完全封装。# A7 W* u5 t0 x0 }/ [! C6 ?
    , A4 U4 I$ H) M; |5 q  b  o! B. t
    可以使用成熟的IDE进行界面设计,并自动生成可执行的Python代码。
    ) H& x, {4 C* z; N5 B" d
    9 a" |4 b  ?. [' d4 e/ l: t提供一整套种类齐全的窗口控件。
    6 u  Z- G& ^$ s  f/ X% p7 J" G. }1 ^. ]6 ^: L
    PyQt5是由一系列Python模块组成,有超过620个类,6000个函数和方法,主要模块如下:
    # ]- a  Y  s4 L4 [
      Q3 |. j& `: E/ I) Y+ ^" S7 e. gQtCore:包含了核心的非 GUI 的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime 类文件、进程与线程一起使用。
    $ k7 A- g4 }# |2 p/ d1 t' w6 O; C# M" P5 F$ {3 N
    QtGui:包含了窗口系统、事件处理、2D 图像、基本绘画、字体和文字类。) |+ T- G4 d4 g4 k: k8 Q* X
    - \: _3 W, }4 i: ]0 v) v
    QtWidgets:包含了一系列创建桌面应用的 UI 元素。
    8 C. Y' v8 V7 V# }, _" Y$ |* `3 l. \) S( M5 D. Q! t1 B
    QtMultimedia:包含了处理多媒体的内容和调用摄像头 API 的类。9 P5 V. k4 Y2 J% S9 n

    ) s4 \( j9 C- A) s3 H$ d: \QtBluetooth:包含了查找和连接蓝牙的类。
    9 `6 K& @- F' \2 b; p1 v; R5 P. c$ A. ]6 P+ n8 b
    QtNetwork:包含了网络编程的类,这些工具能让 TCP/IP 和 UDP 开发变得更加方便和可靠。  T, z* ?. |% U% a0 `2 z1 ]+ ~

    / W& y6 @6 V* p+ p3 LQtPositioning:包含了定位的类,可以使用卫星、WiFi 甚至文本。9 h( ?- b  I1 t
    ( S' F' ]6 T) C  k
    Enginio:包含了通过客户端进入和管理 Qt Cloud 的类。
    5 B3 v/ e4 ?9 ~6 x2 Y1 e* @7 ^8 G
    QtWebSockets:包含了 WebSocket 协议的类。
    - Y4 k, G. c) C: y
    8 {' `* }( ~  H" i4 @QtWebKit:包含了一个基 WebKit2 的 web 浏览器。
    8 t8 I, A" x9 L  W: ]* M% A2 C
    , Q- h. d4 c( e& OQtWebKitWidgets:包含了基于 QtWidgets 的 WebKit1 的类。
    " r8 F6 ^* d) q0 O9 G" ~* n
    % F2 A. {$ X. @  ?QtXml:包含了处理 xml 的类,提供了 SAX 和 DOM API 的工具。) R) s0 C5 P  @6 a$ x9 @

    & f( q( V3 ]3 ~! K1 u0 x+ }QtSvg:提供了显示 SVG 内容的类,Scalable Vector Graphics (SVG) 是一种是一种基于可扩展标记语言 (XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。; N8 u, M+ N/ ?7 u7 \
    * H' y0 ]( L6 e0 E5 D
    QtSql:提供了处理数据库的工具。
    . o/ l! P& a- A+ K) d3 s1 d% i) I% g
    QtTest:提供了测试 PyQt5 应用的工具。9 z1 `& `2 N/ f/ p0 `$ }& P
    9 b. c9 ?" [; L! E; S7 b
    PyQt5的安装
    9 V6 \  j: O1 ^4 F: j0 H! B, ~; U( T' e6 a; z( @
    由于后期要使用fbs进行打包,fbs对Python 3.7以后的版本可能存在兼容问题,所以我选择了Python 3.6.8进行了整个环境的搭建。主要内容为:Python + PyCharm + PyQt5
    & E& Y0 g2 R0 A) r  G/ n+ M$ i2 O# R" F- {2 p9 H+ \/ g& i
    安装PyQt5# A' }: Q' K3 h
      B# S2 h% b, O0 h% l
    pip install pyqt51 t9 Z, `5 z. H! X
    ( `$ @& ~( u' V5 q6 T, t+ H
    pip install pyqt5-tools
    6 O8 M  M. l, g* i: k其中pyqt5-tools为Qt Designer拖拽式的界面设计工具。安装过程中可能会报如下错误:8 Y1 Q, I, N2 P: L3 ~& ~; M

    0 w3 [( u. k4 [8 Wqt5-tools 5.15.2.1.2 has requirement click~=7.0, but you'll have click 8.0.1 which is incompatible.
    ( r5 g$ V7 E9 d) [解决方案:
    + q) m$ y# n: c+ H. c: _1 g( N2 ~
    - X0 O' e* C8 t/ W( t  r! opip install click~=7.03 B9 N9 o' i) ?# k  Y  N
    Qt Designer的配置" _1 |2 n& Q) T! s

    . Z* I* L/ d; u* G4 u" B! E8 N  L; m5 @Qt Designer 是通过拖拽的方式放置控件,并实时查看控件效果进行快速UI设计。- A9 u- `4 Y! p8 b- ^& C- M$ U

    ( J- R9 b8 [* \9 L
    3 H* h* u$ H/ s/ y  E4 i9 x1 ~( E3 _+ S# ?/ `
    整个画面的构成:
    % M  K4 G. n- R
    6 w$ i/ \* d% v5 P左侧的“Widget Box”就是各种可以自由拖动的组件
    $ V5 E" h# F8 o7 U1 |
    . d7 T) q% w) d# d' E7 c中间的“MainWindow – untitled”窗体就是画布
    # _5 A) Y+ O, `  J9 d% Q5 h. G5 t2 q' _
    右上方的”Object Inspector”可以查看当前ui的结构1 g, o6 W1 }6 {) t& }0 K- N
    4 |: v  N* b) x9 v
    右侧中部的”Property Editor”可以设置当前选中组件的属性6 b. `7 H( c1 u$ ], j' g1 ~2 V: K
    5 P* Y8 o" e* y+ K
    右下方的”Resource Browser”可以添加各种素材,比如图片,背景等等
    1 a& `3 i/ L, c4 b1 |8 O7 W  t4 a; c9 ?2 W. V2 [2 A
    最终生成.ui文件(实质上是XML格式的文件),可直接使用,也可以通过pyuic5工具转换成.py文件。
    / t! d+ R3 ]& j, ?( k0 t9 ~
    ) u6 Q/ G# k! ]0 {  i# KQtDisigner配置
    # {: r8 n, ?4 l( T# Q$ S/ d$ u7 G/ a2 T8 H
    在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    % u( I" |! b* e. m1 y( U
    8 ]2 K; {1 Y# NName: QtDisigner
    : {. U+ D  T+ `3 U3 e" f; _/ r& y
    # B/ E) X3 c& @7 @9 r. g! dProgram : D:\Program Files\Python36\Lib\site-packages\qt5_applications\Qt\bin\designer.exe # 请根据实际修改
    % e  c& X" n; S; Z$ e- ]9 \/ C* b. S6 Z6 Y
    Working directory: $FileDir$' @4 }. t  M) j$ b* ?4 \
    PyUIC配置
    9 g0 a1 N9 i5 M& L' V0 E8 l% F) F. I# {2 ~, Z0 Q
    PyUIC主要是把Qt Designer生成的.ui文件换成.py文件。! V' y) u# Q6 @, j. n  U+ T

    ; g. n9 |- ^0 l在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
      ^/ T: o# S( q2 S# S  s2 `5 ], \! D5 W8 D+ W
    Name: PyUIC/ n% N* K/ J- C1 S4 I4 c  }

    - Y7 l! J% r# [% P; ]# MProgram : D:\Program Files\Python36\python.exe # 当前Python目录,请根据实际修改" A+ I; N/ B7 K
    9 f: _. q; t& @/ k! g2 B$ ]; F$ ^) }
    Arguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py
    8 b, j+ h2 p3 U, L
    ( Y. e  m" h0 l1 \  P0 N. y/ _2 g2 VWorking directory: $FileDir$
    . F5 U5 t. q" V: ]1 YPyRCC配置
    - A9 U; v  k: l6 J  l1 t& ?5 O( o5 s8 v8 v; }
    PyRCC主要是把编写的.qrc资源文件换成.py文件。在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    3 h4 v9 ~$ p3 i- Y1 N: Y8 C
    ) o$ I: i7 L5 y! A! rName: PyRCC. ^+ o( `- l, `; S0 ]. Y
    - @; Q  I% i& L- ~! u
    Program: D:\Program Files\Python36\pyrcc5.exe # 当前rcc工具目录,请根据实际修改
    6 d1 s' N: ~: D( m. P* W! l6 e( y" e- V3 c
    Arguments: $FileName$ -o $FileNameWithoutExtension$_rc.py" D- y2 O6 P& g& Q/ e  N( Q

    ! J2 u* b3 Q& ~+ q/ o; o: CWorking directory: $FileDir$
    . a2 I! }6 y) t' ]# c% ^PyQt5使用示例/ z2 g1 {: V" o; U+ l
    ; N2 p( i4 ^0 k+ U
    创建一个空白的界面:
      c$ j  _$ U9 R: [5 q6 x9 z* o  \) p
    import sys8 C, f2 t$ h( p4 P0 b

    9 v8 O0 M5 C3 @7 `from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
    * O# t, M$ Z" [8 C4 G; f3 h& U% Q8 O$ I: X
    app = QApplication(sys.argv)
    1 V! i$ o0 |3 d& M1 \% u' v3 y" d  x. b8 J( ^" q7 D8 X; S+ v5 v* K
    win = QMainWindow(), f! [1 i0 I2 r* J
    9 b' y' Z8 O& R) r1 N+ j
    win.setGeometry(400, 400, 400, 300)
    4 b: g* ^2 O$ l% T( F: I) m
    6 ]; p! ~) e' |8 j* Ewin.setWindowTitle("Pyqt5 Tutorial")) w% \# N3 E/ Z& R/ S* F: O- x
    7 c2 q+ D1 w+ V' v
    win.show()
    $ p6 M! x* y! Y) b* w
    / J- U* |' B" ]sys.exit(app.exec_()); t; a  t# Y% N* K- s1 O1 S& Z

    , F# _, h1 @: P2 ^* C# x9 R2 R6 Z7 U$ R5 D  C3 X

    # o/ C( `1 T9 V* h2 T其中:
    7 D" B% ~9 H2 X' r& C) c/ K) u
    ; b+ E0 J) F0 }4 z: j8 XQapplication():每个GUI都必须包含一个Qapplication,argv表示获取命令行参数,如果不用获取,则可以使用[]代替。
    ) X0 Q* @8 x8 U& F7 t; I7 L3 O5 K" Z; b# _9 }5 _' r8 G. a
    QMainWindow():类似一个容器(窗口)用来包含按钮、文本、输入框等widgets。arg标识可以获取命令行执行时的参数。
    3 g! L6 z! G; L5 k4 j1 f4 o  V
    2 G4 w; W$ G! w7 g" d0 f) |SetGeometry是用来定义 QMainWindow() 窗口的尺寸, 语法:setGeometry(x, y, width, height ),其中x,y为屏幕上的坐标点。0 C7 K6 D/ Q) [) r# J
    4 D9 E/ E& x8 b* C' v
    show():用来显示窗口/ F* t) P2 ~/ G. k/ s: F
    2 s" l! B  O) Y" B7 ~1 s5 c
    exit(app.exec_()):设置窗口一直运行指导使用关闭按钮进行关闭
    7 N' B+ i/ V9 a: t; E2 t5 I6 T
    ) A+ o- w/ `' f+ _: TPyQt5支持的常见Widgets有:% \. x2 C; W2 E% y3 {

    % e0 M. t9 [6 X5 v7 U4 f/ _. i  C* t$ X1 t7 p1 I, \" F* S/ J1 S

    $ _9 S3 D( {$ a) y  v7 n从上到下,从左到右依次为:Qlabel、QcomboBox、QcheckBox、QradioButton、QpushButton、QtableWidget、QlineEdit、Qslider、QProgressBar
    6 _3 D8 K- p( f- a8 `  \# Y" ]1 O) Y
    对于使用Pyqt5设置文本内容,我们使用Qlabel:, N2 u4 h6 G: C& y$ M/ z5 C" y

    ) a2 Z3 U4 G3 C1 e% rimport sys
    ( L" u, H- H8 ^4 z
    3 H3 D$ m+ W) c5 Y& B) o% e9 A+ lfrom PyQt5.QtWidgets import QApplication, QMainWindow, QLabel) i/ k6 }: j, j

    % L: G! Q% N+ k4 T  o& A- rapp = QApplication(sys.argv)
    ; T0 w+ G* Z7 R
    9 ]3 G. x9 o5 V6 `, Rwin = QMainWindow()
    6 X: x# M, o1 g- i; N# H
    $ @% n' Q! ]0 \win.setGeometry(400, 400, 400, 300)( ]& x; a% }: |; g
    ) g) s. F& g# H3 J9 `
    win.setWindowTitle("Pyqt5 Tutorial")& |- @! ]' |; ~' y7 Q
    5 q, a" l" z" _' A3 B* o
    \# Label Text" r5 p$ F+ E/ ?

    3 Y4 w4 Q( A' q% B7 r; [. G+ Plabel = QLabel(win)
    $ W+ L& D6 F( d- Q' k- i
    1 l" z; k: ?* Hlabel.resize(200, 100)
    3 v: P% H; H. h, o; }& ?( g. ?' \0 Q/ H
    label.setText("Hi this is Pyqt5"): [/ P2 ^, g! b" n1 e& x# k
    ( Y* g4 f$ V  W% E2 ^
    label.move(100, 100)
    ; b/ q7 p: H* g% t* e. V
    0 c' [, R. ?# x; m# ]win.show()
    . @$ s- A5 a: d& }" D. R: X% Z- Q- s0 C
    sys.exit(app.exec_())
    5 ~) Q5 V* \" O* Y# w; c/ d3 c* ^% ]  d( J7 G) f6 F3 w
    : R2 i# N' y; A. @& ~2 A
    4 D( `$ ?* l, p/ R5 v" |% _& R
    按钮与事件:
    & `% t6 ]! }( u" R4 O) a1 h6 J; {  }3 |2 v9 t
    import sys% H2 f4 F+ k% @2 d

    ; G& j: ^) I0 i# i, \from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton4 J0 }$ [$ u$ y2 x" F
    % t1 A3 \6 z# _& H
    def click():4 c- h3 Z+ {; Z, V, u! U7 N: [

    + r2 M8 B4 ]. q2 |3 I8 b% t" r    print("Hy Button is clicked!")
    # ~+ l' t. y: i& C. L+ d4 T" r( V7 t" Q% i, W
    app = QApplication(sys.argv)4 K1 s1 S# ^" Z! {

    7 [. D* w: ~# T* t1 Q" |6 B: c1 Awin = QMainWindow()) o* @1 U3 l4 ?
    ' c- b6 I1 D8 P# o+ f
    win.setGeometry(400, 400, 400, 300)$ h3 m. i6 A' S9 l

    8 x8 i$ s/ z! H: F7 H' Ewin.setWindowTitle("Pyqt5 Tutorial")
    " e' F; H/ D4 [- J/ F! R
    ( s  p- M. l0 J9 ?, k\# Button
      H0 D" @3 p9 ]* J/ L$ z* _1 m! ?& Z' u& S
    button = QPushButton(win)
    9 k+ `2 }5 q  \# `0 F5 B% M" @4 q+ f
    button.resize(200, 100)
    6 d* b# Q  a3 A3 G! L0 C8 n( A
    9 r) r0 o2 a6 c0 zbutton.setText("Hi! Click Me")
    0 O1 }4 b: J4 q
    + `4 ^# }. D9 I: w$ tbutton.move(100, 100)
    - C4 S- ]9 K8 @# {4 ^+ H4 S! J0 ?# X, S5 L3 y( _5 x
    button.clicked.connect(click)
    9 d0 K, a0 ^% ]6 Z2 o8 @# }" ?3 k, @
    win.show()
    ! X2 ^3 Y% a3 I
    3 Q# W  h8 @; N! |sys.exit(app.exec_())9 T. i5 w+ F" m4 i
    - T/ Q5 p" X9 r; m: U( b( Y

    7 P/ I; q) F1 ]: m, }4 N7 O+ k  ^$ a+ x* F5 V* O
    button.clicked.connect() 在按钮点击后执行特定的事件。
    : p8 y+ P* d" f9 Q* r3 P
    % a7 k7 A; r# F/ a4 lPyQt5实战) S/ @, d8 N9 L) g" ]; g# E; c
    * n, X0 U$ O# ]# d7 f1 A/ n7 u
    实战项目:简易的天气查询软件
    5 B5 t7 z; n8 t$ S
    $ U9 \1 h; ?. S& x  X  F1、使用Qt Designer设计一个界面
    6 h) {- v- D2 T$ ?9 I
    , a) V+ w0 F7 C) N& b) z' k. d% o9 f! q

    % y+ {9 b, W$ c用到的控件有Button, GroupBox, Label,ComboBox,TextEdit,同时定义了两个按钮queryBtn及clearBtn,分别用来查询及清空天气数据。我们需要绑定槽函数,方法如下:" `( s% Y; E7 d, p3 n" d

    / @" D4 j6 e$ G0 X# J在Qt Designer右下角选择 信号/槽编辑器,点击+号新增. n* [6 O' c' T2 b* v" B, F

    9 C6 A1 c$ [. X, r6 ^分别选择queryBtn及clearBtn,选择信号 clicked(), 接收者 Dialog 及槽 accept(),(槽函数这里不知道如何定义,后期在代码里再进行修改)% x/ |+ L; r8 k! ]7 S) b, P) w
    7 l9 T; f& F; y) \: D
    以上完成后保存为Weather.ui文件。
      p2 A7 ?  b1 T* \) f. k' N: F3 O/ _" ^2 ~* Z% y. z
    2、转换.ui文件为.py文件6 z  r7 M% J' ?7 F
    8 \3 Z) M* N/ v1 Y6 U, Y, E
    PyQt5支持直接使用.ui文件:0 ~- @1 z" V, H; @
    ; x# S. J$ w2 x7 K" I
    import sys
    ( {" \6 L! Z8 L! O. D# x
    0 n( i4 P3 M. R% q; Jfrom PyQt5 import QtWidgets, uic
    / C! [- M! I8 }/ l2 R
    ( F$ v; {* [3 G; ?7 g  tapp = QtWidgets.QApplication(sys.argv)
    ! v' u7 A* Z- F; a
    ) \0 {* o5 q1 R  mwindow = uic.loadUi("mainwindow.ui")
    ! ~8 V0 D1 t2 ]$ B1 ?, v' a
    " J9 B7 F0 d5 n( N0 `- B* pwindow.show()
      n$ b0 y* U( R7 ?' H0 V2 P  L' O  I
    app.exec()
    5 V; J+ W5 \$ v/ K# v但是为了更好的自定义及修改上面的槽函数,可以使用External Tools – PyUIC,即可生成Weather.py,实际运行命令如下:! n; d2 w2 a+ C& o" o" i# I

    ! n) o' o; P0 RD:\Program Files\Python36\python.exe -m PyQt5.uic.pyuic Weather.ui -o Weather.py& ?4 P* e6 f! d3 k2 o) G& K- S
    其中,我们需要把两个按钮绑定的槽函数:
    ) r, ~, |% Z. J+ S, x
    % P" d$ S& S  A  r2 m\# self.queryBtn.clicked.connect(Dialog.accept)' X6 ?4 w, K5 I' v- n

    - Y9 p& w2 A, E/ T& \' p\# self.clearBtn.clicked.connect(Dialog.accept)
    ! V# @! f  u; I# j4 X' i
    / p$ S3 _; y7 w' ^- f/ g\# 修改为:8 `8 y& i5 v0 U
    8 @/ J' a, k4 H! w$ D
    self.queryBtn.clicked.connect(Dialog.queryWeather)6 [5 w9 h3 F4 ?+ ^9 Y

      s3 B2 p6 y) U# i5 Dself.clearBtn.clicked.connect(Dialog.clearText)
    & }- ?9 ]( L# f( T, ~0 s% e最终的Weather.py内容如下:1 J8 ~# ^9 C7 z+ J6 a+ l6 u
    1 r: E8 R; w' A1 e( @) w
    \# -*- coding: utf-8 -*-$ s: q" d+ d& r" A' n

    0 I5 S) N& \3 L$ B! P! y1 b2 d\# Form implementation generated from reading ui file 'Weather.ui'8 d1 r- [6 o) @$ o
    8 ]3 _$ d4 B& a' J* ^0 P( j
    \#$ u+ F: j4 S: x# G, Y  y
    5 r. Q7 S8 v2 _! _8 L
    \# Created by: PyQt5 UI code generator 5.15.4
    9 F2 _5 @. b  ]/ P% z
    + B; A& }# q7 g* L% n( C\#) V7 J% J* }! B: D6 }7 n) e. B

    - s$ ?6 N5 X0 E, A4 ]/ R% s\# WARNING: Any manual changes made to this file will be lost when pyuic5 is
    + ]+ f; O" P) W7 g/ ?/ W4 K1 B1 h( t/ ^: o$ t' e
    \# run again.  Do not edit this file unless you know what you are doing.
    * S, A! F4 O; v0 U% i6 h0 F9 `1 g8 \& I
    ! p+ F% N* v. Y% s! Dfrom PyQt5 import QtCore, QtGui, QtWidgets
    " |1 u- m  g3 k' P* T5 j1 f4 z4 Y# h
    class Ui_Dialog(object):
    4 B* D' f* h, A
    : P9 R* v+ S$ V- M# Y  C    def setupUi(self, Dialog):
    1 f- p# x) A$ ~; X- m  Q! h8 o; D8 k; k. ^5 p
            Dialog.setObjectName("Dialog")
    0 c/ ~9 L; ]" D3 O' V. C5 w  W0 f/ J% X4 [: J8 |( C6 P& [3 {
            Dialog.resize(600, 600)
    : S0 B3 V# m" O: x
    # e) b4 }+ Q" Z& }4 D5 l        self.groupBox = QtWidgets.QGroupBox(Dialog)) ^) X: E# c8 ?1 A! v6 k. q

    - C! ?! [+ y& X, U: A- |        self.groupBox.setGeometry(QtCore.QRect(30, 20, 551, 511))" x( v. y9 X8 T, l  P5 U. N5 E5 [
    : E' z. Z9 K7 C5 c( d3 @
            self.groupBox.setObjectName("groupBox")
    0 R& }4 q# I4 a7 P4 H
    4 I( R1 {3 [+ M3 Y& D        self.label_2 = QtWidgets.QLabel(self.groupBox)
    9 r4 x' ^8 x  n6 _' `8 }  v4 R
    5 ]. \" I4 `* C: s" |0 A( ~6 C        self.label_2.setGeometry(QtCore.QRect(20, 30, 31, 16))$ C% h6 E$ e$ L' ~$ n

    & V$ K" U- |) e# f& l$ U' }( W: q  J        self.label_2.setObjectName("label_2")
    ' z! B% I7 _: c
    7 x9 i% s/ ~3 `! q- @$ X) ?        self.comboBox = QtWidgets.QComboBox(self.groupBox): o4 u, R1 X  w) A) ~
    3 ]1 e% y" W* @4 N2 M% [9 b* f
            self.comboBox.setGeometry(QtCore.QRect(70, 30, 87, 22))% A# L2 Q, H4 c2 O

    9 K) }& A" t: K6 L0 a, O        self.comboBox.setObjectName("comboBox")# w+ B! u# P; g3 z+ ~
    & h+ J+ j7 A* G6 Z5 N+ S
            self.comboBox.addItem("")7 S2 {: V# ~' L8 J; A" ~

    4 P; M7 f) N, E8 X8 x0 t        self.comboBox.addItem("")
    ( U4 |9 V* H  k, j; D" i5 ^) w) e, ]0 I8 d7 s
            self.comboBox.addItem("")
    . {" o% k9 c# d! S# K+ l2 |' K7 }7 E& m1 }
            self.textEdit = QtWidgets.QTextEdit(self.groupBox)" y' d+ }# a. Q; V. G0 B$ u
      P5 R* U# C" c6 e+ c' y/ P
            self.textEdit.setGeometry(QtCore.QRect(20, 70, 491, 411)): s) ^# E* k2 B- v

    1 M7 I( G/ g# v. d. W/ l( t        self.textEdit.setObjectName("textEdit")
    & ]5 k2 @1 z% J# y6 B( `$ n1 S  \4 [4 q7 C
            self.queryBtn = QtWidgets.QPushButton(Dialog)
    7 H3 c9 d; i! d* N( S1 c4 b7 V* w" ^6 P$ q" F; J1 G$ a
            self.queryBtn.setGeometry(QtCore.QRect(490, 560, 93, 28))
    ' b: L8 {  W2 E5 h/ u5 }. _/ Y+ Q$ L& F* U
            self.queryBtn.setObjectName("queryBtn")
    # Y9 Q8 q7 n. W% V5 H( n/ x& B3 B" J7 K1 j$ u. F1 j* {
            self.clearBtn = QtWidgets.QPushButton(Dialog)
    ) H, _% ~2 |& b/ X1 Q5 V0 L) i/ I' f7 l* h2 C
            self.clearBtn.setGeometry(QtCore.QRect(30, 560, 93, 28))9 {' z' P9 j) d
    $ u" Q" T* G' y9 q' P5 F) B
            self.clearBtn.setObjectName("clearBtn")
    * n# h6 ?  X# k& ]
    ! b+ |9 R' Z+ y        self.retranslateUi(Dialog)( L: W+ C3 U  D/ _
    0 H: T+ m$ P) T  \9 @4 R
            self.clearBtn.clicked.connect(Dialog.clearText)( H" s) n( {+ N
    7 F) T/ j2 j! h; ^, \4 u
            self.queryBtn.clicked.connect(Dialog.queryWeather)" \6 M3 }" W" Q5 i8 ?, _0 h
    5 ~( {: M2 I9 K: F
            QtCore.QMetaObject.connectSlotsByName(Dialog)
    % u# G0 P* Z0 Y2 O8 c/ w4 M; v
        def retranslateUi(self, Dialog):
      w: y: _& E6 i" p6 `1 P+ g! _8 O9 W; g
            _translate = QtCore.QCoreApplication.translate: C. o( c* r) o: a

    + E( Y7 j7 f1 }" @        Dialog.setWindowTitle(_translate("Dialog", "Dialog")), Y9 L) q. ^8 W9 Z4 R
    3 q7 I5 Q; ~0 f: m' C& z
            self.groupBox.setTitle(_translate("Dialog", "城市天气预报"))  x$ m( A; B  ]$ z

    # D' L7 m  g7 T        self.label_2.setText(_translate("Dialog", "城市"))# n0 \: {8 ]( F& Q$ U% f: Z

    7 z' a6 y, Q( o( v        self.comboBox.setItemText(0, _translate("Dialog", "北京"))
    $ t: L2 H7 f, q1 l  e
    8 m3 b" O1 I. Y0 W$ a3 t8 B        self.comboBox.setItemText(1, _translate("Dialog", "苏州"))
    ! R& ], Q/ ~8 ?( V& V& N* g+ U8 ^
    4 _8 c# z8 E# D2 i( j% S        self.comboBox.setItemText(2, _translate("Dialog", "上海")), |; m  }  L+ J6 U7 M

    % C! f: V) F3 @' d        self.queryBtn.setText(_translate("Dialog", "查询"))
    9 G& R' A$ w$ U7 j
    2 m5 K/ d; O* i" T4 V        self.clearBtn.setText(_translate("Dialog", "清空"))1 k8 }* Z5 H  w3 V, S+ ?. v
    8 |' J7 g, ^/ A0 j8 i. c
    3、调用MainDialog
    3 X( h4 L' D# I" c% b& V
    , g8 m1 b6 @  ?5 k在MainDialog中调用界面类Ui_Dialog,然后在其中中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。新增demo.py文件, 在MainDialog类中定义了两个槽函数queryWeather()和clearText(),以便在界面文件Weather.ui中定义的两个按钮(queryBtn 和clearBtn) 触发clicked 信号与这两个槽函数进行绑定。: X9 P8 }$ F/ F; W8 S
    * R4 p9 s8 V2 ^% ?) p! A; c! O
    完整代码如下:
    9 {7 B7 f: q1 }: ]  C  u1 \8 D" h4 _2 {; T0 F' I/ o2 K1 a& D4 {) X
    import sys6 k6 J7 R7 u: |& l! Z

    ; _0 g& u9 D/ _5 t$ d( X! Gimport Weather
    & r8 t7 B2 f+ E8 r$ x, o& L) p# B! \1 ^1 s' r
    from PyQt5.QtWidgets import QApplication, QDialog' d% P, n# l% @( h
    " N' _( Z0 V5 s" d) b4 n
    import requests
    / V- `  O6 `! x" [0 d
    5 L" O: }1 F# y2 l! Mclass MainDialog(QDialog):1 y# k3 Z" S, E0 e& h

    ) q' K! _. k" n7 k% l5 R    def __init__(self, parent=None):
    - Z: w% e2 I" a+ z
    2 q; d  ^) P4 e) e$ h4 l( v$ G        super(QDialog, self).__init__(parent)
    % Z! B! D2 T' `2 G# `7 e4 Y0 Z/ K% i" X0 n
            self.ui = Weather.Ui_Dialog()
    ' @5 r. U, K8 o8 O. T+ \
    1 a# R  [/ v6 T. d: l& [        self.ui.setupUi(self)
    1 `1 n) a+ g% g- [, L) b1 s8 T
    1 T! N; i$ {: ?6 O" t    def queryWeather(self):
    , ?# }0 W6 |( @. u# X1 U% O2 w/ G# W! Q6 {1 t; \, y
            cityName = self.ui.comboBox.currentText()
    : x8 |2 i# Q9 o9 V0 B* X  Z8 W) k
    & Y* M# ^- S; d, F3 F4 L        cityCode = self.getCode(cityName)2 }, ?2 u( |/ H# }* K. v

    7 J6 r0 s4 C" Z  b6 i4 u# Y        r = requests.get(: r  \2 P& T! N! I) H; }% b
    : I5 x+ D0 R2 m
                "https://restapi.amap.com/v3/weather/weatherInfo?key=f4fd5b287b6d7d51a3c60fee24e42002&city={}".format(
    " j2 B5 _6 P3 E
    ; m+ X6 A: @% `                cityCode))6 |# X" ?* ?+ {2 E$ }* P8 _: l4 m# U6 u
    & E, v4 L2 ]# L! q0 L. U; b* {1 n
            if r.status_code == 200:1 w* T) G( j; h2 q
    2 f9 p0 P6 F/ D, U3 X3 b. Z
                data = r.json()['lives'][0]
    & D1 t7 x7 y4 C0 ?1 U; n+ h5 v& q( g2 M
                weatherMsg = '城市:{}\n天气:{}\n温度:{}\n风向:{}\n风力:{}\n湿度:{}\n发布时间:{}\n'.format(! \% i# E: y6 T$ h

    9 c: i0 e( M; `) K6 g5 d1 S3 m                data['city'],
    $ A3 e* {' U" v5 `$ [0 u1 j
    ) ~& |7 T8 E- ~5 h. B, S                data['weather'],6 ~: ~! N/ p7 Q( {& {) T) L  d

    6 q* o- D* Z2 ~; x$ x) R) V                data['temperature'],
    / L; @* @2 x: `% r7 }* M) e8 C- t* d$ }8 A& l
                    data['winddirection'],5 I% q6 c/ C! a- W: ]; ~! W
    5 e( X- a  Y/ N/ C# b; D, x
                    data['windpower'],+ |  x& o4 N1 z

    8 R" ^& |7 r  A# a0 D. f' J8 v                data['humidity'],# s6 v1 u2 I, f5 Y% Y# g

    8 ]/ V& ?- v1 h8 n5 o                data['reporttime'],
    " X) s4 L8 L2 y4 g# D# B; c) j1 F+ U8 G2 B& e6 X$ H
                )
    ; R& h' |, W+ j" H" K. L; |) f- z& M+ E
            else:& f0 h5 s( ]# T$ ?6 H3 e: }

    # z0 _5 n  r$ W  m" X3 W$ B# A            weatherMsg = '天气查询失败,请稍后再试!'
    3 q+ V2 M6 n! W  M& c4 Z! w
    + C# m7 s5 Q+ Z8 ]# t        self.ui.textEdit.setText(weatherMsg)
    " X" e' r8 F( A* E
    $ i' T' n) |! v$ N  q& D- W: h4 T    def getCode(self, cityName):
    , [# K6 H. P) S$ Y8 v9 D3 q' N- N/ P9 Y
            cityDict = {"北京": "110000",
    + `( ?3 ^5 ?% Q6 T( j6 `
    1 d) Z4 Y) i5 H, u3 B/ N# u                    "苏州": "320500",
    2 h  N% ?2 F9 s4 j4 T& g- x& _; q- r; R9 T- g
                        "上海": "310000"}4 n- X& A2 |) p% m
    4 c* L# m0 o* L2 d: H) h5 ^
            **return** cityDict.get(cityName, '101010100')/ N, \) Y$ ]9 s7 V, L
    ; I5 N& |+ l2 p5 Z- \
        def clearText(self):7 j- t" ?) u* V. q9 f

    8 S% o8 [; V- Y* a  n4 _* I        self.ui.textEdit.clear()
    # U2 {, ~) k& N, Q1 C* H1 D. x6 P- j+ s0 t9 }
    if __name__ == '__main__':, W1 q3 F7 n9 r3 s) V! j# m7 ^
    ! [- o! v% I. z% \, n8 l  Q
        myapp = QApplication(sys.argv)1 |# t$ S5 l5 u5 e) m/ M
    % f: G: y1 L. ^* E, J
        myDlg = MainDialog()
    % A! _& Q% S# I$ Z4 w: H1 R
    0 L" ?9 t. L4 c+ C6 n7 }    myDlg.show()
    ' j7 X- |+ j( x9 s4 h: F8 j) y8 E8 H: _4 a$ x0 i; ?
        sys.exit(myapp.exec_())
    * |) J  k$ m! c' t# F9 r# q7 h6 w
    运行demo.py并执行查询后的效果:1 z- o& D" A/ F8 G: Q
    1 J/ x. e5 \  L& r- U, f/ W
    - q' i- j: o/ C' A

    ; }. L- ~5 }- @% U" ?# r7 x4、将代码打包成exe文件0 b, k1 L+ L6 K- R* T
    / F7 p& D  n, l3 C% `8 j# \6 L
    将.py文件打包成可执行的exe在Python中称为freezing,常用的工具有:PyInstaller, py2exe, cx_Freeze, bbfreze, py2app等。功能对比:3 f2 C' q  z7 M& w% M% Y
    8 y* \7 a! g' C  w7 n

    . F  |0 Y8 K& [/ }% C$ {2 D! I3 F: `% N& V
    py2exe:软件更新已经不活跃,因此也就略过。
    ' P, f- K0 D& Z$ g. ]# D1 ^
    7 r& U+ o( O3 x8 q6 qpyinstaller:明确支持win8、win10、理论上支持win7,,支持apple Macos, linux。pyinsaller可以打包成文件夹形式内含exe入口执行文件的形式,也可以是一个单独的exe文件。# U  s2 @) O2 |7 O+ ^' V
    , l6 h4 M8 Q  p! c2 _
    fbs:基于PyInstaller,使用起来更加方便9 x& N+ G+ y  K& Q
    * G- [- {% F4 C. h* I* ]5 o4 e  B
    这里选择了fbs来打包。fbs的安装方法:
    ; p6 H4 L6 Q0 k$ ?! x7 U4 o" n8 K: y
    " m* F4 [0 k. ]& ^pip install fbs3 {3 h( l  B4 M1 b8 f& p, H, t
    使用方法,在命令行中输入:
    3 d4 `& k* P& [7 p+ p  i9 ~3 C: Q( M9 @- L3 ?
    fbs startproject
    $ ^  c7 D6 m  v2 {执行完成后需要输入一些APP的名称等。完成后会生成如下目录:
    * `6 N4 ]4 j  e  w7 E( g( t/ X8 B/ L' K5 ]

    : N+ ?: j: a# ~9 W2 Q- F: [) w' f& l% x. |
    将刚才编写的PyQt5的代码(demo.py和Weather.py)拖到src/main/python文件夹下,删除原有的main.py,并将demo.py修改为main.py。然后打开 main.py,在文件头部添加如下代码:
    ( F: [& n  {" O  Q! f$ a9 o( s4 R0 b
    from fbs_runtime.application_context.PyQt5 import ApplicationContext; A& ?( \7 @: Z, Y
    ```; o" I; f' e! e- W
    完成后执行:8 s+ ~+ F% j" ]; @8 ~  D% z# i
    ```$ X2 X, ?. ?4 u2 z5 e5 [
    fbs freeze% `2 ]: T- j" v, N  S  {$ Q4 ~
    ```+ l* A( k( n" z$ b* \) j9 w1 H
    即可实现打包。生成的exe可执行文件在\target\MyApp文件下。1 I4 P; E$ A; }: P+ L
    9 a! p' v6 b- E" q$ ^
    ————————————————+ Y: i( A3 F% y$ [0 f+ b! q, ?! j% I
    版权声明:本文为CSDN博主「宋宋讲编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。4 l: P2 k6 t8 P, Z7 B- E" c( s
    原文链接:https://blog.csdn.net/qiqi1220/article/details/126289667+ m2 |! [+ i3 X# R/ X! o- }9 V7 _# ]. C" {

      i; F8 G" L7 [# {6 D8 ]7 N; S. c* R8 e: |; e9 |$ k  }$ F! V1 W

    # j- p+ ^: ]1 |/ ?: d% W" k# `
    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-6-14 08:14 , Processed in 0.619057 second(s), 51 queries .

    回顶部