QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2254|回复: 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使用指南!0 v6 `4 V3 y7 O" q8 _8 @1 l
    0 ^8 I" m$ y! Z
    使用Python开发图形界面的软件其实并不多,相对于GUI界面,可能Web方式的应用更受人欢迎。但对于像我一样对其他编程语言比如C#或WPF并不熟悉的人来说,未必不是一个好的工具。3 M9 A! y! m& ]4 `9 ~1 g
    9 m2 n7 ?2 s- V7 N' G1 m! d) [
    常见GUI框架6 U5 @- u+ e: i+ D6 _  h' b

    ' s  x, S3 k% v8 e. B+ g/ KPyQt5:Qt是一个跨平台的 C++图形用户界面库。QT一度被诺基亚拥,后出售给芬兰的软件公司Digia Oyj。PyQt5是基于Digia公司Qt5的Python接口,由一组Python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。* F- A  a, M) @( F/ w7 b$ R) B1 Q
    * y: Q. J% l: l( o3 O# T# S
    Pyside6:Pyside是QT公司官方提供的Python包,上一版本为Pyside2,对应的是QT5,最新版命名规则进行了调整,更改为Pyside6,对应的是QT6版本。由于官方出品的比较看好,缺点是发布比较晚,网上的资料没有PyQt5多。, K; P+ o6 @6 m1 S# [

    0 W' k4 w4 _" N5 X# sTkinter:Python内置的GUI框架,使用TCL实现,Python中内嵌了TCL解释器,使用它的时候不用安装额外的扩展包,直接import,跨平台。不足之处在于UI布局全靠代码实现,只有15种常用部件,显示效果简陋。- R) s2 K6 d9 Y" o$ m$ F
    ' j# c7 a7 D! X! S) |# z2 P3 l
    PySimpleGUI:PySimpleGUI 是 Tkinter 一层包装。使用 PySimpleGUI 实现自定义 GUI 所需的代码量要比使用 Tkinter 直接编写相同的 GUI 要少得多。
    ( Z" k$ A; @( b7 {) x' Q$ S7 @: c9 ?: z* t! A/ d! u' H% z
    WxPython:wxPython是Python语言对流行的wxWidgets跨平台GUI工具库的绑定。用得比较广泛,跨平台,C++编写,文档少,用户可能就需要根据编程内容对不同平台中的GUI代码做一些调整。遇到问题不好解决,代码布局控件,不直观。
    : W' c8 t- ^& L# J& t$ C
    6 z( Q9 ~- O7 f. ?! l% tWax:基于wxPython ,为克服wxPython的问题而制作的一个包。
    9 H5 P; f4 d% h2 K* B0 h; Z
    # a( K" g! ~6 B& IKivy:主要针对多点触控程序,智能手机平板等,也可以在没有触屏功能的系统上,全平台支持(Windows, Linux, Mac OS X, Android and iOS.)使用Python和cython编写,中文支持差,需要自己下载中文库并且制定路径。/ O% }2 D5 K/ d- j

    8 @9 X. A4 l3 y% ]BeeWare:Write once. Deploy everywhere.需要与Kivy配合使用。' _4 _& b8 U$ {% X. n6 L7 Z

    5 K4 K* N* X# }, A3 b7 Q/ \/ XToga:一个使用Python开发原生APP的GUI工具包。Toga由一个具有共享接口的基础组件库组成,以简化与平台无关的GUI开发。Toga适用于Mac OS、Windows、Linux(GTK)以及Android和iOS等移动平台。
    7 w$ u5 |$ K3 E3 D3 j. e& E! f$ y
    ! E, h8 ?7 b8 h$ `! MEel:一个轻量的 Python 库,用于制作简单的类似于 Electron(但是比它更轻量) 的离线 HTML/JS GUI 应用程序,并具有对 Python 功能(capabilities)和库的完全访问权限。4 k/ @+ k& s5 Q6 p
    2 T3 Y/ [+ [2 n) F
    Flexx:一个纯 Python 工具包,用来创建图形化界面应用程序。其使用 Web 技术进行界面的渲染。你可以用 Flexx 来创建桌面应用,同时也可以导出一个应用到独立的 HTML 文档。因为使用纯 Python 开发,所以 Flexx 是跨平台的。只需要有 Python 和浏览器就可以运行。5 h) V, {- u) I* y  t% `$ J8 d: t

    . |7 o9 ~, \5 npywebview是围绕 webview 组件的轻量型跨平台包装器(wrapper),它允许在其自己的本机 GUI 窗口中显示 HTML 内容。它使您可以在桌面应用程序中使用 Web 技术,同时尽最大可能隐藏使用浏览器构建GUI的事实。3 D4 ?+ D+ Z) }3 V+ v

    1 t1 d- ^3 W5 M" c  menaml:一种能够让你用最小的努力就可以实现高质量GUI界面的的Python框架,也是一种独特的编程语言。enaml将声明性语言与基于约束的布局系统结合在一起,使用户可以轻松地定义灵活布局的UI。enaml应用程序可以在任何支持Python和Qt的平台上运行。5 z' Q8 X, }" N# r! w" v: ~. E

    . H  _% b, W, v/ ^  @! ?0 F个人想法:太多学不完,先学PyQt5,原因是资料多,学有余力再学pyside6,最后看下PySimpleGUI,看能否解决一些简单问题。
    " }9 ]8 {5 a2 w
    $ O3 u- C3 D. jPyQt5简介
    8 ~8 _! H' L0 M* o$ ~  i2 N8 b' N/ W0 u0 f" F+ h7 C
    PyQt是Qt框架的Python语言实现,由Riverbank Computing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件,因此PyQt的API接口与Qt的API接口很接近,但PyQt不再使用QMake系统和Q_OBJECT宏。
    * G  t  O8 L+ i8 x( y' e
    7 Y7 S% m. l7 U' I6 B- OPyQt5提供GPL版和商业版证书,自由开发者可以使用免费的GPL许可,如果需要将PyQt用于商业应用,则必须购买商业许可。. {9 ?* {: t" ]- h1 v- [# ~: P1 p/ R
    1 X& A5 Z( H6 g  p8 A. @: N! `
    PyQt5特性如下:
    + m3 R) B; v& n4 n7 s5 \2 u4 t3 m3 g# s. P
    基于高性能的Qt的GUI控件集。& o0 ?0 p* f- F& N+ i# D2 @
    8 E. X/ u- ?& y) E0 L( h8 |: j' F: L7 W
    能够跨平台运行在Linux、Window和Mac OS系统上。
    7 z7 ^# k: B% p; V2 }( ]
    - c6 ]: o; @% J  a9 ]3 H使用信号槽机制进行通信。4 s2 i, D: j( M' N

    6 p/ X, W2 i0 {  D对Qt库进行完全封装。
    9 c. r9 K( M/ ?' N/ f3 C; L6 x: r% u4 G* E. J7 L" J: e
    可以使用成熟的IDE进行界面设计,并自动生成可执行的Python代码。
    , _/ D* i; w( j2 ?
    7 X9 h; e. L8 M4 G2 J提供一整套种类齐全的窗口控件。
    * P: J- q# E! d
    ! T4 U  ^& a5 J; w5 ^PyQt5是由一系列Python模块组成,有超过620个类,6000个函数和方法,主要模块如下:
      ^! w) T  E5 j0 z/ l0 U- ^
    / d* n+ P3 n- B4 aQtCore:包含了核心的非 GUI 的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime 类文件、进程与线程一起使用。
    3 X: {; ?8 N% K1 @5 _  K
    - b2 i( ^" B0 u6 E% E; xQtGui:包含了窗口系统、事件处理、2D 图像、基本绘画、字体和文字类。7 x1 m' M9 d) W4 A7 ?6 D
    ; {2 ~# j" U8 k8 Y
    QtWidgets:包含了一系列创建桌面应用的 UI 元素。
    ' u% v9 x+ M- g4 @1 {8 ~0 K3 V! U
    QtMultimedia:包含了处理多媒体的内容和调用摄像头 API 的类。0 d  B& f% L4 x; g1 m
    3 q' ^8 V* w3 E1 F& o
    QtBluetooth:包含了查找和连接蓝牙的类。
    4 _1 j" Q' y/ F# p3 q3 x+ E& T
    0 P9 |4 h5 O' d& d! e& hQtNetwork:包含了网络编程的类,这些工具能让 TCP/IP 和 UDP 开发变得更加方便和可靠。6 A3 O3 h; m  e& z

    1 |0 W+ \2 v5 S- k2 m" F; oQtPositioning:包含了定位的类,可以使用卫星、WiFi 甚至文本。1 W) O) k3 }, C: e9 H
    1 i) T. U+ c% d) Y, C
    Enginio:包含了通过客户端进入和管理 Qt Cloud 的类。
    ) l! ~! K# Y0 Q1 L1 c, H2 V  O) ^+ G6 @0 {
    QtWebSockets:包含了 WebSocket 协议的类。/ W5 h+ y' r0 ~4 ]0 U/ C& g

    + R; d% N6 S6 p5 Y5 u3 P- a# rQtWebKit:包含了一个基 WebKit2 的 web 浏览器。
      g8 z) M! O& r* ~8 |/ K0 R5 _/ i8 g; A" M0 S8 R
    QtWebKitWidgets:包含了基于 QtWidgets 的 WebKit1 的类。/ w$ e# K6 U! t

    9 K/ P+ Q; c# b. h1 k+ ^8 \. CQtXml:包含了处理 xml 的类,提供了 SAX 和 DOM API 的工具。
    ) @. D" \. e  m2 ~) o6 [8 E7 _; g5 _' F- b& _# R$ @
    QtSvg:提供了显示 SVG 内容的类,Scalable Vector Graphics (SVG) 是一种是一种基于可扩展标记语言 (XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。
    8 m- B, e* r: H; p* j# F! g$ ?( W& D# d" ]' Y5 F
    QtSql:提供了处理数据库的工具。
    0 C  f+ d  i# O9 m0 e5 \0 }* }; \
    1 [  W7 r0 M# u( o  H7 pQtTest:提供了测试 PyQt5 应用的工具。) ?/ P& |, D! I" L) I
    / a! R% ]! h6 N8 a+ n6 l
    PyQt5的安装
    $ A  s# l2 y3 H/ t3 @1 V7 x' y
    : k) B) Z& ]. o( N由于后期要使用fbs进行打包,fbs对Python 3.7以后的版本可能存在兼容问题,所以我选择了Python 3.6.8进行了整个环境的搭建。主要内容为:Python + PyCharm + PyQt5
    " ~2 r  Q9 `. S1 e8 Z( h4 ^/ j* z; z- J
    安装PyQt5" M5 ~7 s5 S7 M. a; I/ T

    ; }. v  a8 _$ |" h; j8 Epip install pyqt51 p3 @8 S- C0 T
    4 c( [9 U- Q7 g
    pip install pyqt5-tools- T8 e  e1 F/ B' `
    其中pyqt5-tools为Qt Designer拖拽式的界面设计工具。安装过程中可能会报如下错误:# m  C, K! T; l! w- y! `7 R
    $ k0 s' j; t) l  v' w
    qt5-tools 5.15.2.1.2 has requirement click~=7.0, but you'll have click 8.0.1 which is incompatible.& F) @7 I5 s  ?) g6 w5 O- F
    解决方案:
    0 @0 A, j1 |8 S( g! F1 [4 n, |" w9 h4 K, @: \0 Z! F
    pip install click~=7.09 q! @1 q* c& p4 V# l& e. G- H
    Qt Designer的配置
    * y' m. _- v* b1 q% d" [) Q3 G9 ~
    Qt Designer 是通过拖拽的方式放置控件,并实时查看控件效果进行快速UI设计。+ v. H1 L% X# @/ e
    + w4 M3 M  M5 l0 `5 \
    2 ]( n3 L, Y" N5 d0 t( P
    ! B( f+ n$ b6 J# _$ w- P- L
    整个画面的构成:2 k3 v( t  p5 H" }& [- ?9 H1 f
    - q5 H$ F( c) b& b+ P
    左侧的“Widget Box”就是各种可以自由拖动的组件
    ) @- t' H4 `) Y4 Q/ Q9 l* n9 k6 J* p8 o
    中间的“MainWindow – untitled”窗体就是画布
    % S6 Z, J7 K! B0 ~  q
    . ]% P/ o" ]; ~( b9 d* w右上方的”Object Inspector”可以查看当前ui的结构
    2 R& }1 ~; m/ @9 x' p9 [0 m3 {3 O; G- e  G3 `1 a* H  i' j9 @$ @) i
    右侧中部的”Property Editor”可以设置当前选中组件的属性
    : @4 i: S( p2 D6 ]4 A5 s! J& p. Y% |4 y; r/ f
    右下方的”Resource Browser”可以添加各种素材,比如图片,背景等等
    % R& e- F! F# `% Q+ i8 q/ m7 P) q+ K, W+ ~
    最终生成.ui文件(实质上是XML格式的文件),可直接使用,也可以通过pyuic5工具转换成.py文件。
    ; B# v5 X8 ?& W5 A- L
    2 N* K% ^# |" v4 M( e$ z+ A5 TQtDisigner配置
    , W& M; r+ r- W3 u1 G: f- n' m4 n" h& b# ~2 s& g  s
    在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    5 T# e  t, Y2 {* V8 u
      ]/ c; h+ A: C) w* GName: QtDisigner
    ( B3 k  P) n& Q# ^0 ]* z! T1 x5 j& M! `% w0 I8 v
    Program : D:\Program Files\Python36\Lib\site-packages\qt5_applications\Qt\bin\designer.exe # 请根据实际修改  [& F5 I0 B- W

    9 y7 s8 u# L1 i% y3 q6 FWorking directory: $FileDir$* `2 M1 P# Q9 _8 {4 N$ K8 I! ]
    PyUIC配置. j/ c" y  f, D+ E
    7 K2 g* b5 k5 r" \1 g
    PyUIC主要是把Qt Designer生成的.ui文件换成.py文件。! s+ h( ?# V7 \

      H8 n6 P2 N& w* Z. [% |在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
      ]6 J+ W0 V# |1 U) Y0 F
    ' k8 K9 z# b5 Q, L1 c: F6 e6 GName: PyUIC
    , V  i8 d# Q4 q0 a+ c
    ( V! R" _4 _. T- r; {Program : D:\Program Files\Python36\python.exe # 当前Python目录,请根据实际修改
    " l* }2 f% g* p2 {* ^% q' `2 o( K9 R  D/ k% x5 Z! x
    Arguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py  |4 Q: [; x2 Q/ m& [6 n0 P
    + C+ F. A. P0 y' Z. a
    Working directory: $FileDir$8 s. M2 ]+ N7 R% }) P" i
    PyRCC配置7 }' a' [2 |9 p4 \! e% {

      Y1 D; [- ~/ B" f+ n8 ?PyRCC主要是把编写的.qrc资源文件换成.py文件。在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:- A: i7 b" A0 |8 ], S9 N3 K

    & p6 |+ Z4 t2 ]% e: r+ }! A$ i' BName: PyRCC5 @0 e4 s5 }# x- x2 b3 K

    " M7 D& x% A( u9 [; {" ?Program: D:\Program Files\Python36\pyrcc5.exe # 当前rcc工具目录,请根据实际修改& a. A: H: C. h. t4 h7 a& z7 ]

    ' d9 m8 I1 p; _, g3 D# l% e0 y" hArguments: $FileName$ -o $FileNameWithoutExtension$_rc.py
    4 N8 L3 e% E: i- v# N' B5 S2 }( G9 r2 p
    Working directory: $FileDir$5 `7 g9 G5 {* q  q) t, k
    PyQt5使用示例& t& m* C: \3 G. s" \2 l
    7 q6 l5 L* L* N
    创建一个空白的界面:
    ) S' b# q+ Q) h: O+ `' V5 }8 H. y" Q3 F4 M' z: y
    import sys1 i& C9 _6 C. U. Q+ j

    % h+ y" j% R. p  q9 t1 ufrom PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
    4 u5 M5 U. n8 ^3 u! F  u8 b2 G
    " `% R# a1 F$ t2 R4 B0 |# Lapp = QApplication(sys.argv)
    1 K! z  @3 G, X! D4 d2 H
    1 {3 L& `: w  ]win = QMainWindow()
    & `; w- N; e: C5 T# F9 y
    1 ?- I/ [* P% O7 P; y6 d# |win.setGeometry(400, 400, 400, 300)1 _. i% m$ m5 w) [1 L' C
    + T  M7 @& H' N* C4 T3 d# @( ]+ m" r
    win.setWindowTitle("Pyqt5 Tutorial")
    8 H3 {) @4 x: P
    4 v& I' |) A* zwin.show()- p7 Z- s1 k% |" W6 A* W0 c

    : t, ?, [$ n) wsys.exit(app.exec_())
    3 v3 V/ U* J% ^# `3 @
    5 r* r' I8 Q4 m) @* s7 o) c# o. E0 T% f3 K7 H

    * ^7 K2 F7 b. h: N! D' @) m其中:  K" C# L0 Z. U+ p

    ( X, M* B, j  F' b% \$ JQapplication():每个GUI都必须包含一个Qapplication,argv表示获取命令行参数,如果不用获取,则可以使用[]代替。
    ( r8 k3 P+ `. T# j
    2 m2 M  a2 y/ v1 F' |/ z7 L* ZQMainWindow():类似一个容器(窗口)用来包含按钮、文本、输入框等widgets。arg标识可以获取命令行执行时的参数。
    7 i0 q' R. h6 x' C6 Z- ~  y5 p& q# M7 i1 Z
    SetGeometry是用来定义 QMainWindow() 窗口的尺寸, 语法:setGeometry(x, y, width, height ),其中x,y为屏幕上的坐标点。
    ' e6 N9 d1 o" ~7 E; U4 E$ y0 K5 `, t% |
    show():用来显示窗口
    ( U8 @7 X6 [$ ~0 \0 L! [7 `( ]" }1 v% W' a4 h; E
    exit(app.exec_()):设置窗口一直运行指导使用关闭按钮进行关闭' Q6 F) s7 a1 W3 ^4 `
    6 c7 e5 [% c9 Z1 x6 S' I
    PyQt5支持的常见Widgets有:
    # d2 s" k% [% N  k! o: s- f; j% g  K+ t+ @

    9 g1 c% G7 m2 L
    $ }3 i- Y. }* [6 v# f从上到下,从左到右依次为:Qlabel、QcomboBox、QcheckBox、QradioButton、QpushButton、QtableWidget、QlineEdit、Qslider、QProgressBar8 s$ L: U# V! ~) y! [0 k7 n5 d

    7 T1 @8 l; P1 `9 N& k( W' k对于使用Pyqt5设置文本内容,我们使用Qlabel:4 b$ J% |3 [0 U+ T1 I; {$ ?+ X# B$ r

    8 |& o/ h( D$ M: e$ r: Vimport sys
    ) I/ x/ V3 s- B  ^! h$ ?. x8 D- ^. j- F& p; O8 X3 w3 q
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel3 {5 C6 I) J3 h; H2 O
    , k  G5 q" G4 i' _) z5 |+ g
    app = QApplication(sys.argv)
    " f) s8 m7 G- \- M9 X4 ~8 g) [7 s! D: e
    win = QMainWindow()5 ~1 M& V( C1 f, Z* u
    % ?: t$ ^5 n9 G" _$ E. n5 i
    win.setGeometry(400, 400, 400, 300)
    : A/ G2 [0 ?4 g+ H0 X( V, o, X* Y: T
    win.setWindowTitle("Pyqt5 Tutorial")* k9 X  ]; ^8 M: P
    4 n. _+ g% z* [
    \# Label Text4 q, N2 ^4 r9 S, F4 ~

    ; Z7 Y' I. [8 d0 i6 Zlabel = QLabel(win)
    , h0 @8 l$ b) t5 u4 a- n/ \/ E6 u+ Q/ a& [0 m0 c8 P0 I
    label.resize(200, 100)5 Q/ j6 M1 p% @8 A4 s0 W' Q
    ; I3 q. u" V  [6 a8 m  U+ g( [
    label.setText("Hi this is Pyqt5")/ r( ?; t2 K) d' x

    2 d0 N5 e. K# @9 m5 }6 tlabel.move(100, 100); O, j% `. U" F/ q- m

    & y2 M2 H1 [: Z2 }win.show()
    ! w, l5 V6 L9 d* g# }' P1 J) l1 I& R% e! r! N/ q( B' y, h" n2 `
    sys.exit(app.exec_())
    . c$ l- H& D7 [# a2 l
    1 E' H& [/ R$ h* q( y! P5 Y# K0 a- g6 I$ A* I$ j

    & x, P/ V) [8 s9 k- T按钮与事件:4 W9 U8 u$ H$ _/ r* u: l

    " r% u1 \! ^& e" vimport sys
    % Y+ z5 M0 ?9 ^- b& i) q+ w7 n4 ^; ~* M% n& x0 r
    from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton$ h- n* _" W1 W2 x8 X( f

    : y; V$ Y+ c8 l  F, ~$ j& kdef click():
    ! c0 W6 e! h$ p* s2 t# f
    5 m+ ]9 g' N+ [0 o' Q2 \    print("Hy Button is clicked!")
    8 c8 h9 P* {8 u; b
    7 t& p1 Y3 h0 b. y0 H% Xapp = QApplication(sys.argv)$ J4 L6 W! i) L& L+ ?1 O
    : ~# L6 @% H7 w2 F5 S( g
    win = QMainWindow()6 d. i# S8 l) P

    / G" m* ~% j+ l7 R0 Ywin.setGeometry(400, 400, 400, 300)
    0 C5 Z1 U; @8 J
    ' d2 J2 F# }. Z7 u5 [win.setWindowTitle("Pyqt5 Tutorial")
    & L# s- S8 {; G
      O# t! G# ^. X5 }! _\# Button; k1 r7 [# x- K7 y7 k' [& v/ V2 m

    ( u/ H% D+ ~4 e/ _9 K5 X3 Abutton = QPushButton(win)
    # C) O( T- S& o# G- @$ @/ r2 x- v7 a8 M6 D6 `9 G' u+ R' v
    button.resize(200, 100)
    / Y+ }1 P. q2 A
    , ^2 I, a7 h5 r$ |- l* {button.setText("Hi! Click Me")5 I8 v6 Y! ?. P7 ~5 p$ w( D. d

    . M. h- ^, G3 Q' U0 }# e% E' Kbutton.move(100, 100)- k- C6 _0 L1 N( I
    : R. m, C( @; p7 O4 c4 B5 a
    button.clicked.connect(click)0 V" Q8 @+ p! y) j
    : y2 E0 W# e5 V8 A, j$ |
    win.show()0 Y& a2 x  ?* t# A, l
    9 M1 Z- K6 g1 L! ?4 r
    sys.exit(app.exec_())8 B* Y! p+ O" q& O( G! l& N; `
    ! `! x3 Q8 v3 K2 V. a% Q9 @/ H4 m( V
    6 w( M' a! z& d' u8 ?% G3 I
    $ [" D/ o4 r7 o9 t6 Q4 b7 s( L
    button.clicked.connect() 在按钮点击后执行特定的事件。
    , S, P- i: t, r8 W  P7 @, T) H: E! F
    PyQt5实战
    : D, [! z. S* l" x+ {( I$ p* [$ e% y+ l& v$ C
    实战项目:简易的天气查询软件
    ; S8 b8 Z) i' ?3 R, ]
      m, @; M# Q- w2 q1、使用Qt Designer设计一个界面
    7 I( Q) n- r. q7 }8 @% V! [, a, B! b+ J8 f+ c3 M
    . m9 g; {: ~  T5 v8 ^

    4 m. M( D# }8 r5 r" y4 ^用到的控件有Button, GroupBox, Label,ComboBox,TextEdit,同时定义了两个按钮queryBtn及clearBtn,分别用来查询及清空天气数据。我们需要绑定槽函数,方法如下:6 O$ T+ [. s- k& S) s( P
    - c' Z$ Z% X) p, H# c' u, l
    在Qt Designer右下角选择 信号/槽编辑器,点击+号新增* K5 l, ?$ i6 b4 z1 @
    + _- x+ s; R! l8 b6 C9 G7 j
    分别选择queryBtn及clearBtn,选择信号 clicked(), 接收者 Dialog 及槽 accept(),(槽函数这里不知道如何定义,后期在代码里再进行修改)
    0 S9 G. |: Q- m' v2 P- m  d3 l) \3 W
    以上完成后保存为Weather.ui文件。! d0 @$ B4 t& a( e5 F  W! R6 C
    ; W  l: F! M$ g
    2、转换.ui文件为.py文件! `2 P5 F) p1 F8 w; I7 g

    - r1 K) m3 ~5 D( q% I8 X/ F( qPyQt5支持直接使用.ui文件:( a6 b$ o& _7 Q) R5 y# W
    # Q& s/ x1 s# S, F9 s" O- X, v
    import sys
    & `" V4 `# F9 S) E6 g6 B. `9 e, x: T$ n! n% A$ k
    from PyQt5 import QtWidgets, uic- G/ z6 P2 _6 T' l* B, s
    ! W/ z' \: t% h5 d) h
    app = QtWidgets.QApplication(sys.argv)
    8 L4 x7 a' b$ t- M+ E9 M1 g* O! L" R! H3 m3 V1 Y1 i
    window = uic.loadUi("mainwindow.ui")
    ( C4 [3 S8 m  k( \7 o: P& `6 L" ~$ _- O9 Q
    window.show()7 {$ i4 N+ x/ l* @% S  b
    - |6 G4 y( c5 d. B( \% a5 q, @1 _
    app.exec()3 @0 l) u: @4 V# U- z
    但是为了更好的自定义及修改上面的槽函数,可以使用External Tools – PyUIC,即可生成Weather.py,实际运行命令如下:. T  R% z, ?: T2 f  ^6 v
    + Y* L! B; b5 r* }/ M
    D:\Program Files\Python36\python.exe -m PyQt5.uic.pyuic Weather.ui -o Weather.py' z1 p' J4 b6 F- ~9 U
    其中,我们需要把两个按钮绑定的槽函数:7 _. T' v+ f1 U& v3 l8 W" q4 t+ M

    ' M. W7 c1 A* F\# self.queryBtn.clicked.connect(Dialog.accept)
    & X% k2 W3 W% l$ ~, n3 Z0 k
    3 w2 W' y, Q# W- V\# self.clearBtn.clicked.connect(Dialog.accept)
    $ X' ^! M' B4 X2 I' M& i% \- d2 F
    \# 修改为:' E: n  J4 _  ?  t7 h& K
    & o5 L7 G0 Z* R: E' J9 E) ]! k) U
    self.queryBtn.clicked.connect(Dialog.queryWeather)) d3 m6 F: S0 l  f* w# n
    ( W; x. G: w  E; M5 F
    self.clearBtn.clicked.connect(Dialog.clearText)
    & n. v1 t+ {, l6 O- x  w最终的Weather.py内容如下:) J: ^* U' h1 ~. ?- L9 V* q' d1 m

    ( B1 T/ G: t& x  I\# -*- coding: utf-8 -*-) a; g- X. u6 A0 K: O6 h

    , i1 [  D3 O- ?' m' _" \1 \\# Form implementation generated from reading ui file 'Weather.ui'
    ' a/ b0 T) r8 _+ d$ P5 s  ^& ^' `( N4 h' N9 ~6 R
    \#% I) e8 d, X1 S  [# T  S& y( @
    , E2 g" x5 n" t0 q
    \# Created by: PyQt5 UI code generator 5.15.45 j; x' T' ~9 j, D; k
    ( A; I! m0 ^2 L: w5 T9 W
    \#
    5 A" s) _" p  H* z+ H' h% K% }/ m
    ) E; @+ E, P8 B! F; ^\# WARNING: Any manual changes made to this file will be lost when pyuic5 is
    7 A$ _1 ]+ x/ Y2 I" o0 x+ a$ i( y/ m" d- N8 B2 T' F2 U
    \# run again.  Do not edit this file unless you know what you are doing.& z% O! o& L+ q7 _* }- N6 N

    * A2 R* d! F. v& R! @, zfrom PyQt5 import QtCore, QtGui, QtWidgets! Z: A6 j- M1 C1 r# v

    8 }" @* M; h! R$ D) t# dclass Ui_Dialog(object):
    3 C* d0 t( f3 I! o* {2 ]8 W0 G3 S4 d- l. r. F
        def setupUi(self, Dialog):
    7 F$ H- d; [- p  k3 U! W* M; r/ d. q
    ( `1 \# Q: N6 F, W4 J/ e        Dialog.setObjectName("Dialog")3 C3 Y8 @8 ]/ F$ o: O! V( j+ y

    ! B, N7 k  S, ?- O4 k& A        Dialog.resize(600, 600)
    & u0 L0 X/ D. Z( w" m
    0 [' s0 y6 p4 x        self.groupBox = QtWidgets.QGroupBox(Dialog)3 [6 M0 Y8 @6 R, x7 K3 b4 W! m
    & F  R8 B: q7 ~; {1 N
            self.groupBox.setGeometry(QtCore.QRect(30, 20, 551, 511)); L# T: X" J4 ]2 N
    6 V1 z; E4 n( K; t- S- A/ h
            self.groupBox.setObjectName("groupBox")7 r- _0 `/ D% i% J
    , j, A% E9 z/ Y, e6 D& S
            self.label_2 = QtWidgets.QLabel(self.groupBox)6 v( u4 k, [2 q4 Z( V, Y  \7 q5 L

    4 V. R! P; i6 L# }: i        self.label_2.setGeometry(QtCore.QRect(20, 30, 31, 16))$ P3 I+ o' R* T6 w0 v) o8 Y
    - y. ^2 p( h/ D1 k9 p5 t7 y8 N
            self.label_2.setObjectName("label_2")4 W2 x4 t+ C! z- x+ B
    1 V3 U% c- T0 h% _2 w1 V/ Z
            self.comboBox = QtWidgets.QComboBox(self.groupBox)! U9 ?& \2 S% o+ @$ f

    6 Q  ^4 ?8 e* a; z; K' ]; O        self.comboBox.setGeometry(QtCore.QRect(70, 30, 87, 22)): z1 X- B" p) W: W- R

    % z" g2 }0 a% O+ U, c3 d/ d+ u        self.comboBox.setObjectName("comboBox"); d4 V6 j( T% T+ \. k8 y

    4 U8 `3 Y( l: X  M        self.comboBox.addItem("")3 w5 f' N8 H9 I7 t) E& v/ d

    ! Z- g: k) z7 A# p        self.comboBox.addItem("")
    4 ^; q! A5 Q  ?" I, G5 v+ n0 V) n4 X- l: J/ r, A
            self.comboBox.addItem("")' l4 I( |' Z$ x1 o$ |- z! Y! c1 m
    ) U; ?: x$ J# G$ ^) p" E
            self.textEdit = QtWidgets.QTextEdit(self.groupBox)
    , [* H4 @: w$ U6 y2 _0 N) h; l( l& q7 Q  N6 c/ W" ]
            self.textEdit.setGeometry(QtCore.QRect(20, 70, 491, 411))
    6 y; w+ m3 s0 Z6 K' c7 p7 u6 E, ^8 _
            self.textEdit.setObjectName("textEdit")0 I% t4 e* s6 c8 c6 n

    * l( a8 j# D7 x! r1 h        self.queryBtn = QtWidgets.QPushButton(Dialog)
    5 i  r( S/ i- f. k
    6 r3 f$ }" o+ y+ ~  j        self.queryBtn.setGeometry(QtCore.QRect(490, 560, 93, 28))" [9 ]; n" G) \

    - t$ e5 W2 U. T8 @        self.queryBtn.setObjectName("queryBtn")* b- v4 l  R) h9 o2 m8 t0 ?7 E
    " n( E) a. ~; u
            self.clearBtn = QtWidgets.QPushButton(Dialog): X- p% B% n3 |# @

    ; s5 J! r& K# Y        self.clearBtn.setGeometry(QtCore.QRect(30, 560, 93, 28))
    7 w& |4 G: X# r
    & Y" B, _( u! ^( u+ M        self.clearBtn.setObjectName("clearBtn")
    6 D. T, Q4 v; Z- g& q+ J
    # v; {( U  k$ m        self.retranslateUi(Dialog). x& I  Y& E+ P/ Q, W

    6 s! x0 ^1 x( H0 v- Q; h        self.clearBtn.clicked.connect(Dialog.clearText)$ F1 x0 p! t' ^0 `/ _

    6 H; t' W) F7 \6 f0 v; g        self.queryBtn.clicked.connect(Dialog.queryWeather)( B, d. N# O& w4 E+ x5 g
    1 F5 C5 W% D! f3 i& z$ R" j
            QtCore.QMetaObject.connectSlotsByName(Dialog)1 ?7 Z" h+ w" o1 `
    2 i6 ~( ]" X4 x& w' B
        def retranslateUi(self, Dialog):
    0 m' W0 p# a3 K& V6 m. z" |1 F; g' a7 X- r0 z
            _translate = QtCore.QCoreApplication.translate' L1 n% }6 z( L% V  r9 }
    - X/ s9 h( {3 P- [) ]5 d. e
            Dialog.setWindowTitle(_translate("Dialog", "Dialog"))8 W* {7 u4 _, }& I/ m
    $ e; B: V  `; W" o" N2 W* d/ m
            self.groupBox.setTitle(_translate("Dialog", "城市天气预报")): `3 u: m& ?- b( @/ c0 z5 Y7 `1 u/ |

    . W& r( p+ L3 e! s        self.label_2.setText(_translate("Dialog", "城市"))
    ) L' a: S4 Z- c, H. N; P
    - r/ k# P! ^0 B' |* z' F: m& X        self.comboBox.setItemText(0, _translate("Dialog", "北京"))
    ; H3 @! y: i- Y. a* {$ s% j* o- A4 A+ i/ e# c3 C: v  E; L
            self.comboBox.setItemText(1, _translate("Dialog", "苏州"))
    7 v$ h1 T" L% a, n5 B3 J4 ^1 D1 U  d- ^# h" \
            self.comboBox.setItemText(2, _translate("Dialog", "上海"))8 {' B( S4 g8 Q9 s0 Z% ?8 S* f
    8 [8 v( v9 I5 T; r
            self.queryBtn.setText(_translate("Dialog", "查询"))
    % a% m# X8 e" s2 I2 U! x" r1 S5 ?5 p1 N6 ?
            self.clearBtn.setText(_translate("Dialog", "清空"))% ^) U# i1 W# l9 {, K5 t
    9 I+ v7 J+ I0 f. A9 e
    3、调用MainDialog
    / K/ n) k$ E+ m. g) t; ?* H
    ' A  A: g0 @. E) Y3 P在MainDialog中调用界面类Ui_Dialog,然后在其中中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。新增demo.py文件, 在MainDialog类中定义了两个槽函数queryWeather()和clearText(),以便在界面文件Weather.ui中定义的两个按钮(queryBtn 和clearBtn) 触发clicked 信号与这两个槽函数进行绑定。
    9 y$ |4 u& K& ]) o
    8 [9 L  |0 H6 b, [- L完整代码如下:# ]! V, h5 h; G: x: f

    + \% f  @6 t9 J! {; b" k/ k$ a8 vimport sys6 P) {; d  u+ J% Z* V; z% U5 N
    8 a, n0 o( |8 @. R. r9 U
    import Weather5 X" }# D& ]+ q; @+ e3 d& M
    $ g9 W6 `/ r1 d4 J% K. U: ~
    from PyQt5.QtWidgets import QApplication, QDialog
    ) [( _$ P) k9 ]) c
    ! X% z- `/ i& t% u/ k1 dimport requests
    9 ?/ x# Y% b( W  [) N
    - ]3 \$ a" a) \% m% h+ g4 M7 cclass MainDialog(QDialog):
    3 Y0 K' O1 p/ }8 l
    6 w! @# h* o' r( w& Z! G; E    def __init__(self, parent=None):
    8 x! z4 y2 R8 c2 u8 T+ I: d* m$ @$ A
            super(QDialog, self).__init__(parent)
      |  l6 j4 e" H' d8 L7 w' X3 t' t! }( u. g9 |, w# a& V' i
            self.ui = Weather.Ui_Dialog()
    7 h7 Y. U0 m7 q+ @: r! w
    5 {$ ^9 Y9 m/ {7 n( q! M        self.ui.setupUi(self)3 s# ^4 D5 O+ l# f7 O% z/ i7 ]

    7 F9 k! _, ]; {; F5 y; R5 O' K    def queryWeather(self):* m+ A+ Q4 S9 ^8 g& t

    7 ]  V9 _) g. Y, j* ]* j& f. z2 c% r' I        cityName = self.ui.comboBox.currentText()
    7 s6 J! G+ ~% i
    ; F" G! S' \# }  ?0 C9 q* c        cityCode = self.getCode(cityName)
    & Z+ m* A( u: N* n1 h2 }+ L0 @; I' u; `6 o) x
            r = requests.get(
    ( {5 ~5 b9 O/ h, `2 B9 ]  ], L
    : R" q$ I0 G  j$ `- M            "https://restapi.amap.com/v3/weather/weatherInfo?key=f4fd5b287b6d7d51a3c60fee24e42002&city={}".format(
    3 U: D. f! \3 q5 G5 |( ?+ j) O8 @9 F; E
                    cityCode))  {4 U* ^& ?, w

    0 h- U$ Z: i7 D3 C- M6 {        if r.status_code == 200:* r! _' `4 t6 b1 s0 a
    % c) z7 C) ?) k) @/ p+ y9 |2 m
                data = r.json()['lives'][0]4 y8 a5 h: g+ s; ^7 U
    - s7 ^- E: w5 P% o' t1 B# v0 z
                weatherMsg = '城市:{}\n天气:{}\n温度:{}\n风向:{}\n风力:{}\n湿度:{}\n发布时间:{}\n'.format(7 Z' {' g" ?6 A
    7 S! _& z0 U) d8 H2 A
                    data['city'],
    / M( [5 D' E/ k3 j5 @" R+ E) z! ?2 b. S, r/ h7 h; \0 H
                    data['weather'],# w% E/ K. ~0 j! a0 g3 t2 F) ~

    4 b& x, q) Z/ f. [( h5 R                data['temperature'],
    5 k/ I( g: i- A2 Z8 @% g4 `+ \$ D# m0 C) d) g
                    data['winddirection'],$ A  B7 o6 j1 Z' _$ o; o2 U
    ; c! |& |7 k/ ?
                    data['windpower'],7 O) R# `% Z  l* J  F- A$ v

    4 v3 a& X3 V5 D9 Z: T) Z                data['humidity'],
    ; @5 V  I" Z& x: p
    1 R3 P: x5 }) G( z% N                data['reporttime'],
    " V8 F8 k( h4 Q" g5 Y
    # E- j" e+ e$ L3 [) u            )) |; r* U9 w) u
    ' C9 H3 m2 I2 q! E0 ]
            else:1 [! J8 y/ D+ t7 G1 J6 I. T
    2 i2 ^5 _7 i5 F
                weatherMsg = '天气查询失败,请稍后再试!'
    6 ?( B8 Z6 S3 X) I. q, Q' @/ o5 r3 q- X1 \7 Y: n$ `
            self.ui.textEdit.setText(weatherMsg)
    3 w- G$ _4 s; b. M# P5 s, E! i7 a/ i1 I5 i2 [
        def getCode(self, cityName):
    & r: \6 Z! b% T9 N. M& s  H* D5 ]0 L6 s
            cityDict = {"北京": "110000",- m/ n# m0 Y; V, ~% i; v
    2 J: q" r% M% r8 J5 T& P3 R
                        "苏州": "320500",6 C) F# V1 C1 y' s# ^# R
    ) x0 H. f  h- ^( b" q2 w; [1 T
                        "上海": "310000"}' o, O. |) M& Y) V6 H
    - D/ l8 H1 L/ y$ b& ?6 r) g) L
            **return** cityDict.get(cityName, '101010100')
    3 _0 v7 s5 y2 ~4 w  y
    * p( S2 N3 i+ a+ ^9 o    def clearText(self):
    ) _, V2 P. Y3 a- |5 |! C# y# a! u' ^4 A; c  E
            self.ui.textEdit.clear(). I# q0 \) p% R! v

    . f' k! s- \6 m$ wif __name__ == '__main__':
    - S( A( S1 I% P  ^5 T) a) n9 S. L1 C: e% N( \; g: \5 L
        myapp = QApplication(sys.argv)
    ' q1 B% v" c5 N2 J# o6 {$ j
    1 ?7 k$ D/ l  x2 S& U% h    myDlg = MainDialog()
    ; s& C7 a9 X) T, N7 B, P0 \( q' L4 Q; G, Y
        myDlg.show()2 T, Y/ j0 b/ Q
    5 ]% B! d& b( {2 T* s' ]
        sys.exit(myapp.exec_())
    $ p$ d2 N9 P7 V; [4 g" Y
    ! h( w% Y. T* a; E, D4 N* e运行demo.py并执行查询后的效果:
    5 Q4 U/ ]% i2 h% A  ^+ Q* T3 _8 C4 {* U: c( w- U7 w" s3 @
    ( F; o" Y0 e, x+ N

    4 V. E- O7 l. P) s$ O4、将代码打包成exe文件
    $ C7 O7 F2 \* L- |9 d* U, q' N, P/ \, N( N
    将.py文件打包成可执行的exe在Python中称为freezing,常用的工具有:PyInstaller, py2exe, cx_Freeze, bbfreze, py2app等。功能对比:2 G1 L) p: v# m7 }. j: X5 O
    . L/ O4 ^  y1 v# Q' L$ i
    5 h0 i; o6 ]( \/ [5 f9 [, g2 }: i

    : O, J- Y  d8 Lpy2exe:软件更新已经不活跃,因此也就略过。; T0 k+ S, c. h! c0 w6 v8 W5 b

    2 k2 R0 z3 @4 E' @! {) Lpyinstaller:明确支持win8、win10、理论上支持win7,,支持apple Macos, linux。pyinsaller可以打包成文件夹形式内含exe入口执行文件的形式,也可以是一个单独的exe文件。+ h9 k) J0 U* x2 @5 k# s

    " p5 E/ I8 A8 O3 M, `) T  gfbs:基于PyInstaller,使用起来更加方便% ]2 Q* s' f6 G; {/ @9 z
    % C$ C7 ^$ G1 ?2 v; `
    这里选择了fbs来打包。fbs的安装方法:
    : ?7 r7 w% x" g" L8 X
    & Q2 ^) r, y" Rpip install fbs
    7 l) L& K( \3 Q: m使用方法,在命令行中输入:
    " ]' Y3 O# g) }/ q
    ' V) q  U% u) ^) k" Mfbs startproject* O- N: q6 f. Z$ n- q+ ^
    执行完成后需要输入一些APP的名称等。完成后会生成如下目录:
    2 p- H8 q* c& N& T2 W/ j5 F! o" h, \" l  z) P7 g! c

    3 }/ R0 X% X) I" X/ S+ [/ h. G  \9 {0 X' F
    将刚才编写的PyQt5的代码(demo.py和Weather.py)拖到src/main/python文件夹下,删除原有的main.py,并将demo.py修改为main.py。然后打开 main.py,在文件头部添加如下代码:
    5 v- Z) {1 X$ m8 S8 E) P; [
    ( t5 I4 w* }# M1 ]8 x7 ~  T9 z5 ?from fbs_runtime.application_context.PyQt5 import ApplicationContext+ x  n5 @9 U5 x2 P6 T. J, n; L
    ```- B' S6 D: z9 \, y/ `5 Z8 Z
    完成后执行:
    9 t  r3 W* {, g1 q( f```
    5 [2 O' ~& P6 @5 }fbs freeze4 k" N: T& Y# @2 @4 Z
    ```* C* Y0 {, l( w
    即可实现打包。生成的exe可执行文件在\target\MyApp文件下。
    6 O( W; p! i: y1 ~8 \1 B( r. v% F) A1 J5 _
    ————————————————
    ; a6 v& e( o9 t版权声明:本文为CSDN博主「宋宋讲编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。1 _3 i" D& c" N9 b  B6 t5 c: F
    原文链接:https://blog.csdn.net/qiqi1220/article/details/126289667" X5 G  G) }; ?# B" l" c2 I2 b
    9 C! r1 M( ^: Y- }( H7 D+ S

    " f( k4 g6 E/ d( W8 x% S
    2 c! A# y. K4 v" `1 ]- O/ [3 z
    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-9-22 16:06 , Processed in 0.694849 second(s), 51 queries .

    回顶部