QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2219|回复: 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使用指南!3 y+ g* K  I' s3 r; V0 z# b* R
    3 d  a8 U2 O$ ?# K% h; e, c
    使用Python开发图形界面的软件其实并不多,相对于GUI界面,可能Web方式的应用更受人欢迎。但对于像我一样对其他编程语言比如C#或WPF并不熟悉的人来说,未必不是一个好的工具。5 c+ S9 @! Y2 G! k& T+ u
    6 C7 W6 I0 H* r8 _& F
    常见GUI框架! U# w" B2 F7 b' J' z1 ~! q8 Z2 N- T
    % F: K1 n( C/ Z
    PyQt5:Qt是一个跨平台的 C++图形用户界面库。QT一度被诺基亚拥,后出售给芬兰的软件公司Digia Oyj。PyQt5是基于Digia公司Qt5的Python接口,由一组Python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。9 z$ T3 F! y8 J8 t$ \
    3 |; c  H' U% H. ?0 g( D
    Pyside6:Pyside是QT公司官方提供的Python包,上一版本为Pyside2,对应的是QT5,最新版命名规则进行了调整,更改为Pyside6,对应的是QT6版本。由于官方出品的比较看好,缺点是发布比较晚,网上的资料没有PyQt5多。0 l- C/ Z4 g3 Y/ R8 A2 ?$ o% _

    4 v+ V9 J+ E4 k9 v, s% k, S9 b6 l3 xTkinter:Python内置的GUI框架,使用TCL实现,Python中内嵌了TCL解释器,使用它的时候不用安装额外的扩展包,直接import,跨平台。不足之处在于UI布局全靠代码实现,只有15种常用部件,显示效果简陋。, d0 r% J* e4 u

    $ w7 s+ m' |3 {& K) r. r, u  B4 cPySimpleGUI:PySimpleGUI 是 Tkinter 一层包装。使用 PySimpleGUI 实现自定义 GUI 所需的代码量要比使用 Tkinter 直接编写相同的 GUI 要少得多。$ ]7 _* K* P, V" r

    # S. [0 P' U  v$ xWxPython:wxPython是Python语言对流行的wxWidgets跨平台GUI工具库的绑定。用得比较广泛,跨平台,C++编写,文档少,用户可能就需要根据编程内容对不同平台中的GUI代码做一些调整。遇到问题不好解决,代码布局控件,不直观。
    * J* T& D" o( K' u8 y& G, Z( x
    1 p: {+ r8 e- jWax:基于wxPython ,为克服wxPython的问题而制作的一个包。
    8 U/ U5 |- C- m: ~: R0 s1 V8 d: u9 @. d# ?
    Kivy:主要针对多点触控程序,智能手机平板等,也可以在没有触屏功能的系统上,全平台支持(Windows, Linux, Mac OS X, Android and iOS.)使用Python和cython编写,中文支持差,需要自己下载中文库并且制定路径。
    9 r- ]3 a. S" q' H/ v% k7 ?, O2 X+ [  }4 v1 X4 F
    BeeWare:Write once. Deploy everywhere.需要与Kivy配合使用。
    - ~& f# ]+ Q" u) G0 x' u# ~
    9 Q  R4 D5 w: y# l# ?Toga:一个使用Python开发原生APP的GUI工具包。Toga由一个具有共享接口的基础组件库组成,以简化与平台无关的GUI开发。Toga适用于Mac OS、Windows、Linux(GTK)以及Android和iOS等移动平台。
    1 g0 R: t( T- ~/ t2 S0 P$ X$ ]; y0 k& y8 V( D
    Eel:一个轻量的 Python 库,用于制作简单的类似于 Electron(但是比它更轻量) 的离线 HTML/JS GUI 应用程序,并具有对 Python 功能(capabilities)和库的完全访问权限。* t2 w' i- g0 @; h

    " o0 C4 O5 ?3 ~5 Z! BFlexx:一个纯 Python 工具包,用来创建图形化界面应用程序。其使用 Web 技术进行界面的渲染。你可以用 Flexx 来创建桌面应用,同时也可以导出一个应用到独立的 HTML 文档。因为使用纯 Python 开发,所以 Flexx 是跨平台的。只需要有 Python 和浏览器就可以运行。
    ( r: J7 H% _# `, @4 ?( f
    ( A( `9 I; x( m7 \0 f  z: L0 ypywebview是围绕 webview 组件的轻量型跨平台包装器(wrapper),它允许在其自己的本机 GUI 窗口中显示 HTML 内容。它使您可以在桌面应用程序中使用 Web 技术,同时尽最大可能隐藏使用浏览器构建GUI的事实。. K+ B2 U' F/ V8 x) C. ^7 |
      e" A# K% E0 R, C& V! D+ r
    enaml:一种能够让你用最小的努力就可以实现高质量GUI界面的的Python框架,也是一种独特的编程语言。enaml将声明性语言与基于约束的布局系统结合在一起,使用户可以轻松地定义灵活布局的UI。enaml应用程序可以在任何支持Python和Qt的平台上运行。1 p7 j! w, Q0 Q$ J) v

    $ f: b5 m% q* y1 @+ R个人想法:太多学不完,先学PyQt5,原因是资料多,学有余力再学pyside6,最后看下PySimpleGUI,看能否解决一些简单问题。
    7 r! i# D; H( N& f' S( Y2 {0 q# z& W! c) [* [$ y- k+ o
    PyQt5简介
    ) L4 D6 ?5 {  v* u$ m2 Y* \1 o/ j+ f6 V8 B# W7 @
    PyQt是Qt框架的Python语言实现,由Riverbank Computing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件,因此PyQt的API接口与Qt的API接口很接近,但PyQt不再使用QMake系统和Q_OBJECT宏。9 Q0 H. a7 R  N! O  K' D1 |2 F
    % G! A& ]. k% i; p
    PyQt5提供GPL版和商业版证书,自由开发者可以使用免费的GPL许可,如果需要将PyQt用于商业应用,则必须购买商业许可。' R& {. F( _( S# e8 R" z# T2 N

    , g+ Z. W$ F  N4 C7 VPyQt5特性如下:
    5 }; Z# p3 o# }. C6 u$ l
    - H$ ^8 i) n3 I$ _5 w/ X- j基于高性能的Qt的GUI控件集。
    . l2 _& ~1 i" Y: h% a: q6 h# M2 J  D# t- F
    能够跨平台运行在Linux、Window和Mac OS系统上。
    $ ?! q) r1 w2 n* M8 q& B. _' x5 d- m$ y- [- f/ a! h
    使用信号槽机制进行通信。9 g8 o, n% Z% I. @

    7 P  L. v8 b8 U; U5 _! u& T对Qt库进行完全封装。
    / @& o7 n: ~* Y/ a
    & G* d; L' |; Y  j可以使用成熟的IDE进行界面设计,并自动生成可执行的Python代码。" J' v/ @) j. q  f) o4 c0 G) v

    1 w5 U' A6 k' G# I% S提供一整套种类齐全的窗口控件。5 \6 b2 g* a  k7 }" l5 U
    & q6 |5 d0 j# U+ U
    PyQt5是由一系列Python模块组成,有超过620个类,6000个函数和方法,主要模块如下:( L! d9 k1 G0 ~' @. B" _

      `! t, D7 J( `# M( V3 V/ rQtCore:包含了核心的非 GUI 的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime 类文件、进程与线程一起使用。
    4 v9 B# Y9 f2 w. ?+ E( ]5 l  y9 C: O% B! H/ y
    QtGui:包含了窗口系统、事件处理、2D 图像、基本绘画、字体和文字类。; ]' X7 }) F& x( g

    3 `( V  @* S5 {' DQtWidgets:包含了一系列创建桌面应用的 UI 元素。6 t7 E1 A% b" s; t4 `+ L# R

    1 E  l( i. z: M! SQtMultimedia:包含了处理多媒体的内容和调用摄像头 API 的类。
    3 k. M& X/ ^: L6 \4 O& W3 {/ m7 g: l
    QtBluetooth:包含了查找和连接蓝牙的类。' p' Z. ~5 A5 R6 |, p7 j
    - ~* [/ T6 S  @; ?. g
    QtNetwork:包含了网络编程的类,这些工具能让 TCP/IP 和 UDP 开发变得更加方便和可靠。7 W  h5 {0 V6 _$ R' d  |5 F; x
    + D6 S5 ~" q/ B& g3 ~; g
    QtPositioning:包含了定位的类,可以使用卫星、WiFi 甚至文本。
    0 @6 @- M& u4 k! _6 o- ?& w
    + k) b5 H+ C5 d' t/ ~2 L; HEnginio:包含了通过客户端进入和管理 Qt Cloud 的类。
    ( c& D1 a4 P4 }5 M7 }$ U8 n0 y. ?3 X, X# g
    QtWebSockets:包含了 WebSocket 协议的类。# w* a* K) N" X) p1 U8 K/ t

    9 |& d$ {+ D) s2 K8 o; u! ~2 lQtWebKit:包含了一个基 WebKit2 的 web 浏览器。& N4 ?3 f- b! j! q6 N4 i
    9 p* A, C2 N5 A! J. m9 l
    QtWebKitWidgets:包含了基于 QtWidgets 的 WebKit1 的类。
    4 N4 ~9 A& `4 n
    : z  r: \4 q% O5 W7 WQtXml:包含了处理 xml 的类,提供了 SAX 和 DOM API 的工具。3 s/ \9 B. V2 w1 Q
    # e, g9 Y4 ~' M
    QtSvg:提供了显示 SVG 内容的类,Scalable Vector Graphics (SVG) 是一种是一种基于可扩展标记语言 (XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。
    0 t* E4 n0 ?6 P6 v: o7 @+ R* o
    3 W0 L+ J( K' s' \. M/ fQtSql:提供了处理数据库的工具。
    4 L- j. u) j2 E- w+ C2 @
    , Y" q9 b6 F  t: BQtTest:提供了测试 PyQt5 应用的工具。
    ( L& w) Q3 N- W& v5 W  G! s) v* a/ d) |- F) A! f
    PyQt5的安装8 I- W* k9 }: f% d+ m( y, E. p* }

    * R. i9 z( e4 V: f8 V由于后期要使用fbs进行打包,fbs对Python 3.7以后的版本可能存在兼容问题,所以我选择了Python 3.6.8进行了整个环境的搭建。主要内容为:Python + PyCharm + PyQt5
    9 X$ d, Q" M2 K' D1 j* w0 F8 G' M. o& r! z& R) Y+ P
    安装PyQt52 o, p" G/ L/ x0 B

    $ N" o( v& ?4 E7 i) I- N  l& rpip install pyqt5
    % Y9 t7 O6 A, c/ C
    6 P1 A# U- b' h$ Upip install pyqt5-tools
    * Q# s, a6 ~: Q" J( y* c其中pyqt5-tools为Qt Designer拖拽式的界面设计工具。安装过程中可能会报如下错误:6 I9 l) ~7 I/ f9 R' P
    + N& Y2 t3 ~# a9 p# x1 J% c: @
    qt5-tools 5.15.2.1.2 has requirement click~=7.0, but you'll have click 8.0.1 which is incompatible.
    * _3 X$ t' T2 h, X  f7 j1 [% K解决方案:9 \) R; L7 v; m) b2 Q, [8 L, f
    # Y; N' _5 x# J8 n8 E" D
    pip install click~=7.0
    . X+ |- n3 o4 [3 \Qt Designer的配置  l: n: ]7 z& }' R% }( G* C- |0 g
    ' }' s& a5 L3 D% k& j  ?
    Qt Designer 是通过拖拽的方式放置控件,并实时查看控件效果进行快速UI设计。0 W. X! o# e, x2 \# N) p% f  _, ?' z
    8 M- }+ S" h! e0 G* N7 `
    , y* e7 {' ]2 B' J. Y' K& \

    . }7 }, ]) q6 W整个画面的构成:8 h% Y* U" F% E' d+ W' [, h& S

    * c9 M3 i. _( g0 o$ u左侧的“Widget Box”就是各种可以自由拖动的组件7 {, a3 S5 m3 q2 m3 P

    % B- k" o6 X. H* n% f2 I中间的“MainWindow – untitled”窗体就是画布
    7 P* X! t2 g( n3 n+ W
    5 b2 m9 @( h) ~3 z/ {右上方的”Object Inspector”可以查看当前ui的结构
    . \6 P  P4 m7 {0 Z! m
    2 G5 I3 N& j) y右侧中部的”Property Editor”可以设置当前选中组件的属性
    1 F: f4 Y7 \: P; T8 j: r+ y+ Z# h' ]0 z. g% _- H5 C
    右下方的”Resource Browser”可以添加各种素材,比如图片,背景等等
    ; ?: t' _7 x) {/ ?, X$ _# N$ a0 w/ d2 ^4 ~
    最终生成.ui文件(实质上是XML格式的文件),可直接使用,也可以通过pyuic5工具转换成.py文件。
    3 w+ x$ K9 ~  P. C
    - b/ O" D4 p; _1 f$ \! r4 ]4 {2 l* QQtDisigner配置
    ; a4 q! x1 e7 ]8 N7 T/ O
    / R5 P! x/ `% |% q在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:- s. X0 ^, v4 b, @9 t! n
    - K' k; h4 k3 j+ ^
    Name: QtDisigner
    , f2 y' g  w) q$ g/ M/ \
    0 Y2 z, Y6 t0 dProgram : D:\Program Files\Python36\Lib\site-packages\qt5_applications\Qt\bin\designer.exe # 请根据实际修改
    % Z' S) M: k, H1 }
    . d3 f$ {% L5 b5 U8 bWorking directory: $FileDir$0 {  ]9 h' G" t  l% ]
    PyUIC配置
    7 h3 L6 W0 n6 n; H" x+ A8 m6 B9 |9 @& X4 f7 P. C
    PyUIC主要是把Qt Designer生成的.ui文件换成.py文件。
    ) ?6 r4 Q! w7 _( m- M" x1 N' K: ~5 B' R8 w# |' [3 |: F3 g& _
    在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:- {& X7 e# P. Y* D; L
    & x/ \: X+ Z6 \' e& Q" f2 u( X
    Name: PyUIC4 O# I- F$ ~' _" W

    " K$ l1 y( |+ _2 K% x. ^& i0 f2 pProgram : D:\Program Files\Python36\python.exe # 当前Python目录,请根据实际修改! Z+ R7 t" b, l. N
    3 L- e6 p' A+ }) ^1 p
    Arguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py7 e# G( B. t; l- y
    7 Z7 Y' u8 ]/ i& N& E
    Working directory: $FileDir$0 }6 J8 o2 ?; [" R
    PyRCC配置
    9 S1 `# z! {/ b" ]. \9 Q/ \, T& D  G: g- Q' x. e
    PyRCC主要是把编写的.qrc资源文件换成.py文件。在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    , e! _/ |! g- V; ]6 j" `( \
    $ P( g9 }5 Y) e, Q% OName: PyRCC1 T  p4 n  D! Y. [/ v- V- H
    0 ~4 u8 B4 l' s; Q
    Program: D:\Program Files\Python36\pyrcc5.exe # 当前rcc工具目录,请根据实际修改
    , d/ t- H5 D0 X7 H  C+ L( t: ?! i8 i4 [5 w! h. t# _! E. ~
    Arguments: $FileName$ -o $FileNameWithoutExtension$_rc.py
    $ A' ^% ^: Q5 l6 ]  I, q9 @( w2 _3 Z- I' i7 G* i: v, @, @
    Working directory: $FileDir$
    1 m, E$ i9 b/ V! W% JPyQt5使用示例! P& H" a$ k! |4 d+ R0 F% O* }; B

    ' q  ]+ Z7 p3 \* Q6 A* L9 E创建一个空白的界面:. ~" k( U  r+ k# C: O" v
    / h/ F2 I9 R: [7 j# ~3 Q
    import sys8 p5 [* m/ z$ x& H

      [2 u  x6 T' n. Y, [/ \from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel0 D# o% z/ F+ N8 w4 i
    5 Z9 [" a! W5 J/ ~; x3 n
    app = QApplication(sys.argv)
    , G5 W. O9 q, M  r
      P9 I2 I. }$ a1 m( C/ I- @win = QMainWindow(). l& I6 e4 J1 k+ }9 T

    6 l3 `2 Z, Q" D4 l7 qwin.setGeometry(400, 400, 400, 300)
    / Q( h, W5 p/ A4 K& ]0 [' k0 o7 l) Y9 Y1 ^4 V; C' Z
    win.setWindowTitle("Pyqt5 Tutorial")
    ( s! r* n% ]# O! f* C/ _: u/ Z% Y4 p# h% Q% _0 P5 ^
    win.show()% f, y7 A. N) m2 [& q: {

    4 E( T7 |" ~9 k7 }' |& [sys.exit(app.exec_())
    # W: g! d& }' W# u5 m5 A
    $ m9 Z9 g. O3 x3 m, u- F
    ' t! C( [0 }) ^/ a
    5 b+ X  P" O( K/ z' w5 A: w6 u其中:- }1 P" a1 _0 u) ~: k; z! l
    . e1 r9 O2 Y) W7 y! i2 ^" F
    Qapplication():每个GUI都必须包含一个Qapplication,argv表示获取命令行参数,如果不用获取,则可以使用[]代替。
    4 L3 E1 N) N3 C  [1 A+ X  L  A3 U' b3 g  [: D/ {8 h
    QMainWindow():类似一个容器(窗口)用来包含按钮、文本、输入框等widgets。arg标识可以获取命令行执行时的参数。- p( N! P2 ?" e3 O. I

    ; [5 E: n, l* |* t: m! x' USetGeometry是用来定义 QMainWindow() 窗口的尺寸, 语法:setGeometry(x, y, width, height ),其中x,y为屏幕上的坐标点。
    $ L0 O+ B% n3 f. A/ x) P2 b3 o3 b& \$ a- H" e9 f7 Z6 t8 E
    show():用来显示窗口! E! r( a6 C3 O; }& {0 f# d

    - g/ Y+ S% T0 Y+ `) @exit(app.exec_()):设置窗口一直运行指导使用关闭按钮进行关闭+ U2 O% ~8 l8 E* C+ e( a
    8 K. Y5 _6 N7 z$ i' R
    PyQt5支持的常见Widgets有:
    6 ~+ \6 [, ?6 v' o" d
    9 t1 ~9 B6 Z" y. g& c. q) Y" O& Z. t8 e- P% U/ }

    4 n' N5 G* r3 i从上到下,从左到右依次为:Qlabel、QcomboBox、QcheckBox、QradioButton、QpushButton、QtableWidget、QlineEdit、Qslider、QProgressBar8 n% m3 C" m( |+ o- E7 k

    $ C2 i2 O, a" ~# H* F* B8 [( m对于使用Pyqt5设置文本内容,我们使用Qlabel:; x* e$ K- V" N% {1 d& l

    0 Y  _% }  n9 I. s5 x. `6 Timport sys( d+ g  }+ a( c& b4 \0 V

    6 H- i- P7 ~7 T" qfrom PyQt5.QtWidgets import QApplication, QMainWindow, QLabel9 z& T+ x, d0 l2 P5 B/ B% E  J  x. Y  u
    7 _" @4 N7 i/ y; c; Y5 e$ h
    app = QApplication(sys.argv)
    0 E* Q) d5 j' V( R: k: M
    2 s) Z5 h$ u: v( x0 _( V8 @win = QMainWindow()& @, h6 y' `2 t

    6 Y7 \8 e8 u; T+ v( `, G' Awin.setGeometry(400, 400, 400, 300)# e; _) n7 U0 `; v0 n  D
    . J' {4 u; N5 [  q4 P; m
    win.setWindowTitle("Pyqt5 Tutorial")! W  U6 n# I* v; ?$ e+ |
    # i* W) Y4 k1 S. a5 z* u
    \# Label Text9 k# N4 @( v0 t, @7 w2 X# s, z
    6 v. ?2 Z: v5 K: J9 P- V
    label = QLabel(win)+ H: g/ z: a5 }6 @! O: p
    , w  C: ~! B3 |+ f9 B( O9 S
    label.resize(200, 100)
    5 m7 h" Q" x+ D0 ?+ {3 b; z! }$ r- x+ j0 d7 Y% `
    label.setText("Hi this is Pyqt5")5 G! O/ r7 e6 S/ W# [( r

    0 x) T( J/ P3 I" m& zlabel.move(100, 100)  Z) Q' {5 ~4 L

    0 j' h3 i0 c1 N0 D# V' C( Rwin.show(), r2 ^- u* i: @/ Q+ n$ N, n

    - o6 v) r/ h6 l0 u) F% ^2 esys.exit(app.exec_())
    9 E# \1 m1 e$ x% I% l' m9 `$ `% f: ]+ v8 }6 o0 M9 |
    1 B( X( e3 j( D& @

    0 @0 G, R5 I0 m5 J5 I按钮与事件:
    ; d4 k  C3 F% {7 I8 j8 ~
    # X6 D, g7 d; E( Himport sys' ]/ n3 w6 z; p$ A- Y4 `' H
    + b. A7 Q( @; e. B, g5 z
    from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
    + b2 F/ U7 I0 T: _( A! @0 t
    # B2 X- f5 p: fdef click():2 u8 J4 y1 ]4 s5 y9 q" T3 y

    ( I7 Z" h, f/ N. D; j  ~+ O, g5 l% x    print("Hy Button is clicked!")) j) e" d& V( {* V

    0 g8 W$ L. r9 O3 {9 C" ^6 |  J3 ?app = QApplication(sys.argv)4 c& h8 Q0 n9 K
    # q! m6 L& F5 v
    win = QMainWindow()
    5 ~+ W$ X' u6 V8 x" G$ ]. ^6 c& o0 W. n$ p' g9 r( b; Z8 f
    win.setGeometry(400, 400, 400, 300)$ b7 t, j0 d" K4 B+ d% H
    # ?' w) C4 {6 B* |1 t
    win.setWindowTitle("Pyqt5 Tutorial")' R8 ?# y9 Q( p# y: L

    ; w' i  e8 e# |+ V\# Button3 p0 u( J+ {$ Q1 Q( Y/ ^
    3 F; K! j5 G0 l. _  |5 d
    button = QPushButton(win)
    ! d9 r4 C8 C  u, T; e( b" W7 _# i( X' a/ g
    button.resize(200, 100)3 w/ v9 T7 v0 \1 b* ?

      l3 L& G0 K  e" S3 nbutton.setText("Hi! Click Me")
    , o' h  L! y0 x+ g( r
    $ e7 ]6 }/ n* hbutton.move(100, 100)4 G9 S, N1 X3 P$ s
    3 n0 ^2 p' U3 I% ?! A8 x
    button.clicked.connect(click)
    , P9 U- \5 u  q% N% |
    . R. w4 G% O. jwin.show()
    % Z# c0 c& ?8 Z0 a* H# L% m9 t* ]( ^* V8 T* w0 x7 w$ f# H
    sys.exit(app.exec_())
    6 k$ n& A: V" y9 o3 V1 ?/ B! H5 g$ F% i) }
    # D; R* y8 Q8 O: c: J
    4 E5 j4 n, ^1 v
    button.clicked.connect() 在按钮点击后执行特定的事件。) p9 A6 {5 @& s! f

    ! W- ~% s( ~1 \( {# nPyQt5实战
    ( E8 _! {. e( ~+ f" w' x
    - l) |. X2 B1 t3 h" y8 x* f实战项目:简易的天气查询软件
    : E- h8 M7 a) H5 g
    + V9 \! h$ @7 E( ^9 W4 \' k3 N; g1、使用Qt Designer设计一个界面( P# s. h, g; D. K  h( Q
    9 b4 ^+ _8 k' R( d6 @' {
    & c' F7 B. v7 v5 I9 Q

    4 ?8 o2 l+ B% ~2 K1 i用到的控件有Button, GroupBox, Label,ComboBox,TextEdit,同时定义了两个按钮queryBtn及clearBtn,分别用来查询及清空天气数据。我们需要绑定槽函数,方法如下:. |# T" [6 O1 w) ^' x  R5 ~

    6 p1 w$ E" }' h' b& x) M3 ~在Qt Designer右下角选择 信号/槽编辑器,点击+号新增1 E; N( F  P, M

    ; k5 M- ?  l1 ^" _1 p7 ^6 {) D* I分别选择queryBtn及clearBtn,选择信号 clicked(), 接收者 Dialog 及槽 accept(),(槽函数这里不知道如何定义,后期在代码里再进行修改). w  X1 o8 z  o4 N! r+ G, F) ]7 c! o+ s  x

    % B  Q" p* `# _3 F% X7 ]* }1 s% D以上完成后保存为Weather.ui文件。4 c, h$ d9 z4 S1 t2 @- U/ e$ J3 t" A
    , z% I2 C) ?; f0 o- P6 e  M1 D
    2、转换.ui文件为.py文件
    . l, _- y5 r( Z2 |6 K- d. W- C  I! l7 ]- D
    PyQt5支持直接使用.ui文件:
    5 _: {' f" Z) O# U3 J! L( v' a
    " b/ x: A9 M8 S( R% X) B8 J$ [import sys$ j" l  d( q7 _/ }8 N

    * ?! D6 L) z: K  T/ h1 Kfrom PyQt5 import QtWidgets, uic, n+ r5 c" i3 n1 H+ a3 g/ R
    & {; U* M1 q0 f* M& \& |
    app = QtWidgets.QApplication(sys.argv)
    9 w% m$ ^' w' I% B* ?* d0 Q7 W0 |# r+ b9 k
    window = uic.loadUi("mainwindow.ui")" {0 b/ Q% w' p8 u' \  [( L
    ) k7 b0 h8 Y2 w% A, g9 f, r7 |
    window.show()
    1 d8 W# I* I8 q5 o3 P; _% C& p5 @- d$ ?2 W% n0 L
    app.exec()1 b+ P& u8 n5 a% x; d9 z
    但是为了更好的自定义及修改上面的槽函数,可以使用External Tools – PyUIC,即可生成Weather.py,实际运行命令如下:
    3 v% x5 ^/ R& }) e$ W' t6 t8 c& L; q- N. ~
    D:\Program Files\Python36\python.exe -m PyQt5.uic.pyuic Weather.ui -o Weather.py
    % x$ d6 ~3 N" q7 a: j" |& v  m( L+ e+ ~其中,我们需要把两个按钮绑定的槽函数:2 y! _, p$ O( `# |7 r7 p, _* p' ]
    ' u3 d" ^9 X; M' d7 }# |) T
    \# self.queryBtn.clicked.connect(Dialog.accept)
    6 J) M% L) s, P+ ]4 t. q
    5 K& p9 @& ]' \9 \, B. A\# self.clearBtn.clicked.connect(Dialog.accept)
    ) i+ U- B3 a  D/ b* _. f' c9 k3 G6 H3 r$ o9 F% F
    \# 修改为:
    8 a1 U7 a, c; j2 R' s( L3 K% c+ _; d7 z2 B- |$ ~
    self.queryBtn.clicked.connect(Dialog.queryWeather)7 w& R: X" @" Y" E
    1 u4 J  ?1 k1 c  h  t
    self.clearBtn.clicked.connect(Dialog.clearText)) G9 j3 I/ [0 a0 z& f1 \
    最终的Weather.py内容如下:
    9 L. U. M: m: k0 N
    : P% z" ]. u2 N( R2 n5 U9 A" q! ~\# -*- coding: utf-8 -*-2 Z& a  ^5 O4 I; W4 N4 z, \; x

    5 T% }; \! n- r* Q9 G* G$ [\# Form implementation generated from reading ui file 'Weather.ui'5 U7 }4 @0 C* ~  Z/ ?2 z
    " i! ^7 P7 o* w
    \#
    3 w  P0 {3 ~! L3 E$ N1 E8 r
    3 F% T4 Q7 z/ t  O0 M\# Created by: PyQt5 UI code generator 5.15.4
    + X5 b, W; i/ g3 l0 G0 Z" t. A& d- [  K+ a& t1 c
    \#+ ~- [, k. h" q3 q: v, B1 z
    2 F" J% X: B' w3 p8 B6 H7 f$ z
    \# WARNING: Any manual changes made to this file will be lost when pyuic5 is4 [) {  t, Q- r9 d9 x0 t: p
    4 U: l; A0 b5 h8 a1 ~3 k
    \# run again.  Do not edit this file unless you know what you are doing.
    / e: K$ p( i! f1 F) U! J7 H
    % p, ]  `! z' tfrom PyQt5 import QtCore, QtGui, QtWidgets* n" M: u4 Q1 V, |

    9 m" M+ P. @& J1 ^  dclass Ui_Dialog(object):' r6 d  M1 Y: N+ T( a0 F; ]& N
    3 U4 \6 ]4 ~9 m! r% d2 k
        def setupUi(self, Dialog):
    9 z  D1 T# i! k, E- o& o# x' e" D- n- H; t
            Dialog.setObjectName("Dialog")0 J9 Y+ N( a! u4 W) s4 O9 E

    6 U  T, b  B$ B7 ^" X% `" V        Dialog.resize(600, 600)
    ( b" {3 ]: u$ D4 k' Q" p" z
    ( m7 Y( V$ p' `3 G) K. T        self.groupBox = QtWidgets.QGroupBox(Dialog)
    ' _" R! z4 ]/ j! I  ^* K: R6 u  a0 O7 B8 P$ u
            self.groupBox.setGeometry(QtCore.QRect(30, 20, 551, 511))1 Q# t+ c* h$ t8 a" G
    4 I7 P; R  C3 p" h
            self.groupBox.setObjectName("groupBox")  s1 b! ]* V0 A: }

    $ C8 n, w. r; `. c        self.label_2 = QtWidgets.QLabel(self.groupBox)0 b! K( g: u) C/ m- r, N/ g

    , G* x8 B& N) }3 N* l        self.label_2.setGeometry(QtCore.QRect(20, 30, 31, 16))
    ! I' D% i6 o7 ^) L3 a( }6 P" C1 z  l- _& T. Z/ U7 O
            self.label_2.setObjectName("label_2")+ k; l- T, P! M$ v- C: c7 x

    0 @) s" T1 a" \5 \" a$ B        self.comboBox = QtWidgets.QComboBox(self.groupBox)
    ( S1 H! h8 q2 ]) d0 H( R) V4 o! M) M% Y; }
            self.comboBox.setGeometry(QtCore.QRect(70, 30, 87, 22))
    * p5 F* L" F: y# y& Y9 \  N; K* T2 w$ ~: {6 M. k
            self.comboBox.setObjectName("comboBox")
    0 O9 w* ]/ q: W' e: h9 {( u
    # e1 Z6 \; L- R8 z        self.comboBox.addItem("")
    $ O7 d; Q8 k) {8 o& |3 t  p; d; F4 j2 ~
            self.comboBox.addItem(""). d$ m0 R+ l% N+ s; O, Y* v
    ! m! v3 r* @- F
            self.comboBox.addItem("")
    ' k$ F: v* p$ U$ p! M1 y$ n' P5 m* f6 c, K) y" C5 Y" |5 Y
            self.textEdit = QtWidgets.QTextEdit(self.groupBox)) B- {" [. U! P0 h
    1 a- |# t5 k7 M4 \0 a4 H
            self.textEdit.setGeometry(QtCore.QRect(20, 70, 491, 411))
    1 ?3 c! [+ s6 v- Y! D) M1 ?3 T0 g2 R- W
            self.textEdit.setObjectName("textEdit")
    $ O$ g7 c+ f8 M  [7 Y9 D" u
    ) |' K6 M: b% n' W* Q0 `6 O        self.queryBtn = QtWidgets.QPushButton(Dialog)$ |, X; t; f3 u2 f, ~0 o- a" F) _+ x

    - ^; |! B0 k0 v# W& O        self.queryBtn.setGeometry(QtCore.QRect(490, 560, 93, 28))/ _' I) U/ Y2 l! l9 }- u/ J# k

    + R! ^0 _. T9 a. x  x5 p, [9 @        self.queryBtn.setObjectName("queryBtn")
    % w7 _9 N6 x8 _. Z* O4 x1 U6 I) h$ W& m; f: d) e
            self.clearBtn = QtWidgets.QPushButton(Dialog)
    # ]- J- d2 l9 U2 G. l9 u5 R$ U6 n# k0 V. i! \
            self.clearBtn.setGeometry(QtCore.QRect(30, 560, 93, 28))& J: C: ?- Y3 [: v. C+ }: k. K6 y
    . l  m- {4 v$ b1 ]
            self.clearBtn.setObjectName("clearBtn")' }+ ?2 Q% K4 p5 a* _) z

    * h$ P( x5 ^& n3 a        self.retranslateUi(Dialog)# L. P5 k5 P) ~( `. Y
    ) _5 V; f, |; Y: W/ n8 h
            self.clearBtn.clicked.connect(Dialog.clearText). G4 I. C6 c8 C% f% R% I4 A
    + |! x' G' g2 L+ A
            self.queryBtn.clicked.connect(Dialog.queryWeather)! g  Q/ s: c, f6 ?# ~& e+ n

    8 K; M/ G- l# d8 B! b+ O        QtCore.QMetaObject.connectSlotsByName(Dialog)7 s, s/ i6 r" V& H$ c* E

    & W: |+ \! Y" ^7 B& Y, P: u# }4 S" ]    def retranslateUi(self, Dialog):
    3 ?5 y% e! C  n( U
    & ~9 k% Z% x! f) A, r, J8 L        _translate = QtCore.QCoreApplication.translate* I) t& J" r& z$ d4 W

    4 i( X9 b0 M4 {- U5 Z        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))& ]( W- E, @( E! [/ K/ Q: I5 ~& j

    - z% P$ ?& H. m7 B: z+ b1 T        self.groupBox.setTitle(_translate("Dialog", "城市天气预报"))9 q9 t" S7 G) ^4 ~+ s$ o

    * a9 }+ h7 D! K  v        self.label_2.setText(_translate("Dialog", "城市"))
      |/ i8 u) Q# t8 ]! n; A( T2 Y8 }5 S# X* p- j6 A
            self.comboBox.setItemText(0, _translate("Dialog", "北京"))$ D) l" b8 v- e/ K( p+ }
    ' t- F/ N$ H2 t- P0 F
            self.comboBox.setItemText(1, _translate("Dialog", "苏州")); W; H5 j& D- d( h5 i

    ( j/ A% p, h, R$ q, D        self.comboBox.setItemText(2, _translate("Dialog", "上海"))
    7 x2 p. ]3 y' \! j8 f
    5 F8 m7 Y7 Q, E! B9 s4 ^        self.queryBtn.setText(_translate("Dialog", "查询"))6 d2 K; s$ V6 z+ z1 D
    4 Z4 u+ d" N6 B/ |9 @2 b, I
            self.clearBtn.setText(_translate("Dialog", "清空"))
    - c, }, A; J' R- {" }8 ^% p0 P' g# }) C  n% @( i0 m6 R. Z1 T
    3、调用MainDialog7 E( @$ X3 D/ f& D! J5 {. V9 c

    8 I5 F" h+ Y) }  \在MainDialog中调用界面类Ui_Dialog,然后在其中中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。新增demo.py文件, 在MainDialog类中定义了两个槽函数queryWeather()和clearText(),以便在界面文件Weather.ui中定义的两个按钮(queryBtn 和clearBtn) 触发clicked 信号与这两个槽函数进行绑定。7 d! ^' p' {, B' x

    - R: ?1 z( a/ h) R2 i/ W2 N完整代码如下:
    # u/ ?4 T8 P6 o2 j* v0 [' ~$ c+ u9 A1 Z; k1 ]) L6 i
    import sys/ B5 M+ Z$ I- A

    5 X6 T7 N. e6 p9 w+ c1 fimport Weather0 u! q( f& S+ M7 l

    * w0 l9 Z$ @5 q5 Y6 [. `from PyQt5.QtWidgets import QApplication, QDialog; v' G! [9 Q1 T: [

    ) z1 y4 M3 }; y& himport requests- ?+ m. {% m8 r6 S5 m

    9 C7 P8 G. U1 iclass MainDialog(QDialog):/ T0 N. T$ V- ^4 K/ ?4 F  k, L- A- k
    0 ^2 G9 {# e9 M2 z
        def __init__(self, parent=None):
    " _( \6 D7 n1 m" z5 U" p, N! Y) k! R" Y7 G2 `! {. o4 ?% M
            super(QDialog, self).__init__(parent)% L9 p/ }7 E! `( t! M/ L
    4 S8 U8 S% u6 c/ O; p9 h: m
            self.ui = Weather.Ui_Dialog()
    + g* {4 {* C* `7 ?
    3 a( g7 d( u9 g+ P  F0 L& Q! E        self.ui.setupUi(self)) L9 U! j8 N2 T! ~
    " K) h1 v- G  T6 T" P
        def queryWeather(self):: o$ G+ l- y! l4 X5 j
    6 p9 c1 {4 ^6 C8 `9 o3 E
            cityName = self.ui.comboBox.currentText()
    + o2 A( J* A  g% R7 u" l1 A% h, K1 ~( z# V
            cityCode = self.getCode(cityName)0 r8 {% S) Z& {4 T
    9 X2 z% g9 d  ?- _5 o
            r = requests.get(" T  c" Y3 g" D3 Z3 i. X
    & m7 I9 \2 b9 R1 A) B  \" Q
                "https://restapi.amap.com/v3/weather/weatherInfo?key=f4fd5b287b6d7d51a3c60fee24e42002&city={}".format(
    # I9 P) @1 w  `7 Y' b+ k$ o! ?. C) U; u6 o2 F* }
                    cityCode))
    1 Y6 [- V5 p! |8 u' d
    " W/ l0 G- p4 ?+ W& g9 x        if r.status_code == 200:
    , M, I  A( f7 P. C3 K/ v& i: Y, y3 I, z2 E4 m  O- k, Q# b  o1 O
                data = r.json()['lives'][0]0 @/ `2 H9 f* @- M

    . R* x  i" k9 H! x  \6 z            weatherMsg = '城市:{}\n天气:{}\n温度:{}\n风向:{}\n风力:{}\n湿度:{}\n发布时间:{}\n'.format(
    ( z/ i; P; B! i" T
    0 I" c" M5 s* n                data['city'],  J$ i9 G+ q+ Z
    " z, [# W- X! P, E5 d  L: L8 e
                    data['weather'],6 O# @& P8 B+ _5 @6 h
    # p$ W/ x  m! J% y
                    data['temperature'],) }$ @5 [. S, C0 }+ N+ R) |" x
    9 u% q# K2 j$ d0 n" I
                    data['winddirection'],1 _' y& y& Y4 P2 g$ J, N/ I
    ' ^$ z' r0 t  g* P8 S" g
                    data['windpower'],
    $ a! `5 @  i4 H& q- Y" @
    % Z7 X/ e- O) U3 [( P+ V( B                data['humidity'],  Y, ^/ g2 W& n1 ~
    ; H) B2 X" V, x4 r/ ~$ d# G5 }
                    data['reporttime'],; M: w; n+ V* l# q5 ?
    # H4 Z9 L! E' M% k: b# P3 `$ E
                )% Y5 Z. l1 a9 d6 k: i0 a
    2 z" M- T8 {) _$ {+ t
            else:! G& Y' N, H/ u. A, z: g6 J
    7 r, T. A, ~' A; F  ]$ x* y
                weatherMsg = '天气查询失败,请稍后再试!'9 U* H, F9 i! k1 _: E" R

    - m1 N8 _+ q! ~        self.ui.textEdit.setText(weatherMsg)
    ( K6 w' C. N: y3 a0 `4 _% h& a9 t
    1 H# j$ p! M# g* M    def getCode(self, cityName):. ^2 o/ @( y) X2 l/ a+ Y' x! T% u
    4 C0 {# T7 ^( N; ?' {: x0 ~. i
            cityDict = {"北京": "110000",
    8 x. A! s& }- B' ]& B( P" m  p
    . L' l1 t( S0 H9 H( ^5 M9 w                    "苏州": "320500",5 l( S( X, @+ e' w1 b
    # ?: u+ k/ Z" ^+ f
                        "上海": "310000"}
    : }% A) {( Q0 p8 C) F3 P8 [2 z3 E: n
            **return** cityDict.get(cityName, '101010100')& \& j# B! P, }- e- L
    , v  g8 ~( ]5 }( x5 ]
        def clearText(self):6 X1 t& g) p. m  v. p9 Y7 p
    8 T# D. _, r3 ~! u
            self.ui.textEdit.clear()
    # d; u! T# s+ L
    * q( P$ i5 R' v* ^' bif __name__ == '__main__':
    ( ~6 V" s5 ?2 H( V3 \7 P& X& K. j( ^/ M
        myapp = QApplication(sys.argv)
    8 s9 g" c; g1 {, C' e. O) P2 k7 V% u  x9 p( }* V
        myDlg = MainDialog()0 s) M& D: J7 _" j2 ]7 X, l
    7 b& Q! @, `" g4 z0 f1 n
        myDlg.show()) I/ _. I, L# J! b$ j/ L# ~2 D  A
    ) v. `6 V% R1 c0 t& t
        sys.exit(myapp.exec_())
    " |& q( I4 x$ |$ `
    ' {6 h" H( j% m8 S7 N, N运行demo.py并执行查询后的效果:
      M2 q5 @" `6 `4 C9 W' s$ `2 @+ @3 ^$ d5 I5 T  w& u+ H6 f: b( j
    , C1 N% n& }, v  s
    " |& t0 v* M, m) h+ M) T
    4、将代码打包成exe文件
    6 O% N5 W. M* F; S: Z* a5 J- S
    5 Z: Z7 |! H. B: A' \! X将.py文件打包成可执行的exe在Python中称为freezing,常用的工具有:PyInstaller, py2exe, cx_Freeze, bbfreze, py2app等。功能对比:
    # I' ^. W* C; E. Q+ D4 Y
    ' A, q2 m7 i5 I% I* F* Y- J4 u& a) T; D) ~* `0 l

    0 Q% S7 e* c6 @+ H( J# E! L: p  s2 npy2exe:软件更新已经不活跃,因此也就略过。9 T" ^2 B# l. Q9 d/ Q

    5 |, f4 `; W& Q2 W& Hpyinstaller:明确支持win8、win10、理论上支持win7,,支持apple Macos, linux。pyinsaller可以打包成文件夹形式内含exe入口执行文件的形式,也可以是一个单独的exe文件。
    0 M; B/ B) _- j( V" Q2 V. b6 g9 v) J  S* t: r1 V; N! W
    fbs:基于PyInstaller,使用起来更加方便
    . p  z' F( r4 ?- G8 V  q
    5 u9 p# ^- W0 x这里选择了fbs来打包。fbs的安装方法:
    / m$ ]6 P, m' ?2 \: G5 y; x
    1 O. a! k) i. z* \pip install fbs
    ' ^( q1 f) ]1 i; O" S使用方法,在命令行中输入:( Z" w6 ^; H- r5 r6 S

    $ Q& ~% f- b/ L6 _# J. _& y! Mfbs startproject$ }6 d+ ^( Z- y3 w& f
    执行完成后需要输入一些APP的名称等。完成后会生成如下目录:
    $ }9 w! a/ f9 G5 L5 s8 }% t. I7 B% e9 D

    8 C4 W" B# M7 ]& K- R( k$ o+ E) j' R  g( t+ c8 G4 C! @7 t
    将刚才编写的PyQt5的代码(demo.py和Weather.py)拖到src/main/python文件夹下,删除原有的main.py,并将demo.py修改为main.py。然后打开 main.py,在文件头部添加如下代码:/ v, ?, S9 K2 {2 E& L0 v
    , u) ?2 n% R' N, T( k- g
    from fbs_runtime.application_context.PyQt5 import ApplicationContext
    2 E; s4 T' x" H+ h7 K# Q$ j```
    6 ^+ [# W, {1 S+ Y9 O完成后执行:
      \( a9 Y# V8 i% Z" v0 N```0 S/ C1 f+ A& U( Z
    fbs freeze7 d* c7 \1 ^$ M1 b
    ```) D+ P, m: N4 e% x: m& b
    即可实现打包。生成的exe可执行文件在\target\MyApp文件下。
    ) @! _% i- c6 k+ i8 c- R, c6 m/ {! c( E! r
    ————————————————
    0 N3 l* Z, m2 H( C( i" d* n版权声明:本文为CSDN博主「宋宋讲编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    8 o3 c0 V% X# f: [( t+ b原文链接:https://blog.csdn.net/qiqi1220/article/details/126289667
      J+ i( G- a4 v. b5 w
    ' t2 `7 z- }. q9 X1 j5 }$ X  N. e% j  V. d* E2 Q

    & I+ A- a& [( j* M" Y/ K+ m* v
    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-7-10 13:29 , Processed in 0.407611 second(s), 51 queries .

    回顶部