QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2203|回复: 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使用指南!; [. \* ~+ C8 R' F/ h$ |/ m; @
    % x! |5 D- D# u2 g! [" H
    使用Python开发图形界面的软件其实并不多,相对于GUI界面,可能Web方式的应用更受人欢迎。但对于像我一样对其他编程语言比如C#或WPF并不熟悉的人来说,未必不是一个好的工具。! d9 M4 x; M: ~5 j

    5 P% g" L6 g/ [' O$ ]3 Y常见GUI框架6 i6 s3 Y' |6 s7 f) |" D
    * {& J. b3 ]3 j$ L6 _- k: b
    PyQt5:Qt是一个跨平台的 C++图形用户界面库。QT一度被诺基亚拥,后出售给芬兰的软件公司Digia Oyj。PyQt5是基于Digia公司Qt5的Python接口,由一组Python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。
    1 k9 n+ W- k% y5 w0 i1 |  U9 L0 _& S& A' M- N
    Pyside6:Pyside是QT公司官方提供的Python包,上一版本为Pyside2,对应的是QT5,最新版命名规则进行了调整,更改为Pyside6,对应的是QT6版本。由于官方出品的比较看好,缺点是发布比较晚,网上的资料没有PyQt5多。1 @" [- g7 I7 H2 |# Z8 ^& T% F
    - r" p2 B% I/ T2 `& G! x. p6 T
    Tkinter:Python内置的GUI框架,使用TCL实现,Python中内嵌了TCL解释器,使用它的时候不用安装额外的扩展包,直接import,跨平台。不足之处在于UI布局全靠代码实现,只有15种常用部件,显示效果简陋。" @) w. K  y' M) o: P4 ?4 B7 [+ f" Z
      v" }+ [; d/ Z& F7 f- c
    PySimpleGUI:PySimpleGUI 是 Tkinter 一层包装。使用 PySimpleGUI 实现自定义 GUI 所需的代码量要比使用 Tkinter 直接编写相同的 GUI 要少得多。, {4 _; f* z& j9 \& X# P

    ' p/ R8 |) p3 X* q; o& p' VWxPython:wxPython是Python语言对流行的wxWidgets跨平台GUI工具库的绑定。用得比较广泛,跨平台,C++编写,文档少,用户可能就需要根据编程内容对不同平台中的GUI代码做一些调整。遇到问题不好解决,代码布局控件,不直观。
    0 i# @. F( w; W- m: ]0 r( b# h
    9 d8 x8 c+ ~, q% x7 W0 r' B6 LWax:基于wxPython ,为克服wxPython的问题而制作的一个包。
    ( Q$ r) [1 m2 d0 b
    ( X. n5 R( ]% |3 L  w) S& P2 uKivy:主要针对多点触控程序,智能手机平板等,也可以在没有触屏功能的系统上,全平台支持(Windows, Linux, Mac OS X, Android and iOS.)使用Python和cython编写,中文支持差,需要自己下载中文库并且制定路径。
    + w- T7 \. M0 a8 Z/ r+ Y& \! B4 f% P3 x3 {
    BeeWare:Write once. Deploy everywhere.需要与Kivy配合使用。' Y% e9 a& `6 _8 w- G8 ~/ P

    . D% X7 N. k: Q" R" _* o) a4 [7 `Toga:一个使用Python开发原生APP的GUI工具包。Toga由一个具有共享接口的基础组件库组成,以简化与平台无关的GUI开发。Toga适用于Mac OS、Windows、Linux(GTK)以及Android和iOS等移动平台。/ A( W, \; B6 y0 D5 _2 S" @
    3 g" J0 Y/ D5 G$ G6 g/ K
    Eel:一个轻量的 Python 库,用于制作简单的类似于 Electron(但是比它更轻量) 的离线 HTML/JS GUI 应用程序,并具有对 Python 功能(capabilities)和库的完全访问权限。& z. ~+ D: B/ ?# r+ ^. _
    1 R' i; d' ?9 \# L) n* [8 d
    Flexx:一个纯 Python 工具包,用来创建图形化界面应用程序。其使用 Web 技术进行界面的渲染。你可以用 Flexx 来创建桌面应用,同时也可以导出一个应用到独立的 HTML 文档。因为使用纯 Python 开发,所以 Flexx 是跨平台的。只需要有 Python 和浏览器就可以运行。$ X3 s; f  w- ]  \& h* Q: t
    * e! ^, X: ~; x9 u7 C! @
    pywebview是围绕 webview 组件的轻量型跨平台包装器(wrapper),它允许在其自己的本机 GUI 窗口中显示 HTML 内容。它使您可以在桌面应用程序中使用 Web 技术,同时尽最大可能隐藏使用浏览器构建GUI的事实。
    3 ~* E2 m& r  X4 `0 `% J  Q3 r7 f. D0 p9 G' p$ i
    enaml:一种能够让你用最小的努力就可以实现高质量GUI界面的的Python框架,也是一种独特的编程语言。enaml将声明性语言与基于约束的布局系统结合在一起,使用户可以轻松地定义灵活布局的UI。enaml应用程序可以在任何支持Python和Qt的平台上运行。
    6 M4 E2 h& I' \. ?  c0 b) O
    1 Z1 }3 U' {1 D3 K6 i* H" H# i. z个人想法:太多学不完,先学PyQt5,原因是资料多,学有余力再学pyside6,最后看下PySimpleGUI,看能否解决一些简单问题。
    " w  v# w( Z% L' s! l3 I/ Y6 U% E+ F0 `% _1 d' X& l- V
    PyQt5简介
    . R: j* n  |- J& A8 u
    9 a- K9 N6 O7 T7 [* L% o, YPyQt是Qt框架的Python语言实现,由Riverbank Computing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件,因此PyQt的API接口与Qt的API接口很接近,但PyQt不再使用QMake系统和Q_OBJECT宏。& g  E5 k+ `9 f
    ( o0 `6 r  e6 Q+ X9 c
    PyQt5提供GPL版和商业版证书,自由开发者可以使用免费的GPL许可,如果需要将PyQt用于商业应用,则必须购买商业许可。+ ^, L/ v& l* [/ v

    3 b' R' U9 u8 y4 h/ `PyQt5特性如下:7 E+ o$ Z0 N8 B

    3 ^8 Y* K- @2 R, d" N6 E2 ^基于高性能的Qt的GUI控件集。
    + {! j- C' f7 b0 i5 l- n% t/ A" k  V, a! `
    能够跨平台运行在Linux、Window和Mac OS系统上。. `% `- W4 k. c3 N0 y" Z
      R  d0 [3 w1 G
    使用信号槽机制进行通信。
    * k: |/ w6 D- `2 o
    : @% q  B" @0 @. n8 ~7 h对Qt库进行完全封装。
    5 ~2 o' s+ Y0 L; K) l
    * |, |9 p) a/ n9 I$ e/ p可以使用成熟的IDE进行界面设计,并自动生成可执行的Python代码。
    # R. F, r, K6 a, `* f
    2 C4 z, \0 _7 r7 S1 ]. ?( k8 _3 o提供一整套种类齐全的窗口控件。; T2 u: s; I, ^: `$ j, p9 A3 z. b

    " ]. {# `# Z6 ], i7 N. f0 h6 XPyQt5是由一系列Python模块组成,有超过620个类,6000个函数和方法,主要模块如下:+ m/ C) e: ~2 c3 ^1 u

    - U8 k) X$ @# `7 ~7 @% w7 DQtCore:包含了核心的非 GUI 的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime 类文件、进程与线程一起使用。$ s1 F* _: T& h4 k9 l
    ( h  C. {  }2 E7 \6 E
    QtGui:包含了窗口系统、事件处理、2D 图像、基本绘画、字体和文字类。9 D4 T! t4 G  ^6 L! n4 Z
    7 Z9 M  G, T, L! s# r+ p# _) Q: y
    QtWidgets:包含了一系列创建桌面应用的 UI 元素。' R  ~' [4 \8 H* S
    5 G3 q3 v+ @/ n) D5 K3 B
    QtMultimedia:包含了处理多媒体的内容和调用摄像头 API 的类。8 i# }2 u1 |# @, ^( p
    / H- B* {2 r* S- ^
    QtBluetooth:包含了查找和连接蓝牙的类。; p0 ^8 i) D$ e, a+ W1 D. h4 ?

    ; R. _: P+ k  |. J9 v' O- y8 nQtNetwork:包含了网络编程的类,这些工具能让 TCP/IP 和 UDP 开发变得更加方便和可靠。, v+ p/ D/ N* w4 s2 b+ N- h3 A

    , B  P3 s# ~6 {5 e9 s) a5 w% WQtPositioning:包含了定位的类,可以使用卫星、WiFi 甚至文本。
    $ k3 W6 e/ a( L% Q0 H  ~$ ?: s! C0 l7 S# h9 Y" t# M) M$ s4 R& Y: B& x
    Enginio:包含了通过客户端进入和管理 Qt Cloud 的类。4 Z5 M  Z/ Q2 P+ S/ ]- K

    & B+ r$ J6 a1 vQtWebSockets:包含了 WebSocket 协议的类。7 b  y. }/ e" B& z2 J* e
    0 ~2 e2 q* z; F+ k, U! {- X* t
    QtWebKit:包含了一个基 WebKit2 的 web 浏览器。
    ( C& K8 B6 K6 J; i6 f+ ]/ `7 f4 _$ V
    QtWebKitWidgets:包含了基于 QtWidgets 的 WebKit1 的类。/ H. T7 m7 P; Z. n$ h
    9 a+ ~; @' o' ]" b! ~' M
    QtXml:包含了处理 xml 的类,提供了 SAX 和 DOM API 的工具。
    ; ^! s9 Z! s- Q/ w" a: \) Z9 X3 C- }" q
    QtSvg:提供了显示 SVG 内容的类,Scalable Vector Graphics (SVG) 是一种是一种基于可扩展标记语言 (XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。' ~! B4 x: J; D% F' Q* M$ y) A
    : ~: ^* t' h9 D
    QtSql:提供了处理数据库的工具。2 ^: C. o/ n7 h3 c. q$ v# F& v
    9 @  G6 C; X# q
    QtTest:提供了测试 PyQt5 应用的工具。
    * F! s* z: I1 ]& R9 T" a8 x
    ' U! Y' \0 }: }' c9 kPyQt5的安装
    + A6 ~/ }9 ~& Q: G
    1 W' J, h3 s& F! r5 j; s由于后期要使用fbs进行打包,fbs对Python 3.7以后的版本可能存在兼容问题,所以我选择了Python 3.6.8进行了整个环境的搭建。主要内容为:Python + PyCharm + PyQt5
    + i3 J, T! e- r# q0 c- I9 T' ]# k/ n' n( ~4 R
    安装PyQt5
    0 v. Y4 b' k8 l
    - o% }0 f2 k& kpip install pyqt5
    # |# \6 d6 I4 L) w3 l8 H1 X/ k! T. ?" h! N$ I7 D
    pip install pyqt5-tools) Q8 w! ?. T# `
    其中pyqt5-tools为Qt Designer拖拽式的界面设计工具。安装过程中可能会报如下错误:: C0 F4 h/ K" M- M8 l9 s; E2 X
    $ q  x4 C9 u: z( P$ M- ~. Z
    qt5-tools 5.15.2.1.2 has requirement click~=7.0, but you'll have click 8.0.1 which is incompatible.
    ! Q3 T7 Q1 \9 G) |" X' R解决方案:
    $ x0 u9 {0 f- b2 m3 N% \3 p4 i; a" u, U2 r$ e4 s2 j
    pip install click~=7.0& U) {2 n( `$ u* Q) U, A* _
    Qt Designer的配置
    7 i1 \, B# _: @/ ?
    0 s. @- M; T/ DQt Designer 是通过拖拽的方式放置控件,并实时查看控件效果进行快速UI设计。9 w: X6 D4 w6 y5 \$ [' S

    5 Z5 I- k; _; M$ {0 k/ x; G2 ~$ E0 {/ v7 i* g: U5 u. Z
    # x$ A1 _2 `! l8 N( d7 }
    整个画面的构成:
    9 ^$ i! c, _/ c5 f% i7 K. j& j
    $ Q2 x* H& U! B8 @1 h9 O左侧的“Widget Box”就是各种可以自由拖动的组件
    3 X4 s5 [. o  c! [5 [* W* L. E9 {: M9 Z2 r, H( _) [
    中间的“MainWindow – untitled”窗体就是画布
      l4 N4 I- e+ t4 J4 M% u" Z8 Z
    * Q9 s2 k9 {3 j8 c+ z( p" I右上方的”Object Inspector”可以查看当前ui的结构
    * ?7 r, ]5 B3 [: }" d
    6 R5 y8 U3 }* q* @* b6 i( y右侧中部的”Property Editor”可以设置当前选中组件的属性
    ! @8 f0 }+ h" k2 z, @1 H) V' H' a: j( _) q" O  ]" m. @; b
    右下方的”Resource Browser”可以添加各种素材,比如图片,背景等等6 s; d; S: M1 F5 G
    " o  S* n/ G* x, n, c2 `
    最终生成.ui文件(实质上是XML格式的文件),可直接使用,也可以通过pyuic5工具转换成.py文件。
    $ u6 n1 u* y  L8 V0 J+ b3 D7 P1 i1 e* |. L% A% u
    QtDisigner配置
    6 D* m' ^: m$ M# I* \1 n
    ; @* z7 Z4 A, X在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    9 W& W, D8 E; e8 ~
    ; h/ u3 t5 v/ m( b7 ^5 OName: QtDisigner) `8 V9 o# n, E8 N! T# f0 \% k" i
    6 \6 y4 E- c% o2 A) B8 f
    Program : D:\Program Files\Python36\Lib\site-packages\qt5_applications\Qt\bin\designer.exe # 请根据实际修改( X& x( i& P7 [" j7 b

    # ^4 L5 R; z: wWorking directory: $FileDir$
    " c6 [6 E# n' S: m4 VPyUIC配置- `2 H- Y$ m) c& u
    ! n) J- D2 A* N' D' O7 _9 I# x
    PyUIC主要是把Qt Designer生成的.ui文件换成.py文件。: N9 M: d9 A& f; S
    % y, P& v! A; K$ ~2 d9 E+ H. f2 P" G
    在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:4 B$ |( l: |' l2 [( D& M( O" Z- h

    % |5 M! l( e' _" g6 `Name: PyUIC
    0 T7 h4 `# k1 P1 ?( b
    0 w2 F2 A$ R3 BProgram : D:\Program Files\Python36\python.exe # 当前Python目录,请根据实际修改
    $ E, ~' \5 f# D; l. s2 j
    + v2 ^3 D2 Z" D' }0 Y# q) ^Arguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py  n; K- g- l) O
    # s8 L$ `# q0 \& U: ]5 k$ ]
    Working directory: $FileDir$' L5 g* O$ G( ~9 M: g
    PyRCC配置5 J5 J2 t; ~. {' j4 |$ Q

    ! c6 R/ W2 _5 w- U* L, P  `& bPyRCC主要是把编写的.qrc资源文件换成.py文件。在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    + t8 y* v" r3 i) U" w' l0 ]& M% N
    Name: PyRCC% w; Y1 R2 V0 l) G

    ' S( d2 s( S( E; |Program: D:\Program Files\Python36\pyrcc5.exe # 当前rcc工具目录,请根据实际修改
    + R$ Q( j% J7 _9 u' i/ d4 Z
    1 d6 K9 Y: x1 f5 H0 P) e9 j  g# O6 k1 oArguments: $FileName$ -o $FileNameWithoutExtension$_rc.py3 {1 ^) w2 q$ B/ y
    3 H* x2 A- U6 C! |6 n1 C
    Working directory: $FileDir$& a0 p2 b. Q$ H, }2 a
    PyQt5使用示例
    7 Y" ]2 L; b  L# k' L, G) l9 L9 b. S" G9 y0 p7 S/ N6 B
    创建一个空白的界面:
    / h4 N% s$ v" T3 `; i; l
    * Y) F. M( ?" H& x' V! {6 j; |7 uimport sys
    & n( n$ _8 L, f4 D4 M4 B) e/ d* X+ ?( K) o
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
    ) P+ E& o+ Y% T: g" ^1 y
    & s" Q% ~9 Z# e4 o. iapp = QApplication(sys.argv)
    4 Y; C  ]1 ?# q' ?
    , w; b: g; O+ F5 L: o- ]$ @- R$ Qwin = QMainWindow(), o6 h/ y5 Q: v" X
    / O# z; C$ ~  p# i; d+ T. W9 o' A3 s
    win.setGeometry(400, 400, 400, 300)
    ( y! P2 l2 B. ?+ V/ {1 y# }: `0 q! g2 S4 O9 a* S) O! ]8 j
    win.setWindowTitle("Pyqt5 Tutorial")+ e, v! y  }( y8 h. z' U2 _
    ( m( i0 U+ R) b/ D; j
    win.show()7 |6 O# z3 a! s
    8 n: p- ~+ n2 p- u: t
    sys.exit(app.exec_())
    / m6 b) p2 ?3 t4 U, z4 r* S
    2 j% x2 m# i. J  t2 K6 `  N9 @9 d0 [  ]* c% m6 h7 @

    9 `1 l! \2 J2 _/ e其中:
    ' o) z  O/ x- Q/ Z$ P7 K
    6 j; h# S% r* s3 |5 k1 r& t; [/ h5 sQapplication():每个GUI都必须包含一个Qapplication,argv表示获取命令行参数,如果不用获取,则可以使用[]代替。
    . G- V/ Q) i% ~3 t1 v
    . \( h2 {8 V/ d2 {- gQMainWindow():类似一个容器(窗口)用来包含按钮、文本、输入框等widgets。arg标识可以获取命令行执行时的参数。4 o, ?- Q/ x/ V  D

    6 A7 [: c$ J. z3 P( |& Y, @SetGeometry是用来定义 QMainWindow() 窗口的尺寸, 语法:setGeometry(x, y, width, height ),其中x,y为屏幕上的坐标点。
    - @' f; u& S& I6 k7 V
    4 |+ |) R9 D4 r8 }" B2 f2 n6 u# |show():用来显示窗口
    4 J) Q2 v0 c4 r7 r! t& x( @7 B4 v2 u$ P/ v7 E
    exit(app.exec_()):设置窗口一直运行指导使用关闭按钮进行关闭
    ' Y0 N, t" ~; V. F$ N4 t% d$ Y* n
    PyQt5支持的常见Widgets有:
    : P, R9 T" ^2 R/ J
    * ~: G( U$ ]( P6 r
    ; p. Z; I" \! w8 k4 h7 h
    : D7 u& d2 r/ d从上到下,从左到右依次为:Qlabel、QcomboBox、QcheckBox、QradioButton、QpushButton、QtableWidget、QlineEdit、Qslider、QProgressBar
    " k; `2 R- }8 n& J& q) R$ ]# ?; S6 h: u* L7 o# W: J
    对于使用Pyqt5设置文本内容,我们使用Qlabel:, C% V1 \3 T2 W7 ^) q& o

    5 Y6 S5 y% \3 C+ Z0 q  Timport sys4 j3 z/ x4 H1 }4 a4 K% W6 `

    ( P( j$ N) i' B" X9 k* n3 Vfrom PyQt5.QtWidgets import QApplication, QMainWindow, QLabel3 h6 M) M0 Z% a$ H

    $ k8 j8 t0 X% m- P( t0 Happ = QApplication(sys.argv)# c) e  G) j; U4 r) Y& F1 u
    0 K0 q* X" p% ~! u% D/ F
    win = QMainWindow()
    + V  k- l' k6 I% f% \: ~% ?# g$ n7 p
    win.setGeometry(400, 400, 400, 300)
    % f5 X) p* u$ I' U2 j, N! F/ _1 s$ |, n$ O! i' @5 X
    win.setWindowTitle("Pyqt5 Tutorial")1 x- |# s8 V5 W+ o( e, X

    $ j- l% Z2 s6 R. k0 t\# Label Text$ F& q2 W" S, C$ V% {, g

    6 R6 j% V2 W8 Dlabel = QLabel(win)& e. G  c. {5 m% i" y
    ; [4 j8 l" X3 a
    label.resize(200, 100), U& m" {$ m/ R8 q7 u9 ?( z5 W
    3 A* g8 _& x8 a3 C; c
    label.setText("Hi this is Pyqt5")0 }3 v1 t: v0 Z5 t# m

    ( w& `( j, }) ~. llabel.move(100, 100)  g9 ?3 B* M3 ^* x* Q
      K( j* v1 S: ]. V0 a, R  f
    win.show()% \6 f0 f( p; d) h5 Q
      R4 D7 M5 M8 z3 a* P
    sys.exit(app.exec_())
    7 R& {& {2 \0 q
    / Q0 `- u+ K: x/ F9 L1 y
      q! @8 W* e' f9 b& W
    4 K& Z" o( }" V# u3 O按钮与事件:
    , {/ Q1 T6 M1 r! |2 e, @# y6 F
    import sys
    8 l# ]/ R1 C1 l3 X8 ~2 Z) g2 |$ V$ j- [( w( `
    from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
    ) E1 [2 @; Y: p" t' Z' S& X0 I$ O. r
    ( A# I7 E& o- Qdef click():7 n7 {4 f) G4 h

    7 M& g$ N) m: s4 C$ x; v    print("Hy Button is clicked!")7 z# j- @. N8 U1 W

    8 [: m3 F. f! L- M8 q% Kapp = QApplication(sys.argv)
    / ?% f/ c" z% t% }3 ~+ E2 H0 L
    . D  z: F1 o; uwin = QMainWindow()
    3 _3 B' o+ I, q- R  w2 Q; A9 Y5 z- |$ T: [
    win.setGeometry(400, 400, 400, 300), X+ C+ M3 u) d8 t: ]  R

    " H6 f% Z6 C9 l% E* t+ X; Xwin.setWindowTitle("Pyqt5 Tutorial")/ p. Y  }% \# ~- f" X
    % s* S; l1 j, r; _& v8 H: U
    \# Button
    7 ?' S; I6 B! Z2 H7 J1 N5 N9 I3 H1 ]6 Z7 ^: U. `
    button = QPushButton(win)
    , R- O9 |$ S' B9 h, k, r! z" C. Z4 J; v% b% l
    button.resize(200, 100)" I+ Z" t7 t0 D# y" R8 S
    6 ^+ H7 ^+ S. k" g
    button.setText("Hi! Click Me")
    ' y) Z$ l8 ?4 \9 s! n4 _9 m3 l
    + b( N* U3 E9 a& K" S" }! ]button.move(100, 100)
    ) U! U4 B) U8 }" l, ^6 U) J9 E
    ) u( [& W2 E: Dbutton.clicked.connect(click)
    : J' C5 E7 ], H- w, m1 Y* F: r% h2 m/ i
    win.show()
    ; \6 c$ E. ]# X2 |* ]0 a! Z
    ) `& z3 ?) I: i4 i( i$ g- t( ?sys.exit(app.exec_())" d$ N- M( y4 O. ^1 W, [

    ' L, a6 [7 A# B
    ; V  e/ S, }6 R6 d3 b6 t: Y' X/ K' z, F/ b% V
    button.clicked.connect() 在按钮点击后执行特定的事件。2 W0 L' W6 G/ q6 P' l5 d

    7 A+ ^8 ~% w9 R% J' L' f0 C- uPyQt5实战" J  D6 V! `# y. l' G6 z( n5 c

    1 i1 X$ P7 d5 K实战项目:简易的天气查询软件6 T; n8 r/ L' ^2 E* @: q# p

    0 P  i0 }4 c: [$ B- y- |& o1 r1、使用Qt Designer设计一个界面
    3 ^; A4 O" j; L$ e/ P; A2 W( O8 |2 f5 ~6 V

    8 F1 U3 K! o3 J4 D( a3 x1 R: X8 i- |9 u
    用到的控件有Button, GroupBox, Label,ComboBox,TextEdit,同时定义了两个按钮queryBtn及clearBtn,分别用来查询及清空天气数据。我们需要绑定槽函数,方法如下:1 J* t; I6 ^3 b7 _% }$ Z

    ( J4 O; S6 a. D6 T6 A+ l: D在Qt Designer右下角选择 信号/槽编辑器,点击+号新增: S3 u4 Y4 f( A& r( g

    / G! @! j! w0 J5 s分别选择queryBtn及clearBtn,选择信号 clicked(), 接收者 Dialog 及槽 accept(),(槽函数这里不知道如何定义,后期在代码里再进行修改)
    5 M# I! T. s) N2 M- X: }
    ; S) t7 E% U% B! e以上完成后保存为Weather.ui文件。
    1 A( R5 B# E% D) \; Z, a; I& F0 j% c! v& A8 c: \; U
    2、转换.ui文件为.py文件
    9 Z* l/ @* S# c
    1 w3 q. e9 h  u8 n& d6 v9 @) nPyQt5支持直接使用.ui文件:
    1 i. i% i( J- `! F- t8 x: G3 v
    ) T. l) L0 Y6 O; ~9 s4 Q' rimport sys
    % `: c' D; c% @( Q' Y: q" K  A
    - Q1 ~' z+ A% Z* D, k9 hfrom PyQt5 import QtWidgets, uic3 Z3 d) ?: d" j5 L: S5 }& x

      ~8 [$ Z* V( m3 Oapp = QtWidgets.QApplication(sys.argv)/ v. }" p6 I; J$ i; F+ A

    0 K3 c. J& Q' X0 D& Kwindow = uic.loadUi("mainwindow.ui")
    4 S8 f1 W) p& d  U  f# \$ c
    " U  U4 t8 ?3 }6 R0 ?5 R6 \! b/ ewindow.show()  E+ Y1 A4 x# a' ^# [

    $ n1 F2 [9 W; X* v2 n; ]2 Lapp.exec()5 G- {1 G* }0 _4 }6 l# S
    但是为了更好的自定义及修改上面的槽函数,可以使用External Tools – PyUIC,即可生成Weather.py,实际运行命令如下:, P  I3 `) T5 Y5 A. z6 B$ }
    ; T6 V  w; h! K/ N( V
    D:\Program Files\Python36\python.exe -m PyQt5.uic.pyuic Weather.ui -o Weather.py! a. P( J% i  z4 J1 P* P$ g" B
    其中,我们需要把两个按钮绑定的槽函数:
    0 w2 I: }3 x$ O5 [0 @5 J5 a
    * C' U# a5 ^. n/ a. T: x+ X( R\# self.queryBtn.clicked.connect(Dialog.accept)
    , U2 J6 ^8 Z5 A1 q! }+ F: C
    $ J, D. {9 [( U\# self.clearBtn.clicked.connect(Dialog.accept)" I5 P9 M- o% i/ j% |4 Y# B
    1 ^* f9 L+ n. L. y* [6 A
    \# 修改为:5 e# \9 R+ V: y: i4 P, l# c# G
    1 ]9 U2 |! {) t$ M" j
    self.queryBtn.clicked.connect(Dialog.queryWeather)
      P% i7 [- ?6 X2 E& T+ A0 K, s
    self.clearBtn.clicked.connect(Dialog.clearText)
    0 T8 E; M; \9 U  G! @3 k最终的Weather.py内容如下:+ R8 I2 b' s5 f, g1 C7 W& G

    ( \$ C; ?; C! m& d" V\# -*- coding: utf-8 -*-. G8 G" c9 y: q8 p. A
    7 u3 `2 o5 A, d! f+ k
    \# Form implementation generated from reading ui file 'Weather.ui'- Q1 |. b% L1 B$ ^6 I

    * ^& A0 w4 G9 J& s\#0 l1 W; l3 S* I1 D' V. {

    6 k! \/ m$ e2 s( Q\# Created by: PyQt5 UI code generator 5.15.4
    - O8 u7 t3 u' P% ?' t3 C) P! N4 S  Y1 l
    \#
    : |5 ~8 |1 C0 |9 ^4 Z) K; @. x7 L! q$ k
    \# WARNING: Any manual changes made to this file will be lost when pyuic5 is
    4 a5 N- ]& P) Q8 ?( B+ d6 A
    ) y* N& |. c, J; ^2 N# M( O\# run again.  Do not edit this file unless you know what you are doing.
    7 v, j  {* }0 x8 d# X% \) \1 F, ~
    from PyQt5 import QtCore, QtGui, QtWidgets& E6 \5 B* E& ]9 Y5 L5 y

    # i- P0 z  O. N) T6 x, y! aclass Ui_Dialog(object):
    2 A$ g" J3 l/ W. N. c
    * u/ j# D8 n) ]  j' s5 H    def setupUi(self, Dialog):. m8 ~; `7 P* r9 Y9 y

    : s4 a; o2 l3 D6 o5 L; C        Dialog.setObjectName("Dialog")0 J4 |  X8 V* t) a# ~- e2 x

    7 D. e. V3 x+ }        Dialog.resize(600, 600)6 Z$ x, O! C- A$ n

    # o+ K  t5 _) y0 o        self.groupBox = QtWidgets.QGroupBox(Dialog)+ z9 H' N0 ^# i5 z6 G2 d$ ]- ]

    ) D( m5 p$ x( G- f0 M7 w' m        self.groupBox.setGeometry(QtCore.QRect(30, 20, 551, 511))5 k/ d( W) h# A  R

    . X) I' \8 Q4 E6 y        self.groupBox.setObjectName("groupBox")
    8 ~; o$ e4 {* z# _# E
    8 X( H/ ^# w3 U+ a# y        self.label_2 = QtWidgets.QLabel(self.groupBox)1 W% R/ ~4 p0 M0 }

    % b3 k8 {& ]& t* m9 z2 i        self.label_2.setGeometry(QtCore.QRect(20, 30, 31, 16))# X7 ~" V& n+ ]9 ~( V' X
    $ a& x7 p5 B0 j- _, X
            self.label_2.setObjectName("label_2")
    % k* W0 x1 f4 \1 f: \+ ^2 y4 l2 E1 |5 _' s/ I. U- r2 r
            self.comboBox = QtWidgets.QComboBox(self.groupBox)' c" _8 N- w* i2 Z8 U( w2 O2 h8 C

    . L$ A! d) @+ ]0 ?' e1 v; ?, O! o        self.comboBox.setGeometry(QtCore.QRect(70, 30, 87, 22))8 k) j0 i  R, [$ Y9 l
    - B/ d" l6 D. B- f1 M
            self.comboBox.setObjectName("comboBox")9 y+ x; \/ v& ~6 _! o% o& d& o

    / j7 d6 V1 I) b7 o  P0 [! R/ H8 y6 Q        self.comboBox.addItem(""); I* E+ G: V3 c

    6 ~) N/ i4 F. A: R0 `0 b1 X        self.comboBox.addItem("")
    # ~7 O! \, N! Z, @  g  \  i, ^" y; r5 p* J' I0 ?' m$ P+ H
            self.comboBox.addItem(""). U% W" F0 Y) ~; d" E. n

    ( ]' C7 l8 T8 o' n, m        self.textEdit = QtWidgets.QTextEdit(self.groupBox)
    7 m, k/ \; X: ^
    & ]2 I( C# c* t/ `: c" a4 `, Y3 M8 ~        self.textEdit.setGeometry(QtCore.QRect(20, 70, 491, 411))
    4 E6 ^5 N9 G4 ?$ P: Q6 Y' Y8 ~& J  w" N6 U
            self.textEdit.setObjectName("textEdit")
    + R) [* r0 I9 w* C
    + f3 Z! c9 h+ U7 D8 Y6 g- \        self.queryBtn = QtWidgets.QPushButton(Dialog)
    ( {& v" {# u1 E" w+ Q5 l4 K# b2 A# M, I
            self.queryBtn.setGeometry(QtCore.QRect(490, 560, 93, 28))
    % X" I( T# a: n7 v# I
    : [- U4 {: s$ g9 Y8 k& O: Q! r        self.queryBtn.setObjectName("queryBtn")  h- Q3 {$ n' @6 Q2 T6 Z0 r; M1 z

    , k2 Z6 o; P8 v        self.clearBtn = QtWidgets.QPushButton(Dialog)4 z* y& @( R( o  [# \% L

    % ^: S+ [* K, R; {        self.clearBtn.setGeometry(QtCore.QRect(30, 560, 93, 28))1 I0 ~5 w4 i/ D4 W

    9 Q. {3 I# M8 a6 r' p        self.clearBtn.setObjectName("clearBtn")
    6 g; ?1 _: b9 Z) s  r
    / |- p/ W7 K1 b; y6 w, `# a* x        self.retranslateUi(Dialog)5 g: N) l& f1 m0 C
    ) n/ K8 L) [' X
            self.clearBtn.clicked.connect(Dialog.clearText)
    6 A  M9 z' n8 Y$ W$ A1 N# U- B6 ]- Z3 b  v3 y
            self.queryBtn.clicked.connect(Dialog.queryWeather)3 W1 d  Z8 h# _$ ~1 A% z3 F
    ) X4 ?- t. L, b: H
            QtCore.QMetaObject.connectSlotsByName(Dialog)
    * V* ?( |! T) }/ H0 y' o. z' j
    & U$ \4 e" ^  `7 m5 D* ?    def retranslateUi(self, Dialog):
    * {+ j2 Z9 |) a( B$ J" R- u9 ?6 N  q2 L& ]
            _translate = QtCore.QCoreApplication.translate
    ! G/ k7 G/ R& T! ~
    ; u- Y+ F0 w  j, x6 w, |9 r& e" ]        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))1 ]9 l  r* |$ S, O6 z/ a, v

    + M5 a& e* |5 g# F; s* z) x        self.groupBox.setTitle(_translate("Dialog", "城市天气预报"))
    , o: z& s2 ]# u
    # t  e0 n6 \3 E1 o$ b2 c        self.label_2.setText(_translate("Dialog", "城市"))
    2 a. J4 E8 p" K& Q4 A
    3 r! r$ V+ y" j; b        self.comboBox.setItemText(0, _translate("Dialog", "北京"))5 d3 _# l, d; S  i# H

    & w: V  l" C, b/ X/ |/ s8 |        self.comboBox.setItemText(1, _translate("Dialog", "苏州")). Q& g; b9 I& X% s$ B

    : \' e' a; ^9 f9 o: z        self.comboBox.setItemText(2, _translate("Dialog", "上海"))7 l& {) E/ L: _- s2 M! z, g

    ( G3 L! `1 G- Y. f  R1 n" p$ P' S        self.queryBtn.setText(_translate("Dialog", "查询"))
    ) S- P8 X% X0 z1 r* b3 ~, o' p0 l5 _1 V, X7 L" \3 K
            self.clearBtn.setText(_translate("Dialog", "清空"))5 \1 m2 f$ v. b
    7 N8 y9 M0 E  Z6 [) W6 i
    3、调用MainDialog0 U( s* D, C* W

    ; |3 u* b: G) g* s: W在MainDialog中调用界面类Ui_Dialog,然后在其中中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。新增demo.py文件, 在MainDialog类中定义了两个槽函数queryWeather()和clearText(),以便在界面文件Weather.ui中定义的两个按钮(queryBtn 和clearBtn) 触发clicked 信号与这两个槽函数进行绑定。
    9 G0 v, f( ?9 }2 _! g/ z" B8 I3 {# a( `# p6 e
    完整代码如下:) I3 q/ t& H; @
    8 }1 j; D$ J9 U6 F" T+ ^
    import sys8 @$ ?  n2 _; U0 i% b7 U! h
    ! x; B- Q- q$ J- r8 U& `
    import Weather9 i/ F/ n8 I$ j. |3 Q

    ) q" E- p  K+ S5 R0 S! j: Ofrom PyQt5.QtWidgets import QApplication, QDialog; P3 K7 \1 K0 D! d6 A
    9 `- d* T, U/ a9 w
    import requests# v; N. T) W" r6 a

      R! I0 Z: N8 L7 \class MainDialog(QDialog):1 _; k2 ?  k% m3 r; _
    : j4 P( [7 M0 _% V5 b  A
        def __init__(self, parent=None):7 `. k! E  _, ^
    . U" @+ k8 u  x5 _! n# \, w
            super(QDialog, self).__init__(parent)
    : Z5 E# r" ]) q4 X2 d0 f/ m7 i% n* w4 [$ L" s. F8 T# Y: M+ M' a
            self.ui = Weather.Ui_Dialog()9 l3 s! ?7 e4 f& m. E# J/ M  A$ s
    ' E4 `& Y5 K% j! B  o
            self.ui.setupUi(self)
      Z# k/ E- Q6 g% {5 e/ J3 f1 M: t! ?& J$ q: k
        def queryWeather(self):
    0 ^  C& T. [! V8 K- Q+ s
    $ [  M& G5 i- Q        cityName = self.ui.comboBox.currentText()9 P: F! O6 {8 Z

    2 C0 _4 d5 }& Q! ]( r        cityCode = self.getCode(cityName)
    * {+ j/ U1 \# G$ r0 o
    / d1 B3 ?/ O$ A' C7 o        r = requests.get(: b, V9 a+ u  K" x/ T6 J

    $ W- @; e% Y2 C! h% V6 \            "https://restapi.amap.com/v3/weather/weatherInfo?key=f4fd5b287b6d7d51a3c60fee24e42002&city={}".format(
    1 \, u5 _! p( t4 Y5 z( N' |! c8 Z0 V* m6 G2 S3 H- R# |% c  X$ X& l  p$ [
                    cityCode))' z3 d+ Y; A) G/ b6 x
    1 x7 N" v8 |% a/ h
            if r.status_code == 200:
    $ m) Y' d4 V" d+ s# k- Y7 y+ o7 P
    6 w$ _1 U% u, M: ]1 n            data = r.json()['lives'][0]
    ) x8 n. e4 }2 `5 [$ |6 {6 f  r- I2 k9 O, T3 F
                weatherMsg = '城市:{}\n天气:{}\n温度:{}\n风向:{}\n风力:{}\n湿度:{}\n发布时间:{}\n'.format(2 S5 ]$ {# M$ H8 {
    ( E1 z& f* u2 S
                    data['city'],! B/ g6 Z1 u$ G' H4 w  z
    - z, G4 }+ i5 e8 p
                    data['weather'],
    ' l: V8 n, c  ]8 a/ A8 W- q% U" R; M9 L
                    data['temperature'],
    ' x! m8 `% f/ H" w" ^' i; W0 w$ h6 j7 n: S, L( [
                    data['winddirection'],7 {7 m0 H1 [/ P& f# ]% n) c$ ~

    + b. j  k2 O: Q: A4 V6 F                data['windpower'],# H+ F/ n; {& Y0 ]: V, p
    4 F4 z1 v& C- u% b5 X: Y# Y
                    data['humidity'],
    ! V6 p9 K$ y4 [: M; `# B" D
    6 |& C+ O8 r# ^6 w" j                data['reporttime']," `) [- E* F- M' b8 y+ I( O8 d5 J
    - S8 S( L  ?* V  a2 E* R
                )* j* w, ^: }+ r+ E- K2 u3 u: S, l
    0 e+ Q$ b; ~  ^. m( D; j  c
            else:3 u) k7 g2 s9 r3 z0 b

    5 {' L2 L, e0 y/ F: {            weatherMsg = '天气查询失败,请稍后再试!'
    6 I: v5 f4 \- V  m& R% _
    1 u$ G% R  M6 L+ `) i% n7 W( O        self.ui.textEdit.setText(weatherMsg)
    7 K3 Q  G* F4 C6 w7 h" ?' V2 ]4 R- n- k3 W1 z& x- @! |
        def getCode(self, cityName):
    ) H( s# E* Q8 p& m2 k! X
    2 F9 p7 D/ i/ x( B( v        cityDict = {"北京": "110000",
    ; K( b" a7 }; o8 d
    9 Z; h! Y+ n& b% K, i( }                    "苏州": "320500",
    - i% ^# t7 v. r/ ~( n5 P3 L4 j- W( o4 [. F$ M
                        "上海": "310000"}
    . Y: A; K! P! d1 g" F/ D+ `4 T
    . d  {% `$ j7 S: w% H. o' h        **return** cityDict.get(cityName, '101010100'): `( Z3 C7 \. Q, [; L2 d

    " r. n/ N/ G  I  e# n( s    def clearText(self):, i( i( _# j: A' w1 I& l8 I' ?
    ) R9 D. m2 ^% y2 |: ?3 n) B
            self.ui.textEdit.clear(); |8 R1 Y- T* o3 z- I9 r

    ! }; T* p. I: h! cif __name__ == '__main__':
    7 M/ i6 q5 U2 q+ V6 y# v  i# q5 B- k9 a4 }/ E* K2 s
        myapp = QApplication(sys.argv)3 }& o& D  f& x

    ( W7 I/ Y) V. Q: _* U    myDlg = MainDialog()% H% V8 i0 b, y4 Q5 V

    . l  \7 B" D$ _: M    myDlg.show()
    ' H( W6 `" ~6 Q2 v  l! Q  M7 s
    5 O6 X+ \0 B& z8 H    sys.exit(myapp.exec_())8 }- ^: h2 M+ N7 L' F" z

    + ^& E0 o5 K* Y; R6 C运行demo.py并执行查询后的效果:
    ( V4 H8 g6 X* x/ ^9 X5 g# A# y  w$ W% {# ]/ Q9 y0 N1 G

    $ S4 k' {2 g% k' I( Q6 \1 a
    9 {2 {" {7 k( e7 L7 L1 B( e4、将代码打包成exe文件
    2 H$ t  F9 f8 X$ R) m% M9 ~$ t! i! n  [) x- F0 e( ?
    将.py文件打包成可执行的exe在Python中称为freezing,常用的工具有:PyInstaller, py2exe, cx_Freeze, bbfreze, py2app等。功能对比:
    - V1 n9 Q* y+ |, y" {$ `0 p. a4 q2 a2 w7 M" L

    # J, E. P' g! C, M+ P0 m# T/ l& s" m0 i1 Z6 [$ Q+ j7 f! s# y2 e
    py2exe:软件更新已经不活跃,因此也就略过。
    . _, `- d; w8 I0 x( T) B4 h
    1 r* U$ ]. p7 j- g; fpyinstaller:明确支持win8、win10、理论上支持win7,,支持apple Macos, linux。pyinsaller可以打包成文件夹形式内含exe入口执行文件的形式,也可以是一个单独的exe文件。) }  ?- ]4 R: `' ~' _( F# @* Z

    3 c6 j8 {. R  u" }+ |. ?fbs:基于PyInstaller,使用起来更加方便
    0 E/ @5 x; m' \0 @# \- V7 U# P2 g8 u
    这里选择了fbs来打包。fbs的安装方法:
    $ ~' N- O; p) A& @/ h4 W" v
    # h2 c: X+ B/ t5 R+ G9 B7 N3 gpip install fbs% z9 a( ]. z" ^0 A4 K
    使用方法,在命令行中输入:
    2 \0 M6 A1 A1 `9 _0 l9 V# v5 @3 }$ \$ i9 T/ N0 U! Y% |
    fbs startproject
    / M  y2 D: S/ N4 M执行完成后需要输入一些APP的名称等。完成后会生成如下目录:
    ' z. u, A( `9 L
    ! t2 j  N  I/ ]' k* H; |) d/ ^* V3 u5 _( z$ k# ]
    4 M6 i) @! E% j7 v0 ^6 y
    将刚才编写的PyQt5的代码(demo.py和Weather.py)拖到src/main/python文件夹下,删除原有的main.py,并将demo.py修改为main.py。然后打开 main.py,在文件头部添加如下代码:5 i! y( d2 u0 b* f* I
    : `8 {" x- h2 h- z
    from fbs_runtime.application_context.PyQt5 import ApplicationContext9 R) j; b) I* b3 R. m. E' p0 C% @
    ```
    ' D5 A3 k  W7 X; {1 x4 k) q完成后执行:
    + Q& b/ H* G, y- a, c6 D# h7 O# q```
    9 k2 c% e' X) Qfbs freeze
    $ r: J/ Z! X/ O+ l  R4 X9 O```
    4 w; k. o2 r! h即可实现打包。生成的exe可执行文件在\target\MyApp文件下。
    - q" {$ C0 P" u; _  s3 I; A
    4 k+ U  S4 L7 t& p1 O  k7 u0 F————————————————( M7 t8 Z% O+ V7 I
    版权声明:本文为CSDN博主「宋宋讲编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    7 t- l5 y5 p: _& a8 }原文链接:https://blog.csdn.net/qiqi1220/article/details/1262896674 s8 ?0 L( H) ~7 {2 `! q4 ^

    , ]( N& ]4 m; o  B  K1 u% I$ E2 I# Y2 n$ K; _9 S. ], K
    . C+ {" k6 W/ h0 P
    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-5-26 05:17 , Processed in 0.325750 second(s), 51 queries .

    回顶部