QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2211|回复: 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使用指南!
    , h- M4 C5 R# W0 Q! |
    . |/ A4 F) {, @5 {2 d4 \( m使用Python开发图形界面的软件其实并不多,相对于GUI界面,可能Web方式的应用更受人欢迎。但对于像我一样对其他编程语言比如C#或WPF并不熟悉的人来说,未必不是一个好的工具。
    5 T* d( h  {" Q/ @1 ?+ G
    ; G/ K9 S) H! I$ P( a常见GUI框架
    5 m& Y  X( q, k/ F: Y1 a7 _5 s" a% V: B: X+ ]2 B- X9 C
    PyQt5:Qt是一个跨平台的 C++图形用户界面库。QT一度被诺基亚拥,后出售给芬兰的软件公司Digia Oyj。PyQt5是基于Digia公司Qt5的Python接口,由一组Python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。
    0 }( Y+ b+ o3 W4 X: W3 i$ y) w; [5 O
    Pyside6:Pyside是QT公司官方提供的Python包,上一版本为Pyside2,对应的是QT5,最新版命名规则进行了调整,更改为Pyside6,对应的是QT6版本。由于官方出品的比较看好,缺点是发布比较晚,网上的资料没有PyQt5多。
    / L% ]& u0 Q. U. F& S0 _9 j  Y" e- H2 U# A
    Tkinter:Python内置的GUI框架,使用TCL实现,Python中内嵌了TCL解释器,使用它的时候不用安装额外的扩展包,直接import,跨平台。不足之处在于UI布局全靠代码实现,只有15种常用部件,显示效果简陋。7 u; R' @5 V' D  j
    & \& n9 ?' t6 j3 T7 J
    PySimpleGUI:PySimpleGUI 是 Tkinter 一层包装。使用 PySimpleGUI 实现自定义 GUI 所需的代码量要比使用 Tkinter 直接编写相同的 GUI 要少得多。
    & w8 L; m+ v2 F& @1 I: @) T4 i0 ~6 c1 x
    WxPython:wxPython是Python语言对流行的wxWidgets跨平台GUI工具库的绑定。用得比较广泛,跨平台,C++编写,文档少,用户可能就需要根据编程内容对不同平台中的GUI代码做一些调整。遇到问题不好解决,代码布局控件,不直观。
    , o5 X1 i% }: w7 E/ g  ~0 C* X1 T/ `+ a: p& O* i
    Wax:基于wxPython ,为克服wxPython的问题而制作的一个包。7 ?, D- l% E/ _

    ! P' ~, d( x% i/ X+ ~Kivy:主要针对多点触控程序,智能手机平板等,也可以在没有触屏功能的系统上,全平台支持(Windows, Linux, Mac OS X, Android and iOS.)使用Python和cython编写,中文支持差,需要自己下载中文库并且制定路径。
    & ^! J* Q, C# g# }" ~, L
    6 {* C# e% Z. d4 D7 S7 ^BeeWare:Write once. Deploy everywhere.需要与Kivy配合使用。$ w( K5 }: o/ Y5 A* n; C
    1 V& W5 K7 k/ _
    Toga:一个使用Python开发原生APP的GUI工具包。Toga由一个具有共享接口的基础组件库组成,以简化与平台无关的GUI开发。Toga适用于Mac OS、Windows、Linux(GTK)以及Android和iOS等移动平台。
    ; _8 j- u/ l. i' V6 g1 i' q! m( S
    3 m! V3 ~1 Z, k- _% WEel:一个轻量的 Python 库,用于制作简单的类似于 Electron(但是比它更轻量) 的离线 HTML/JS GUI 应用程序,并具有对 Python 功能(capabilities)和库的完全访问权限。
    ; @+ Q/ A: b. |/ e4 ~: U$ r) w  Q1 S, u0 ~3 y1 w
    Flexx:一个纯 Python 工具包,用来创建图形化界面应用程序。其使用 Web 技术进行界面的渲染。你可以用 Flexx 来创建桌面应用,同时也可以导出一个应用到独立的 HTML 文档。因为使用纯 Python 开发,所以 Flexx 是跨平台的。只需要有 Python 和浏览器就可以运行。
    & h- b1 a/ @1 o5 B6 J6 ]  ]
    ; }5 s9 Z% l; G, f. M. \pywebview是围绕 webview 组件的轻量型跨平台包装器(wrapper),它允许在其自己的本机 GUI 窗口中显示 HTML 内容。它使您可以在桌面应用程序中使用 Web 技术,同时尽最大可能隐藏使用浏览器构建GUI的事实。
    1 @& z: I6 ^9 ]3 r4 ?' Q0 F4 S' o" u. r" K8 z. s$ L
    enaml:一种能够让你用最小的努力就可以实现高质量GUI界面的的Python框架,也是一种独特的编程语言。enaml将声明性语言与基于约束的布局系统结合在一起,使用户可以轻松地定义灵活布局的UI。enaml应用程序可以在任何支持Python和Qt的平台上运行。2 j0 ?6 E- k; J3 X$ Q6 O' u

    : |! o1 @/ \. l3 r/ n  l个人想法:太多学不完,先学PyQt5,原因是资料多,学有余力再学pyside6,最后看下PySimpleGUI,看能否解决一些简单问题。
    ' \6 @( H: u4 l2 \
    2 D2 z& e5 A+ M! N: z3 APyQt5简介
    9 S2 N2 [, M4 h9 w$ v+ P0 Y8 Y( v" @5 h$ j3 {: F( b, u6 _7 u2 m
    PyQt是Qt框架的Python语言实现,由Riverbank Computing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件,因此PyQt的API接口与Qt的API接口很接近,但PyQt不再使用QMake系统和Q_OBJECT宏。( l0 M, k3 T' M

    + E' E8 `, q) z- q& d( ?8 S9 |* wPyQt5提供GPL版和商业版证书,自由开发者可以使用免费的GPL许可,如果需要将PyQt用于商业应用,则必须购买商业许可。. H) S$ q+ ^+ f& V

    + S" x- c  I2 [  ?PyQt5特性如下:( K& \7 W4 l' c( K4 J
    / h' N4 Q+ }/ k
    基于高性能的Qt的GUI控件集。
    " _2 L$ H( t' T
    8 a4 \/ f0 t, d" j能够跨平台运行在Linux、Window和Mac OS系统上。
      Z5 ]; C$ ^0 d: L2 {
    8 r4 {* _0 U# s; X; ^" n使用信号槽机制进行通信。% g7 X6 ^0 M8 V9 I% U

    0 @3 O4 a/ H( M2 q: w3 d对Qt库进行完全封装。+ L, x4 e/ e9 b. v: `6 M

    % w% G  d* ]8 N; }4 q$ o. S" ~! v可以使用成熟的IDE进行界面设计,并自动生成可执行的Python代码。
    , ^' ]' z# y$ _* ]+ W7 j; ~* n; g
    6 d8 ?0 r) F# p% K提供一整套种类齐全的窗口控件。* v% Z2 C# W9 ^5 {; O* F" e5 j

    ! ~2 F# x+ g: U5 A3 z. oPyQt5是由一系列Python模块组成,有超过620个类,6000个函数和方法,主要模块如下:
    ) f" W& I0 f" {
    ' p# z0 E) \% A: ~# x7 t: r9 LQtCore:包含了核心的非 GUI 的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime 类文件、进程与线程一起使用。5 f6 Q: V% v4 a) N

    # U! Y! q( _, Y3 O) g& @QtGui:包含了窗口系统、事件处理、2D 图像、基本绘画、字体和文字类。, {3 c% F8 ~6 l, i; c: K

    4 v! m6 }' }; n) V" a, q1 _, {QtWidgets:包含了一系列创建桌面应用的 UI 元素。! i0 {! ]6 J; B1 {; ~& u: I$ ]( v

    " a$ G; h: {1 e' Q0 Y! F" D. e" m' U' jQtMultimedia:包含了处理多媒体的内容和调用摄像头 API 的类。
    7 J) s9 ^0 h4 q1 Z2 e& L8 c) t' N; I0 r0 g# x7 S; }
    QtBluetooth:包含了查找和连接蓝牙的类。
    3 \! `5 K4 e1 G- B% p
    5 s6 _) ~4 {. r) \: TQtNetwork:包含了网络编程的类,这些工具能让 TCP/IP 和 UDP 开发变得更加方便和可靠。$ W/ o) Z5 u8 u

    , K, V; S) _! y. ]QtPositioning:包含了定位的类,可以使用卫星、WiFi 甚至文本。
    2 O: k: O3 a* @, a, ]- _
    9 |% T- Z) b6 L. nEnginio:包含了通过客户端进入和管理 Qt Cloud 的类。
    ( u" U; ^  x" M# m- ]1 S9 A& |' I& \& Z& b9 k( m
    QtWebSockets:包含了 WebSocket 协议的类。
    - R4 M2 u% o- g0 O! g
    4 V6 ~$ H3 N9 a5 `$ dQtWebKit:包含了一个基 WebKit2 的 web 浏览器。
    ) D/ V# z" Q! _5 l4 w8 y+ ~% g8 i% c: l
    5 H- B6 H6 `/ M. n* n5 _QtWebKitWidgets:包含了基于 QtWidgets 的 WebKit1 的类。
    * ?  x4 y0 N% z. Z4 n# O. U! s) m" X$ S& S* s: H- {0 J
    QtXml:包含了处理 xml 的类,提供了 SAX 和 DOM API 的工具。
    0 ]) M7 l/ R+ z/ I& ?( I2 ]% r/ L( m
    , x+ @$ D8 B% PQtSvg:提供了显示 SVG 内容的类,Scalable Vector Graphics (SVG) 是一种是一种基于可扩展标记语言 (XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。
    % s: n6 s. e, ~
    1 O& N" G/ r* I! r; C, K9 ~( f2 [QtSql:提供了处理数据库的工具。
    9 O6 F/ {! o. ^1 c$ q  A
    ; z1 U9 i3 [' GQtTest:提供了测试 PyQt5 应用的工具。
    4 ?9 ~* c. C! p6 d6 W3 i+ d! I
    9 y' @9 k5 _# n$ v2 _7 Q3 mPyQt5的安装' W/ m& M# E2 {. P3 |  [6 P, A
    ) z  b- q# t  l' g- Z$ N
    由于后期要使用fbs进行打包,fbs对Python 3.7以后的版本可能存在兼容问题,所以我选择了Python 3.6.8进行了整个环境的搭建。主要内容为:Python + PyCharm + PyQt5
    ( Q8 V. `( i$ g5 W7 B6 I- t: j' b2 i5 U( R2 ^
    安装PyQt5- @' Z5 D, U: f. H' s# I1 [

    6 @$ `, `, S: y; v8 ^  v* gpip install pyqt5& R5 N8 N1 T( \4 Q* ?7 s2 j
    5 ^  j: g* y; `* ?% ~- O
    pip install pyqt5-tools
    8 l! h% Z6 i9 z0 g  w# M9 p8 g其中pyqt5-tools为Qt Designer拖拽式的界面设计工具。安装过程中可能会报如下错误:
      ~/ g. v: {9 V; m  N' T
    5 g9 `* S! C& w: [" r  T* xqt5-tools 5.15.2.1.2 has requirement click~=7.0, but you'll have click 8.0.1 which is incompatible.8 ^2 m/ b, r) {9 T) M1 R$ E/ G
    解决方案:7 {' R1 S, R( B: u
    ) Q. I( _8 b# W9 y# s. l
    pip install click~=7.0% d+ ^( j9 q. w
    Qt Designer的配置! [) ?' R5 Q+ T2 E; a5 I
    : z: H8 y( ]0 J* x
    Qt Designer 是通过拖拽的方式放置控件,并实时查看控件效果进行快速UI设计。
    / f" m, U7 `0 `; V) ]) m
    6 e+ E( S# t! F0 m1 T' b+ V8 D! _& T. ]+ \
    - c1 Y" l: i7 V/ L! N
    整个画面的构成:2 f7 D) c  O$ z- K4 q
    $ y: d0 H2 H$ w. Y. ]
    左侧的“Widget Box”就是各种可以自由拖动的组件- |! ?+ E& K% z; o4 x' F
    2 |% \! d6 o3 v# X9 i, @9 j: p& i
    中间的“MainWindow – untitled”窗体就是画布! K* c2 b$ q/ Z- J% C+ j6 G2 b2 k$ @

    8 H- I! {# J  f& m: M/ M; J右上方的”Object Inspector”可以查看当前ui的结构/ [9 M( m1 d, j  {) e6 o

    ( b! O. k8 _0 A9 M6 \右侧中部的”Property Editor”可以设置当前选中组件的属性
    7 _) p* e8 n: @9 u, x6 z; g
      l* x; c5 _/ M% |, k右下方的”Resource Browser”可以添加各种素材,比如图片,背景等等
    9 ]# _1 g6 I3 @5 H* c
    5 I9 A4 X- l: e, v& \% j% U最终生成.ui文件(实质上是XML格式的文件),可直接使用,也可以通过pyuic5工具转换成.py文件。2 l$ ~4 w; Y, {2 p: z
    , ~& v0 t# c; d$ f/ T7 P- V
    QtDisigner配置, J% ?" l1 G0 X4 V
    & t% [( y, M* T
    在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:- H) P% a4 L: R7 x

    : z$ s, [8 }2 N9 w% KName: QtDisigner& e6 a; e5 [( b8 J+ \. E8 x6 [

    ) Y2 w% i1 ^8 f# ]% r6 u6 l( cProgram : D:\Program Files\Python36\Lib\site-packages\qt5_applications\Qt\bin\designer.exe # 请根据实际修改
    , w; W6 g1 l  o9 P, k, H: a- S. n' `2 `% @, n- X
    Working directory: $FileDir$
    ! v5 G/ d5 u# |9 [6 J( vPyUIC配置' V: T9 N: x; y0 \7 |

    + F2 ?7 a" n8 Z% G& F# A) ~/ l5 ~2 |PyUIC主要是把Qt Designer生成的.ui文件换成.py文件。
    5 @7 b. Q: r' n2 K% n" j: x# B( S. l1 s
    在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:" v: n, a/ e- L3 F+ n4 L$ R/ A. ?; _9 O
    0 t2 ?/ j2 Q; o( j
    Name: PyUIC% ]1 j# f- F& C2 I

    ( G- a8 i/ J" bProgram : D:\Program Files\Python36\python.exe # 当前Python目录,请根据实际修改/ F  R1 H* K3 S- A) {

    * Z4 n" c% X3 T# ?2 W3 @Arguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py
    3 W3 ]; ]( ~# O5 I% K. M# b
    - r# G, R( f9 o# j" Y  p2 l8 y- FWorking directory: $FileDir$8 W0 o( u& d2 s& j6 K' y$ s
    PyRCC配置  v3 j& d1 S  K! _* D9 S% U% e2 R
    " [5 d- A! r8 B3 a& v4 Y$ R( A; x: Q& @
    PyRCC主要是把编写的.qrc资源文件换成.py文件。在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    0 k% u4 B9 Z/ G: i, |8 I$ C' ^# x# e
    Name: PyRCC
    0 X1 V+ f$ `9 R1 ?; i+ V2 q# ~# @: _  k7 D! t/ [# t, ]$ T
    Program: D:\Program Files\Python36\pyrcc5.exe # 当前rcc工具目录,请根据实际修改
    0 }: ?3 E) |" ?. s
    ( ~! G$ t- I6 u/ {8 b" T- {. u- [6 ]Arguments: $FileName$ -o $FileNameWithoutExtension$_rc.py, F& y. S* n% j7 X" _3 x) m: u
    ! e' E& I5 d9 ]- k5 k1 t2 y9 h( P
    Working directory: $FileDir$
    ) f0 K$ H9 L) @2 ZPyQt5使用示例. a  `; j4 J( J3 M

    5 l. y0 @3 W: l& R% Y创建一个空白的界面:
    * M* C& y9 y; \  y7 M  M5 P" a2 d0 |( Y
    ; D/ G) q6 {' x: o+ Fimport sys7 L' ^3 k+ i, a3 B
    ( J* ]( S; Z7 w% ?
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel. z0 U6 [$ }. R2 E: [0 n0 s, {# X
    ! Z! @2 M9 [3 |& Y/ r
    app = QApplication(sys.argv)
    $ ^: P, c4 v3 }, Z3 k$ k& q( W  J' Q+ X8 A' y5 @
    win = QMainWindow()
    ) x+ v1 I1 F- k  y5 l& J5 V) c3 _; E6 V5 P
    win.setGeometry(400, 400, 400, 300)
    7 p" c: I& Y4 c7 l  w9 y. q5 n/ O+ c( r3 J- q- {
    win.setWindowTitle("Pyqt5 Tutorial")
    1 u/ L- e7 Y& W. }; q
    / W# e9 A& }# Jwin.show()4 ?# h4 n- ^: l" t# B8 Z0 _3 A
    3 h3 N6 A, q+ `! v
    sys.exit(app.exec_())  S- v% u7 Z0 E4 g8 Y' k+ @' v

    3 y7 R$ L" L8 Q7 ?) c4 w2 Q; ?0 j3 a0 M0 x6 `" n
    6 `: s% p- o& K3 |  c$ @
    其中:6 ^, O2 h  u  g8 P1 f& H9 P3 n7 q
    ) T: {: Z) d2 m- \
    Qapplication():每个GUI都必须包含一个Qapplication,argv表示获取命令行参数,如果不用获取,则可以使用[]代替。5 o) f1 ?3 y- d$ V+ ?$ A

    % e9 Z+ O  _9 uQMainWindow():类似一个容器(窗口)用来包含按钮、文本、输入框等widgets。arg标识可以获取命令行执行时的参数。2 I& E9 N( g9 x# m5 p8 a: O
    4 s( F0 _) L7 g& J/ U5 B" P
    SetGeometry是用来定义 QMainWindow() 窗口的尺寸, 语法:setGeometry(x, y, width, height ),其中x,y为屏幕上的坐标点。; o4 k1 ~# Q' H% B0 x
    7 n8 m5 A6 o7 o4 _, X
    show():用来显示窗口" {0 r1 V: F! V) ^3 ^. k
    . u! E% R5 {! _) L) H6 n8 o
    exit(app.exec_()):设置窗口一直运行指导使用关闭按钮进行关闭  Q( g& D1 {0 W, y
    7 W- p/ o! [/ ]
    PyQt5支持的常见Widgets有:5 w6 C* s4 C4 `1 ^8 ?$ j
    * c; f* ^5 h) n; i2 w
    ( d7 w) ?' I# o9 X3 C
    7 p8 M( b7 ?) _0 b+ d- d8 x
    从上到下,从左到右依次为:Qlabel、QcomboBox、QcheckBox、QradioButton、QpushButton、QtableWidget、QlineEdit、Qslider、QProgressBar# [6 e4 k5 T5 c7 E% ^
    $ l6 W1 R( X+ y- _2 T0 s* f
    对于使用Pyqt5设置文本内容,我们使用Qlabel:
      K% X* a8 D& H2 E6 T
    ) {# ~& z: m$ }# }2 Iimport sys$ A: K% P* m. z, _
    / i8 B. P, A/ p! @
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
    * l& [. O. l4 L- I, e  c, G+ b' {8 j" Z3 v3 A2 G
    app = QApplication(sys.argv)7 a  x- i0 G/ ^. o; x: z7 ^! ~- ^: z
    ; S% g+ k, n' ^# i3 H
    win = QMainWindow()
    ( R6 e# h- R: y  T6 A9 k9 c) n$ c- E6 \
    win.setGeometry(400, 400, 400, 300)* @0 |6 Q6 ^5 B1 E9 B
      [6 [8 w5 J+ u
    win.setWindowTitle("Pyqt5 Tutorial")
      E; Z& D. P; `. E, T1 o
    ; o& ^) J% f7 p% d" M9 d( q\# Label Text. ?" s' h: e# Y6 q( u2 q9 u
    5 ^0 T  y3 B( B0 }( G) k: N) a
    label = QLabel(win)- c+ Q8 U0 u4 i; y4 e( z

    4 h2 c, z/ l6 L- V- B( ^/ xlabel.resize(200, 100). X2 y$ J- t) _0 {1 b/ A/ i. Z
    5 Q/ n" z1 M1 [/ G  g
    label.setText("Hi this is Pyqt5")
    5 k$ j; w0 \- z) U7 `3 N$ S' k/ P, @6 w  x
    label.move(100, 100), V6 j) }+ H' k3 Z

    " F) }6 T4 A/ zwin.show()% D7 R3 o  O" B+ B: J' P& S
    ( w" f1 u; t9 l& J* t1 z" j4 p
    sys.exit(app.exec_())6 w3 L. P! }. H. l4 e+ {1 w
      O  D2 H; k- |5 T, M7 {0 X
    4 j$ |7 L- `  t: n( O$ g+ r
    ! A: A. b3 T4 N, }7 D: C2 f8 a  V
    按钮与事件:  d& W. O; \' c- F" l6 f6 V- s
    5 `% b% S+ `9 A: H3 @
    import sys
    . X  {# k' n. j7 ]$ u1 ^5 [+ a  Y, J, F
    from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton8 H! E2 u) x$ M7 x# v
    - P9 J" k7 _% n5 e
    def click():! r; ^* j7 H& J

    " O0 \2 R' @4 p9 |" [    print("Hy Button is clicked!")# S# _( Z7 w8 l/ w4 f& ~* ?$ G# e0 {

    7 ~& u" r# @  J* m' c" happ = QApplication(sys.argv)
    , n' V7 N) L; o8 ^& D2 y3 e3 g' S- P" ~# Z5 g7 N
    win = QMainWindow()7 E+ j+ P# r3 V& W/ |

    , s5 Z& M# J! ^/ c# Gwin.setGeometry(400, 400, 400, 300)
    " x. P( b1 k# R" f2 T# u
      ^! F( S1 u& I" R# T2 bwin.setWindowTitle("Pyqt5 Tutorial")
    ' w, \& X& Y) l$ z( M6 z1 \3 I: u; V) H3 L0 X  h$ \4 y
    \# Button  V* Q' T( ^( p) [! v) F: P
    * g) G# D, N) x- t+ z
    button = QPushButton(win). T" |! ^3 ~7 n- T1 k6 f
    ' V. A& W% T- q9 f% @
    button.resize(200, 100)
    % Z0 R2 B. v9 i8 y- W
    9 ]$ ~. C' C0 j8 `; a, Pbutton.setText("Hi! Click Me")
    ) x# Z3 d0 X5 x& z) R! i$ ~2 o! G7 j! @7 ~& k
    button.move(100, 100)! x- C8 S# L' L4 ?* i0 {- y

    , I) Z! w/ a0 L2 ^button.clicked.connect(click)
    6 y/ ?' y+ n0 e5 b6 U
      K  Z. I& A4 A" G7 S$ [8 {win.show()
    ! z) r6 C6 ?7 V" Z& w9 ]
    ( J7 C1 l' c; t; ]sys.exit(app.exec_())
    + S. x  M% @* s. P& s' w) H6 \) {6 b

    ; S2 \" P0 a% ]% G4 h/ r4 p( q' y- D; c- W- h
    button.clicked.connect() 在按钮点击后执行特定的事件。
    9 C" o5 P3 _! n1 ?) s) E. ]+ }; ~+ P
    PyQt5实战
    9 x( D' G) @- M+ v
    : U1 R% V; w3 Q' T, _1 C: t实战项目:简易的天气查询软件
    ! b; P! n. y0 X' B, T/ y  d* a7 B- x1 N6 w+ D' v. r; j6 I
    1、使用Qt Designer设计一个界面
    7 G. @4 S$ A5 j: T5 u3 U7 A* h  \( u# j5 N& K
    ' b8 |0 Y, @% y/ C

    : ]. x  L# g  Z* f用到的控件有Button, GroupBox, Label,ComboBox,TextEdit,同时定义了两个按钮queryBtn及clearBtn,分别用来查询及清空天气数据。我们需要绑定槽函数,方法如下:
    9 d( k& y3 ?* M* Q0 v
    4 e5 H' u% a4 J- a8 A在Qt Designer右下角选择 信号/槽编辑器,点击+号新增! j. C) P1 _( |+ a( q# D
    2 O+ R( [+ R( I6 e. b/ @! d
    分别选择queryBtn及clearBtn,选择信号 clicked(), 接收者 Dialog 及槽 accept(),(槽函数这里不知道如何定义,后期在代码里再进行修改)
    % d( x; A# z; G' ~$ M8 ^" V9 A( v' u& v- U! Y0 C- r
    以上完成后保存为Weather.ui文件。
    : m1 V2 s8 U5 ?$ n* t6 G/ S# w* b) g+ R3 C
    2、转换.ui文件为.py文件+ f! @- ]7 D4 t% S

    9 D; a# w% p0 b4 [PyQt5支持直接使用.ui文件:3 X6 j3 S6 W5 W# ]
    7 Y+ H3 v% G& O% M) }" H# R
    import sys
    ! R6 G6 P1 @7 i- _4 w8 {) g5 P) ~8 l+ _
    from PyQt5 import QtWidgets, uic# a8 a, ~( Y; h' P

    4 a) G+ b% t: J0 B4 r6 m8 f. ]app = QtWidgets.QApplication(sys.argv)
    7 D! n! u1 _/ T  g) ~8 a' M( X7 k  j! p) J
    window = uic.loadUi("mainwindow.ui")7 r( V: \. U, J2 @5 v# M
    & {  y4 p" h; l" i& B$ y$ Y3 J
    window.show()2 ~. c+ \+ ?4 m, H& m) w3 t9 F4 p
    3 H6 u) ^' i2 [) ?
    app.exec()
    2 Y6 c1 e0 O1 X- J" v5 j1 V但是为了更好的自定义及修改上面的槽函数,可以使用External Tools – PyUIC,即可生成Weather.py,实际运行命令如下:# T1 a/ A, M3 g0 j
    6 x1 b; }/ c: j$ M
    D:\Program Files\Python36\python.exe -m PyQt5.uic.pyuic Weather.ui -o Weather.py
    3 c: M5 ^8 }& W# d6 \5 D其中,我们需要把两个按钮绑定的槽函数:
    # S" {$ B* e/ O. u; p8 f7 c# [1 ]
    . K1 O0 Q4 e9 k3 a% H+ L\# self.queryBtn.clicked.connect(Dialog.accept). ]. N7 S% Y9 @
    9 a1 j+ Y. z6 @. |3 C3 f! H0 x
    \# self.clearBtn.clicked.connect(Dialog.accept)6 g8 J2 a1 D! O- U5 g

    ! J1 }: _% R7 W1 {7 g# k\# 修改为:
    . f( Q5 V+ N1 w" S  j3 L/ c! D
    & {( a3 D- J3 z% B7 j, s* C6 oself.queryBtn.clicked.connect(Dialog.queryWeather): o9 E# ~8 g% `
    $ Q, M1 m" V5 r& q
    self.clearBtn.clicked.connect(Dialog.clearText)( ?& e4 P2 M- u) D4 O
    最终的Weather.py内容如下:  c9 q7 [$ j! j$ C- s& j8 |4 E

    2 j* U% H9 \( j6 g  V! ~$ J\# -*- coding: utf-8 -*-
    $ B0 b9 T. @6 o3 b4 E0 K& x) Z, u4 x
    \# Form implementation generated from reading ui file 'Weather.ui'; l( G. t6 s0 o

    . S* Z8 y5 m1 N4 b: z\#8 J; X, ~) t  D/ t  t7 k: B

    & @  ]* {" t5 K2 u- T$ |  G\# Created by: PyQt5 UI code generator 5.15.49 W9 U% x. h" s+ e! s/ l

    6 R/ F* m) [% J$ @# X/ B  k* g\#, w# q, W( Z6 \& u( r

    8 \! m0 w. r8 Q7 `1 U0 n! f8 G\# WARNING: Any manual changes made to this file will be lost when pyuic5 is
    ) t+ [: g9 S) _4 L9 }- t  C8 G1 V; u# q) t- \7 n# h
    \# run again.  Do not edit this file unless you know what you are doing.9 X- |& P) t- s% U& C
    5 \$ n* l) C# l5 z) R7 g1 Y( B: J
    from PyQt5 import QtCore, QtGui, QtWidgets
    ; T0 C! a; I" ]* G% {% g2 T( i* [' Z. w& k* U
    class Ui_Dialog(object):* P; `; F( ]' X% l/ P+ M7 j. c5 J

    , b7 z  M' s1 R* O  M5 y    def setupUi(self, Dialog):) U6 q1 a, ], x' k
    1 e" Y! f! b) ?, V" w3 `
            Dialog.setObjectName("Dialog")9 ?5 X2 O) V" C3 ]( E* ^) z5 o) Q# Q

    + A* {" B( I2 q9 d2 m9 d        Dialog.resize(600, 600)/ |( n, M  b2 k+ c, w" S6 l1 e! A
    ; z$ ]  M; B$ ~; |+ K9 S
            self.groupBox = QtWidgets.QGroupBox(Dialog)
    , w* G/ y8 n8 V
    7 l- X0 d& U7 t6 s5 k        self.groupBox.setGeometry(QtCore.QRect(30, 20, 551, 511)). g; T, j9 h+ U6 }6 ]& l5 P: d) Q
    / o* }) P1 O) a4 l. s$ f% C3 D1 J( H
            self.groupBox.setObjectName("groupBox"); \* K) o0 E0 O

    4 {/ ]" S9 Q$ |/ h        self.label_2 = QtWidgets.QLabel(self.groupBox)2 Z- Q3 \, s! R
    2 A. C6 z2 |( J- ~  i0 J
            self.label_2.setGeometry(QtCore.QRect(20, 30, 31, 16)): G* A0 M/ B% G3 H% Z$ X1 H& r5 v3 k
    6 Y+ `6 R% N4 d6 L
            self.label_2.setObjectName("label_2")5 D  G, `) {8 h0 O4 s
    . I1 V& `9 \0 T, w- z# t
            self.comboBox = QtWidgets.QComboBox(self.groupBox)
    0 Z9 o( e( E; o) n% x% Q, P! e2 w4 G% j( r4 ]$ b
            self.comboBox.setGeometry(QtCore.QRect(70, 30, 87, 22))
    & n' g4 J# b$ B4 x- k$ c3 Z/ T/ R. ~7 W% `
    9 _- U! H! c' |# X& l3 ^        self.comboBox.setObjectName("comboBox")
    2 M; ]3 E5 H3 w) L; `9 h) k5 c8 }$ x3 [8 {7 R# h
            self.comboBox.addItem("")
    8 v! t4 ^1 `3 }
    1 T* @, y; L- ]7 E$ a        self.comboBox.addItem(""): \' h, D: D  h7 q" P/ c% E. ?8 x
    ) q& y5 Y5 M4 m3 X$ w& C) p  f  X
            self.comboBox.addItem("")
    + G% D0 O# B6 `/ B$ ~) F2 Z( N
    + H" h6 c) o; U. `) l        self.textEdit = QtWidgets.QTextEdit(self.groupBox)# q' a/ P& P( o9 X# B( `6 J, `( \6 o
    1 x& a  [9 t, e2 Z
            self.textEdit.setGeometry(QtCore.QRect(20, 70, 491, 411))2 N/ p# A. ^, A& Q

    . T% U- n7 J3 G4 S2 ^6 S  y: w        self.textEdit.setObjectName("textEdit")7 c+ S5 k+ w% O3 ^& j8 f5 ^0 Z& k
    # Q4 o2 K1 G3 w8 A3 ~1 v4 ^
            self.queryBtn = QtWidgets.QPushButton(Dialog)2 p* {1 t' `3 h/ K6 ~
    ; x2 L! P$ S1 e
            self.queryBtn.setGeometry(QtCore.QRect(490, 560, 93, 28))
    / ~! E7 v2 |& X' ?8 @: y1 ]6 K  u+ P! b% e% z9 u1 \- \
            self.queryBtn.setObjectName("queryBtn")
    # E6 ~: f1 e. H8 F% A+ n
    . z1 p/ h: K7 Y0 N        self.clearBtn = QtWidgets.QPushButton(Dialog)
    . l" f- w( B" |' _: a% ]# s/ q- p6 H* o! k
            self.clearBtn.setGeometry(QtCore.QRect(30, 560, 93, 28))# \5 f8 J; T! F! O
    * n; \7 e7 ^1 _& B8 s; e; g9 y. X
            self.clearBtn.setObjectName("clearBtn")
    4 U7 C( C, D' O6 Y# j1 D6 h2 H1 e& ]
            self.retranslateUi(Dialog)6 G+ t" ^& ^& Q, ^
      b; ^8 ]0 }7 q) A  L# v
            self.clearBtn.clicked.connect(Dialog.clearText). [- G: q3 L' }( G3 P  T

    ( m: u  S4 I9 |2 r# [        self.queryBtn.clicked.connect(Dialog.queryWeather)* j1 f0 |$ T# \. a
    ! A4 a5 [& D, E; Z9 e6 w; k( o
            QtCore.QMetaObject.connectSlotsByName(Dialog)
    % L# o/ i9 ]/ b1 m1 c3 q. `* ~) J& J' i; @
        def retranslateUi(self, Dialog):
    8 v: I5 H" L# j! H6 E! K$ p) V% D8 M$ D8 I
            _translate = QtCore.QCoreApplication.translate1 f' G% V5 I3 F
    5 c' ^0 M  G2 V
            Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
      [0 P3 J, N8 l. ^0 s5 j
    3 f" |+ }) N5 h* J. p0 S. G8 @        self.groupBox.setTitle(_translate("Dialog", "城市天气预报"))! w; {- P+ E1 D% o  l! Z3 Z6 b. i  J: ^

    : ]& Q1 x" z8 Q        self.label_2.setText(_translate("Dialog", "城市"))
    ) M, _# a- A& b8 {: ]" l
    9 ~0 G+ ~  \: I) o        self.comboBox.setItemText(0, _translate("Dialog", "北京"))  B& {; |: |: L" O

    5 P+ [6 m4 v7 J! o3 Z        self.comboBox.setItemText(1, _translate("Dialog", "苏州"))
    ; N/ Y5 _$ _; T2 g1 s9 b6 i' ?( r! O6 }; D$ l+ Z% d
            self.comboBox.setItemText(2, _translate("Dialog", "上海"))& J' x4 D) M% _. l1 K! X
    7 {3 q1 [* _+ H5 C
            self.queryBtn.setText(_translate("Dialog", "查询"))  n5 f) s1 |: e% @* ]
    5 i) B5 s: |) m. o5 g# ]4 C
            self.clearBtn.setText(_translate("Dialog", "清空"))" u3 f: M6 N3 A+ [, W
    " s2 Y  E' F& b9 e3 }
    3、调用MainDialog
    ( c% m8 K/ U; D% i- Q" p
    ' l6 {3 _7 e7 ?" K+ Y6 @在MainDialog中调用界面类Ui_Dialog,然后在其中中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。新增demo.py文件, 在MainDialog类中定义了两个槽函数queryWeather()和clearText(),以便在界面文件Weather.ui中定义的两个按钮(queryBtn 和clearBtn) 触发clicked 信号与这两个槽函数进行绑定。; d; X* I2 r& q+ i/ Q( C
    2 f- b$ P% @  V+ f0 D. S
    完整代码如下:
    0 s4 y9 U* V. n: N- s, T' z9 i" Z8 Y3 Y% B: v
    import sys
    ( m* E9 H0 k5 E& }3 N1 Z4 g; g5 p. p0 g# x
    import Weather0 S$ N# }& \# N+ K9 f
    & @& _/ Q. K' {' @8 o
    from PyQt5.QtWidgets import QApplication, QDialog8 h& |' U' l1 p! n
    9 Q+ @3 r9 X7 ~$ ]7 S( O
    import requests
    + }4 J5 k- \4 [! Y- ~
    % J* |+ `3 s) |( x, t+ Z5 kclass MainDialog(QDialog):2 L6 j" f, e" m. \

    # z2 N4 V$ y# Q7 |; w6 w( }# u    def __init__(self, parent=None):9 Q/ L/ {( h/ t3 f8 b# e6 f) a
    1 T- v' E# R% G5 U  K
            super(QDialog, self).__init__(parent)8 R2 i) ~! y: o: C' B1 n/ t3 K
      F8 y  v# ^% v) ]' \
            self.ui = Weather.Ui_Dialog()
    - m: j) N! Y' T0 i& |
    + [  A, {, U3 K% g+ Z        self.ui.setupUi(self)( C+ @+ @& T  I7 M; p

    1 h% C1 r- ^- `: }! Z7 r    def queryWeather(self):
    . `6 P. R. n' y5 y* C2 G% w- r- c3 P; n& s8 V& G5 R
            cityName = self.ui.comboBox.currentText()
    ! R" A/ D" `& E8 Q* Z6 L& a6 J, w( d8 Z: c* w# r/ L' H% E
            cityCode = self.getCode(cityName)4 S$ Q, M; n) q

      M  p: Z: u+ n# q' q) _- q8 {        r = requests.get(3 K/ g3 E- s( c. F
    1 n' e5 K, Z( b, z6 [$ D
                "https://restapi.amap.com/v3/weather/weatherInfo?key=f4fd5b287b6d7d51a3c60fee24e42002&city={}".format(5 e) W0 ^( ]( S- D9 l

    & {& Y: L3 K/ O2 y1 K                cityCode))
    . l; ^' K: M2 S) X' p+ t
    % B' V- A7 s6 d% X, r! X        if r.status_code == 200:  I9 R! w3 l* l3 B8 m/ p

    1 x% i( J) s$ @  E            data = r.json()['lives'][0]
    0 |- u5 H) L' i7 i6 R& R1 ^. `  c* O
                weatherMsg = '城市:{}\n天气:{}\n温度:{}\n风向:{}\n风力:{}\n湿度:{}\n发布时间:{}\n'.format(
    , A+ L4 E. b& j1 x, _/ t" N: x3 V8 H8 z# D- C9 N5 S
                    data['city'],
    ; U5 a" e9 V% d: n, l3 Y1 g
    4 u4 U% M) }1 O+ o) W7 o  n, u                data['weather'],
    7 V$ W5 c0 O8 q$ U) i+ O* H' I$ B* Y4 M. C; j2 P5 B
                    data['temperature'],
    9 j( R( w6 @8 r6 R7 e0 V: e  Q9 U6 k0 [
                    data['winddirection'],
    , G- C) w' K" V( K( Q3 x6 D) H
    8 n3 a* R' E2 K1 _9 Z                data['windpower'],4 ?8 m3 V* c8 o+ }; ^7 S

    ! I. B! u5 \5 Z                data['humidity'],. e: P8 l6 B. y, N+ G

    ! P" c/ h; ^0 X7 s- }, P. t1 r; R                data['reporttime'],* z# d0 M2 ~. W  y! w( Z

    0 Y8 l, c# B4 K' k            )
    : _3 W( }3 @& _/ q7 p: ]: @3 w& C! r+ K  b& ]7 `4 U- f' L6 E. R
            else:
    4 }+ l8 S' n0 p2 M% m7 K# \: g( I: a
                weatherMsg = '天气查询失败,请稍后再试!'5 A0 P: p8 h4 \! [/ y& q5 ^. m$ C
    + [7 z) ?8 _9 D9 ]6 X) S
            self.ui.textEdit.setText(weatherMsg)( k# A$ ?3 J. G
    ( Y  ]% s' B8 V' A( H, f
        def getCode(self, cityName):
    / G  [1 C( v+ Q3 i2 W, r( ^3 @, r) O) K- M, k
            cityDict = {"北京": "110000",; C; s. Z2 Q4 D! s& ^
    1 C: n( a/ C! J2 P
                        "苏州": "320500"," Z) s& q& f! H- C& m* @* U7 I
    $ b; Z' O  W; }% D3 T6 O
                        "上海": "310000"}
    % W' l3 V3 j# d/ A* [3 o+ ~; h. c2 m8 e
            **return** cityDict.get(cityName, '101010100')
    7 Q& M1 e% R9 C, ^: C
    & m9 C  U# s& Y- E- ~    def clearText(self):
    / g) o' P3 m! O
    ) f9 m  \7 p- B        self.ui.textEdit.clear()! u+ Z4 k+ v' ^# m2 x  `! t

    3 Q1 S6 a6 b3 {if __name__ == '__main__':$ P% P: k/ _3 a9 z

    # F8 @9 R" X4 p  j    myapp = QApplication(sys.argv)1 [7 C5 m+ Z1 a7 l: B7 r
    2 O7 j. W4 Q, \& \# T) L
        myDlg = MainDialog()
    # \/ b3 h& V! E6 r. n; T9 M9 P) s5 c7 u- ~" t
        myDlg.show()
    4 A, Z- f/ e7 _, h; t7 g4 V' \  f/ s0 e$ M. j( ?
        sys.exit(myapp.exec_())
    ! H) d. c5 v2 p1 x* _, g% p: S8 s' M& l5 \0 w' K! |! q" F
    运行demo.py并执行查询后的效果:
    ) Z$ c% k6 h4 R# i4 z/ _% ?% R2 _7 q! |

    - T2 w# j9 O# }
    5 g9 I3 c) Y, a4 g5 U4、将代码打包成exe文件
    8 U3 W# F# l/ K& I1 ~3 k% E/ \+ X; I& W1 {: P
    将.py文件打包成可执行的exe在Python中称为freezing,常用的工具有:PyInstaller, py2exe, cx_Freeze, bbfreze, py2app等。功能对比:( F% L: A  P: ?4 O! N1 k+ g  H
    8 A/ j0 H# k9 S& ?% t

    % {# ]2 u, Y% @: T- i" _6 k  G& O& F
    3 Z# D5 d* k" k# Rpy2exe:软件更新已经不活跃,因此也就略过。
      W2 q6 {* W  f, e5 B6 W! P5 g9 s% d+ n. E
    pyinstaller:明确支持win8、win10、理论上支持win7,,支持apple Macos, linux。pyinsaller可以打包成文件夹形式内含exe入口执行文件的形式,也可以是一个单独的exe文件。
    / v! \2 h& @, s) N' }2 \9 ]. H% ~0 x" X
    fbs:基于PyInstaller,使用起来更加方便1 ]# p) ^" v4 K
    # c- B" C! l' `& N9 C5 g
    这里选择了fbs来打包。fbs的安装方法:
    % i/ I# S1 K4 J
    : O' K2 g, c9 u, [- `pip install fbs& ?2 X1 ]/ M% K$ z1 M; t) i+ {
    使用方法,在命令行中输入:
    # ]( v) o% j( ~* D
    % E2 X, i2 w* h- z0 Y& L& E7 lfbs startproject
    1 t7 j; s2 F  r1 ]* N! J- F$ ]执行完成后需要输入一些APP的名称等。完成后会生成如下目录:) Q% l& C' G3 @7 [3 m+ o/ o: Z1 N

    9 Q. A8 x# C7 \1 `$ U
    $ K" G5 n3 D6 i# D( W
    . d9 q- D- V* K5 D% H) T1 O将刚才编写的PyQt5的代码(demo.py和Weather.py)拖到src/main/python文件夹下,删除原有的main.py,并将demo.py修改为main.py。然后打开 main.py,在文件头部添加如下代码:% i, U* q5 P7 _& I  {/ ~' I! [
    - d: f. R: N# I3 Z& h& e
    from fbs_runtime.application_context.PyQt5 import ApplicationContext
    ; u2 L7 D# w0 t9 O2 @4 a) c: A```
    ) ?* c  \: c) d: v. w  k3 G9 ^完成后执行:
    $ ~+ |0 A! E9 E0 q" ]+ R```
    & z( D. M1 g, H$ w, xfbs freeze
    ! T0 I- N* v5 q! G0 C```1 ~8 F1 x9 R7 l
    即可实现打包。生成的exe可执行文件在\target\MyApp文件下。
    , ~1 a4 ]# ~' _* K. n9 g/ J
    ! _4 J3 o* `7 x$ ^) r5 P2 n————————————————3 l2 L+ [; s; N1 B3 \! R2 x- _& B
    版权声明:本文为CSDN博主「宋宋讲编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    ! |* |# k2 v' w7 `' f0 J% |6 w6 F  O原文链接:https://blog.csdn.net/qiqi1220/article/details/126289667  y; q9 y7 U* l
    $ j. m; n' a# ^* `! Z9 P9 N

    ) g: Z3 H1 A; @" j' D5 ~7 u$ n1 H, B
    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 18:05 , Processed in 0.394456 second(s), 51 queries .

    回顶部