QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2233|回复: 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使用指南!
    . R3 O* |5 a9 c0 s$ O7 U! p" c, m! N; O0 i3 O% t
    使用Python开发图形界面的软件其实并不多,相对于GUI界面,可能Web方式的应用更受人欢迎。但对于像我一样对其他编程语言比如C#或WPF并不熟悉的人来说,未必不是一个好的工具。( v7 f0 A. |  \& ]4 h5 _' G' T

    1 _' E$ v# p4 w3 b8 D常见GUI框架
    $ t! B& `% i8 v# K/ h" ~) t$ E3 h9 m: m& n  _
    PyQt5:Qt是一个跨平台的 C++图形用户界面库。QT一度被诺基亚拥,后出售给芬兰的软件公司Digia Oyj。PyQt5是基于Digia公司Qt5的Python接口,由一组Python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。
    3 ]0 }& ^7 H5 l
    + f4 w( F$ X+ W$ |9 j  [$ c) [& MPyside6:Pyside是QT公司官方提供的Python包,上一版本为Pyside2,对应的是QT5,最新版命名规则进行了调整,更改为Pyside6,对应的是QT6版本。由于官方出品的比较看好,缺点是发布比较晚,网上的资料没有PyQt5多。1 I: W5 \$ W0 @& H# `9 Z

    . X7 |4 f5 e- e* a  E. [Tkinter:Python内置的GUI框架,使用TCL实现,Python中内嵌了TCL解释器,使用它的时候不用安装额外的扩展包,直接import,跨平台。不足之处在于UI布局全靠代码实现,只有15种常用部件,显示效果简陋。7 B' H8 }; w" K' C

    : w; P# O' k& ^; fPySimpleGUI:PySimpleGUI 是 Tkinter 一层包装。使用 PySimpleGUI 实现自定义 GUI 所需的代码量要比使用 Tkinter 直接编写相同的 GUI 要少得多。
    2 d' G' b  o+ J) t! ~0 k, V. R  m" l) X" A: R, \
    WxPython:wxPython是Python语言对流行的wxWidgets跨平台GUI工具库的绑定。用得比较广泛,跨平台,C++编写,文档少,用户可能就需要根据编程内容对不同平台中的GUI代码做一些调整。遇到问题不好解决,代码布局控件,不直观。! ?9 a' i9 F! Q' `6 K4 f7 i
    ) Q2 d1 T% X" l; }; Q1 J2 V# V+ \
    Wax:基于wxPython ,为克服wxPython的问题而制作的一个包。' p; M7 d! C7 P2 E1 `) M! |
    ! K6 b7 B" }! L9 a
    Kivy:主要针对多点触控程序,智能手机平板等,也可以在没有触屏功能的系统上,全平台支持(Windows, Linux, Mac OS X, Android and iOS.)使用Python和cython编写,中文支持差,需要自己下载中文库并且制定路径。
    4 R7 A5 \( V, r% q4 X( h- s. M: k4 i
    BeeWare:Write once. Deploy everywhere.需要与Kivy配合使用。
    , |+ h4 q2 J0 D; n' j, f$ _, T4 g
    1 v% S4 Y8 v2 g* [Toga:一个使用Python开发原生APP的GUI工具包。Toga由一个具有共享接口的基础组件库组成,以简化与平台无关的GUI开发。Toga适用于Mac OS、Windows、Linux(GTK)以及Android和iOS等移动平台。1 H) D# q# N! \
    $ P* j8 `0 {$ J& k" C
    Eel:一个轻量的 Python 库,用于制作简单的类似于 Electron(但是比它更轻量) 的离线 HTML/JS GUI 应用程序,并具有对 Python 功能(capabilities)和库的完全访问权限。
      O/ W3 A" `, o) ?* [7 G1 P' h$ s" r. ?3 a$ a1 J+ W1 [+ |
    Flexx:一个纯 Python 工具包,用来创建图形化界面应用程序。其使用 Web 技术进行界面的渲染。你可以用 Flexx 来创建桌面应用,同时也可以导出一个应用到独立的 HTML 文档。因为使用纯 Python 开发,所以 Flexx 是跨平台的。只需要有 Python 和浏览器就可以运行。" W6 `' O  r/ F3 T7 d
    ' ]# Q' i- c/ w% `" v2 B: f
    pywebview是围绕 webview 组件的轻量型跨平台包装器(wrapper),它允许在其自己的本机 GUI 窗口中显示 HTML 内容。它使您可以在桌面应用程序中使用 Web 技术,同时尽最大可能隐藏使用浏览器构建GUI的事实。4 |) |* @% r0 v

    $ f6 u$ I$ P! |/ \3 ^( s6 _enaml:一种能够让你用最小的努力就可以实现高质量GUI界面的的Python框架,也是一种独特的编程语言。enaml将声明性语言与基于约束的布局系统结合在一起,使用户可以轻松地定义灵活布局的UI。enaml应用程序可以在任何支持Python和Qt的平台上运行。
    ( b+ N% u0 D4 \6 L  Z# Y5 R. Y+ F9 @' m; r6 E0 m
    个人想法:太多学不完,先学PyQt5,原因是资料多,学有余力再学pyside6,最后看下PySimpleGUI,看能否解决一些简单问题。
    / p% q* L- l7 w: G* Y( B" \
    9 S7 v0 a( e- PPyQt5简介: N2 ^8 s% a/ ]. Y4 C; X
    + N* H( Y$ Y2 {1 y0 p, h1 S6 r
    PyQt是Qt框架的Python语言实现,由Riverbank Computing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件,因此PyQt的API接口与Qt的API接口很接近,但PyQt不再使用QMake系统和Q_OBJECT宏。! b) j! ~; k+ [9 K0 F

    4 T4 ?+ A* q0 ~) lPyQt5提供GPL版和商业版证书,自由开发者可以使用免费的GPL许可,如果需要将PyQt用于商业应用,则必须购买商业许可。0 w4 ^% g  X3 k7 _* b6 E
    ( v( G6 u. V# u! g( H
    PyQt5特性如下:
    1 l1 Q- ^  F7 ^6 L1 i- W) {  {9 l! V2 Q6 O
    基于高性能的Qt的GUI控件集。
    - O! M+ I1 p: |, E% V1 d
    ; h2 G. Y: q: f' R3 S能够跨平台运行在Linux、Window和Mac OS系统上。1 W- ^/ D$ b! H0 d' v' b4 a% F
    - D: |# t& j8 ?& a0 `0 D( V8 E
    使用信号槽机制进行通信。1 E7 |# G# K6 C1 z5 k9 A

      x5 p* q; W7 X9 R  \- H对Qt库进行完全封装。
    ; Z) ]! W' q3 G3 _1 G
    + h; a8 [, [8 C* `3 B2 c4 b3 q可以使用成熟的IDE进行界面设计,并自动生成可执行的Python代码。# @- w' U+ t: p# C" g, e
    * v# ?) U6 }$ a. x) a
    提供一整套种类齐全的窗口控件。
      D& q( Z0 {: h2 S* D7 F  d/ u6 Y' n; ?1 ~
    PyQt5是由一系列Python模块组成,有超过620个类,6000个函数和方法,主要模块如下:
    , z* n/ j/ g- ~: ~2 w1 p- l3 g+ c- }
    QtCore:包含了核心的非 GUI 的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime 类文件、进程与线程一起使用。  x9 s- K& E0 E5 e, q9 o

    8 f7 l% x) g% M" {" n) u5 l" oQtGui:包含了窗口系统、事件处理、2D 图像、基本绘画、字体和文字类。
    0 B0 M3 ^% D& b0 G
    ! e/ \* `! f1 |QtWidgets:包含了一系列创建桌面应用的 UI 元素。0 m1 s/ I* z0 i* ?3 a+ I

    3 h. X+ s5 r+ k' nQtMultimedia:包含了处理多媒体的内容和调用摄像头 API 的类。6 z& u, u- U$ C& Q2 p8 n& X

    * v1 [: f$ E9 t8 L! J( e& BQtBluetooth:包含了查找和连接蓝牙的类。2 v# L2 k; w/ Z1 K# \- |$ A; X

    ( M. |/ K% E& ~" u7 rQtNetwork:包含了网络编程的类,这些工具能让 TCP/IP 和 UDP 开发变得更加方便和可靠。: ^3 Q* M, e; c5 h) Q

    % J+ R* i4 I! R8 ZQtPositioning:包含了定位的类,可以使用卫星、WiFi 甚至文本。
    . o: j# m7 e' s- t& d
    * s& l6 j+ L6 S/ `7 q# ?Enginio:包含了通过客户端进入和管理 Qt Cloud 的类。
    * V! k) K0 v, P  E+ }! q1 ^) W4 X! G1 o9 A( c) x
    QtWebSockets:包含了 WebSocket 协议的类。7 P0 |; {; Z* i" I2 G3 v
    + N. c: n6 u, m+ G
    QtWebKit:包含了一个基 WebKit2 的 web 浏览器。
      |) V" p. D/ n8 P! h7 z: y& J, U
    # A6 u7 h0 _( B1 b. U5 }9 xQtWebKitWidgets:包含了基于 QtWidgets 的 WebKit1 的类。0 o! Q+ O' H4 q% n# S2 R

    ( Q5 b! s; o* CQtXml:包含了处理 xml 的类,提供了 SAX 和 DOM API 的工具。; r, U2 Q  W8 H  x

    / h3 K. l) U5 ~9 b% }2 lQtSvg:提供了显示 SVG 内容的类,Scalable Vector Graphics (SVG) 是一种是一种基于可扩展标记语言 (XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。
    7 a0 a; I# x  s" ^
    0 ^7 ]/ S9 ^" E7 ~8 ^0 |QtSql:提供了处理数据库的工具。# a( F  J0 l1 ]

    & W8 Z! M7 h! e3 ~QtTest:提供了测试 PyQt5 应用的工具。
    2 m) D8 a1 N& v8 v5 z, n2 {$ B# D7 `. C5 J/ ?( @- Z
    PyQt5的安装: `$ W% [9 P; q: x$ J6 o

    , J1 D. ?6 K# W( g' ]- W由于后期要使用fbs进行打包,fbs对Python 3.7以后的版本可能存在兼容问题,所以我选择了Python 3.6.8进行了整个环境的搭建。主要内容为:Python + PyCharm + PyQt5 0 v/ b: I! Y( m

    7 S- K% V/ Z! K- p# E安装PyQt5
    : D$ J/ P( L1 p8 n+ T
    3 F8 k3 N0 `, opip install pyqt55 S2 O0 p6 U. K* \8 a3 Q
    7 w* }9 R- @, h* @- @
    pip install pyqt5-tools
    - p9 o8 R4 Y8 Y- l其中pyqt5-tools为Qt Designer拖拽式的界面设计工具。安装过程中可能会报如下错误:
    + R; W) P! p* `
    . E. t( d% r+ X, z8 p+ U: C2 Iqt5-tools 5.15.2.1.2 has requirement click~=7.0, but you'll have click 8.0.1 which is incompatible.; T0 W$ c; l% j, Q0 X% u, N" j$ x
    解决方案:  @+ H2 H& V& R5 d& \0 _; X
    " D# ~3 D3 R# i" a! z
    pip install click~=7.0
    : f$ `0 H$ v4 m! gQt Designer的配置
    3 T( D  v& }8 q+ E( o3 j+ l! o
    : ^7 c, z5 G  C) aQt Designer 是通过拖拽的方式放置控件,并实时查看控件效果进行快速UI设计。
    / l* g8 U4 E( o4 C# u8 R. B3 w/ _1 Z5 f+ w- N

    + c) T; ~3 a* u. }' g! L# C) {7 q- P% O
    整个画面的构成:+ d* q8 j* t# S
    ! x* b  m: l7 j1 i4 |9 J+ s
    左侧的“Widget Box”就是各种可以自由拖动的组件' M- g  n9 [. B( O: d
    # C& f5 B& _3 F, M1 \3 R* k5 x
    中间的“MainWindow – untitled”窗体就是画布, n7 g5 U  O3 x

    ) u/ R5 t- T9 h' L右上方的”Object Inspector”可以查看当前ui的结构& p6 T& E5 B+ o$ g

    8 l9 y2 `0 M: z2 E右侧中部的”Property Editor”可以设置当前选中组件的属性0 a) U- Y2 A2 i- m$ f& y- ^9 m

    3 e+ d2 o3 V) ]- B3 b6 W  k右下方的”Resource Browser”可以添加各种素材,比如图片,背景等等
    - k; v3 G. x2 y% U: N9 A8 u" W- |8 S
    最终生成.ui文件(实质上是XML格式的文件),可直接使用,也可以通过pyuic5工具转换成.py文件。
      j' Z- Y& N1 q, t# Z7 [
    & S" u3 I% Q  @3 bQtDisigner配置1 z6 \9 m, P& I, U- i4 y" P

    8 n0 l1 N' {& C. v* p在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    + r$ g, m2 ~2 x2 ?- \! ~( y( C& H: R+ v0 m
    Name: QtDisigner" b' M) b4 o5 \, R5 |! ]
    4 c4 y% c+ o, _
    Program : D:\Program Files\Python36\Lib\site-packages\qt5_applications\Qt\bin\designer.exe # 请根据实际修改
    ' e; {+ \; K2 Y8 J+ n1 F3 u4 u
    - [% I+ q( S6 X4 z' L$ R& k6 KWorking directory: $FileDir$
    5 Z2 f2 m9 U+ i; YPyUIC配置
    + e# N8 C. b) v% U3 X  y6 H- [0 s; I3 l
    PyUIC主要是把Qt Designer生成的.ui文件换成.py文件。
    " j8 u0 C, O' z$ J2 ~- E8 ]( P- W/ S# |" I% N7 E/ {4 l
    在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:( y8 Z5 @2 H- H' S8 a

    ( }6 L* }. j8 u+ ~Name: PyUIC
    & Q6 F. t; s8 ?, ]+ a$ N
    - i' W9 b8 O/ g% d1 s2 LProgram : D:\Program Files\Python36\python.exe # 当前Python目录,请根据实际修改+ e3 R, V* H! i! }

    ) ]) z# @% X1 }) BArguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py  I4 K2 C$ g( [' M& O8 ?
    * V( I* D4 [( a/ s5 I
    Working directory: $FileDir$
    " f% O4 S, V( bPyRCC配置
    + y/ H) J; {% X4 R
    7 b7 }" E+ A; UPyRCC主要是把编写的.qrc资源文件换成.py文件。在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:3 q8 K  S; y% J8 b
    ( T! L* A' q8 T# R/ ^: O* D( x' ]
    Name: PyRCC
    $ n$ z2 y$ d  R# y$ a" ?3 B7 e% I6 L$ ?# f
    Program: D:\Program Files\Python36\pyrcc5.exe # 当前rcc工具目录,请根据实际修改
    - |6 @5 U+ E0 J4 l) P1 u5 Z" X- Y$ d& r' H0 V( S1 ?% w
    Arguments: $FileName$ -o $FileNameWithoutExtension$_rc.py3 m. @8 A4 b% l; B

    ; F( l6 w) d4 \" I4 ]* N; {7 KWorking directory: $FileDir$
    2 b4 O, k8 c: W4 jPyQt5使用示例6 F6 o) }+ H" r3 l. @2 {0 \
    . j+ G5 i4 h2 s+ x  F8 s
    创建一个空白的界面:1 X1 H: L7 h/ W

    : w' j, x3 e3 s. `9 D- A) m# S- uimport sys
    9 h0 \% a2 E( t- z" [9 j3 u) {% Y: w7 ~3 q% h& k0 _$ M) d9 k+ b. |
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
    5 |0 ~8 K3 z5 L4 g  E/ }. |; X. Z7 D2 b* s+ O
    app = QApplication(sys.argv)# ?4 X9 R; v% a5 \! o
    ; J- ~: _% `% K$ w
    win = QMainWindow()
    " @5 J+ y. V$ @! ]* d% U! h" Y3 F* W4 T% p7 Y  Y+ Z
    win.setGeometry(400, 400, 400, 300)
    ! [& N( A8 p. O& q
    0 X. w! @5 K- i2 _/ u7 mwin.setWindowTitle("Pyqt5 Tutorial")$ G( ^6 X. O7 Y4 L* B: J
    ( b- R, U' R" L2 S- @- ^8 v
    win.show()
    : a  q  q: O5 j3 a9 B
    ! h, K. B2 X- _! v+ ~sys.exit(app.exec_())8 F  m3 w9 E) {" c: {
    ) J+ {0 D0 o4 j& z  b+ }/ H

    , [; Y( d2 F! I" L* u. E& b
    ) }# V7 B9 S, F2 s4 S: K其中:, n8 V( E. F) a& }( v

    , w- h# e2 t/ t2 k$ gQapplication():每个GUI都必须包含一个Qapplication,argv表示获取命令行参数,如果不用获取,则可以使用[]代替。
    9 [  v1 K" g  ]& n9 H( f; u3 D8 l3 N, r( s$ j5 F& @
    QMainWindow():类似一个容器(窗口)用来包含按钮、文本、输入框等widgets。arg标识可以获取命令行执行时的参数。
    # H1 \& u+ m, E3 ]$ {
    ! l) S" O8 E. BSetGeometry是用来定义 QMainWindow() 窗口的尺寸, 语法:setGeometry(x, y, width, height ),其中x,y为屏幕上的坐标点。5 m: E( D8 V. ?3 r3 O0 z9 L
    + P! Y1 j& _, @
    show():用来显示窗口; }) x) @& ~5 w+ O6 u7 k2 U3 c

    7 b9 ~$ v0 J/ ~; Bexit(app.exec_()):设置窗口一直运行指导使用关闭按钮进行关闭
    $ M1 q2 m- ?! |0 f! v
    * X; `& e/ l+ b7 c- ^. ZPyQt5支持的常见Widgets有:  B9 Y. ]2 D' k& b8 R

    3 |0 N9 _  V. [  S# K: H# B! {; Y9 ]# ^+ `& J, I3 c3 n

    " M9 w7 h7 R+ ^5 [' g% u1 {从上到下,从左到右依次为:Qlabel、QcomboBox、QcheckBox、QradioButton、QpushButton、QtableWidget、QlineEdit、Qslider、QProgressBar8 F  N/ g3 A: |* R

    & z4 N( G: I. a+ `' p# q( |/ W" r对于使用Pyqt5设置文本内容,我们使用Qlabel:% @: C* b4 G, V7 c
      e+ c1 S3 w' i' P1 u( X
    import sys
    0 c5 I  D, n! U% F- Q
      {1 X+ a/ F" `- W" e- `from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
    3 x; `* L: v3 M) H/ @% G7 r
    , K1 {5 z& E) iapp = QApplication(sys.argv)5 X6 Y) ?5 a' I# b: l

    ) w3 k/ e/ A5 h8 gwin = QMainWindow()6 c4 P( y; `5 H: U8 _% X5 S
      v3 J3 }7 B  \2 I6 {6 b
    win.setGeometry(400, 400, 400, 300)& l/ g9 j' e- l2 p) D- z

    8 Z$ L* u& {' K" |6 Lwin.setWindowTitle("Pyqt5 Tutorial")- R% {' {+ [  P8 q0 T9 O

    ( h3 g& h9 t& P7 h2 Y\# Label Text4 B7 _3 i  ?$ `% w

    7 B) @- z  w! q, W* ?7 C5 glabel = QLabel(win)5 u9 S0 f1 [  S/ m- S
    . v8 g4 L: H0 Y& g/ i( K
    label.resize(200, 100)
    , s! v" N8 g% o9 d! X$ A! \/ P9 V' O& I7 K  T# @$ ^) [
    label.setText("Hi this is Pyqt5")  _& @9 W: Y/ t! T# k- J" f0 n
    . q0 s7 R& [9 l6 {' Q7 p( m6 n
    label.move(100, 100)
    0 C6 u+ Y* R+ m8 ^' X0 p, ]: B9 W; @
    win.show()
    * j1 }+ f) T/ |" b' n+ m
    % |  _* D6 o3 \# k+ A% L- Usys.exit(app.exec_())  R5 q8 {; C: F" }6 S" E3 M

    # ]  X4 g% m2 A" `6 b# {+ j
    6 }0 M) t' N. E$ O8 k7 f8 n( j; M; Z( r9 l
    按钮与事件:8 N$ N) \; b2 Z6 _1 F# \7 G. s  b

    ; c! F- F  O2 P' o$ F* mimport sys. t) Q9 R, }# Z( s6 A1 ~4 ^

    * p7 }1 I- n1 Q2 d2 }3 E5 Zfrom PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
    8 a8 z0 J4 Y# k  C2 y
    & a& Q( s6 B% A: @0 e! \def click():# W' Z8 ~% L! w) W1 a
    ' E0 X7 O7 R0 H$ L
        print("Hy Button is clicked!")4 R. F: @5 U  S" l/ J" x' T& ~5 p2 |
    $ |4 y1 ^( g) T* j, M5 |
    app = QApplication(sys.argv)) r- v& b3 _" W4 q8 }. v- k
    # N, X3 x8 L7 a# L4 v) W
    win = QMainWindow()
    3 K. _! p2 j7 {% ^+ q( p$ L/ C  Z% G4 U
    win.setGeometry(400, 400, 400, 300)! g: ]+ n& B3 m

    0 B. ]6 F8 S/ v* U5 J1 j. Mwin.setWindowTitle("Pyqt5 Tutorial")
    , b( M! y; G5 s8 N
    " Z1 _& U- K* o0 X0 F( e3 p/ Q$ ^6 ^/ l\# Button
    ( r& k% z# J# G3 Q5 `  y# {' y1 ]% j/ F1 ]& o. s( S
    button = QPushButton(win)
    ! K) N' {; _/ o3 C8 Q9 a. e' [6 X* |: a$ _  a& [" i$ b4 A8 {
    button.resize(200, 100)
    - h" {3 ?8 i! o3 {% r5 z8 ?7 g" g+ F" `# _: y5 V; _0 V( D
    button.setText("Hi! Click Me")
      |$ C$ ^) s: \7 I9 Z; T/ Y
    , f& Z/ D5 G) q% v" D* b5 Bbutton.move(100, 100)
    # z* [% S+ o3 z/ h; K
    & I: h* y! c: abutton.clicked.connect(click)
    8 R" S7 L" a+ B# n% m
    " z* v% m/ P5 t7 f0 X+ ywin.show()4 v: e- v$ S# w
    ) u1 A) V4 ~/ [8 N7 j: i- u
    sys.exit(app.exec_())" [8 E) o/ V; g/ k$ b
    , _# D4 q' l: ^- Q: a
    ) ~/ T+ _9 @6 ?* k
    4 G0 M# x( E/ c$ O  E
    button.clicked.connect() 在按钮点击后执行特定的事件。9 r9 v! P* p8 ?" B" Y

    ' p+ j% h* b* E& S3 x& I9 VPyQt5实战
    0 D$ |; L$ {/ Q' I! ?8 _& [4 R( v& S$ D7 M
    实战项目:简易的天气查询软件. u, U  C, ]$ y  Z

    & S* t3 r: K! ~1、使用Qt Designer设计一个界面
    ! T' S2 d) b9 _0 V) F) Z3 H' b( B3 |& c5 W% k! d/ R! e8 C

    # F2 f8 Z9 [5 U/ @* ^  P) J, I
    5 n& `9 t, w: Q5 h* A用到的控件有Button, GroupBox, Label,ComboBox,TextEdit,同时定义了两个按钮queryBtn及clearBtn,分别用来查询及清空天气数据。我们需要绑定槽函数,方法如下:
    , a/ H) G$ g- D' d
    ' n( j) n( F* @9 F* X# V在Qt Designer右下角选择 信号/槽编辑器,点击+号新增6 f7 k/ s: B$ ?$ ^+ h) r# J9 r

    $ I# V1 L" [+ @1 `分别选择queryBtn及clearBtn,选择信号 clicked(), 接收者 Dialog 及槽 accept(),(槽函数这里不知道如何定义,后期在代码里再进行修改)) V: K+ e2 j3 L5 _& v
    , J& f- K* [5 `1 ?
    以上完成后保存为Weather.ui文件。1 Z$ b2 U' D6 @; V! X  `4 l
    $ R  b$ f7 ?4 U1 \* _2 q8 k
    2、转换.ui文件为.py文件# [7 Z+ L9 h9 I0 @9 h+ w
    & k4 m  F: I7 J4 k5 p# {0 _5 {
    PyQt5支持直接使用.ui文件:" _& Q$ u. }  g! r) o) E% @

    - \5 I! t7 o5 ]import sys1 {+ d7 c+ U& X
    3 d% ~0 s( Y" M/ ]4 v0 A- Q7 a
    from PyQt5 import QtWidgets, uic7 {( z5 E' N# Q, p2 ~2 e+ D4 z/ j

    ! ]7 x' ^7 C9 y2 _) X, w$ ?5 zapp = QtWidgets.QApplication(sys.argv)
    ; d4 b0 v; Z$ r; ^
    + z0 a. I. g2 F/ ^. _window = uic.loadUi("mainwindow.ui")1 T, h( l0 n. x# L: J! Z

    $ |. K6 I/ x' {" X& M( ~+ X" Bwindow.show()
    * U! ]$ q, A7 d( F8 N9 w. ^2 e4 V7 w( b; S
    app.exec()% R) s5 O- \3 R& ^1 v# A
    但是为了更好的自定义及修改上面的槽函数,可以使用External Tools – PyUIC,即可生成Weather.py,实际运行命令如下:
    4 c7 o. A1 _# H1 }& u+ `. j& L
    4 h+ C" c$ H! [, \: O* q( SD:\Program Files\Python36\python.exe -m PyQt5.uic.pyuic Weather.ui -o Weather.py& }9 y2 s* d% a' Z8 I1 C9 V7 q
    其中,我们需要把两个按钮绑定的槽函数:
    2 y' }0 \' u. U) [" t: h( l5 r' k- G4 ~
    \# self.queryBtn.clicked.connect(Dialog.accept)* X; `9 f3 e% u/ A& Y5 x

    6 F/ }3 N+ ?5 ]" ]) b$ K\# self.clearBtn.clicked.connect(Dialog.accept)
    # a& x3 w* D' X# X0 k' _& w( h6 L- }' g! x7 z; h; W% t# Q; K
    \# 修改为:
    6 @2 k1 E) L1 f/ s' u. _+ K/ l! O" f
    self.queryBtn.clicked.connect(Dialog.queryWeather)% a: Y% k" G& p' Y: t* U5 i1 V* R! C

    # C# h; L5 f8 W! V8 U* nself.clearBtn.clicked.connect(Dialog.clearText)
    " z/ [9 a' D3 i0 f, h; R最终的Weather.py内容如下:
    ! h$ K; |- H* D% O& o* E$ N/ d) G# w/ a5 m3 i" I$ U
    \# -*- coding: utf-8 -*-
    7 ^* n9 O4 y1 s6 a6 C
    $ O* j. v' X) U. _9 j% v/ A! c9 j4 w1 F6 L\# Form implementation generated from reading ui file 'Weather.ui') x' `' s% @/ K* [, p' ^

      N9 Z9 }8 P) e( F* D" R\#
    - u9 R9 k+ @; S3 ]" f1 U8 J1 ~: e  M3 Y
    \# Created by: PyQt5 UI code generator 5.15.4
    5 q7 T( T" w- @" X
    7 G* B5 C# f- G" V2 q\#
    0 Y  R! x' y! ~9 _# R( U8 S/ S- N$ ]1 V. Y' u! f# T% r! u
    \# WARNING: Any manual changes made to this file will be lost when pyuic5 is2 c) `0 I/ g3 }1 b

    3 ~2 k( s2 |7 H6 I\# run again.  Do not edit this file unless you know what you are doing.7 n' P6 w9 q4 O# P- N2 y  _7 A
    ; Y; R7 X4 \, f' W1 ?- z
    from PyQt5 import QtCore, QtGui, QtWidgets% ^/ w+ T/ v  n0 }2 m4 q: U, c

    , S8 }9 h; F3 ^/ iclass Ui_Dialog(object):1 W& N! }* K) D. B8 d3 V7 U
    " X' k: _6 k7 O  g
        def setupUi(self, Dialog):
    - d; d: i% |$ _$ K& U' s& G& Y# ~! I( h* `: {
            Dialog.setObjectName("Dialog")
    # X' ^3 D# N+ L! w2 R; {/ M, d' |7 `# f, e( Z( t
            Dialog.resize(600, 600); O9 u. U9 U) M( p- x2 E, |

    + H+ C! x) n6 ^+ ^  m1 T        self.groupBox = QtWidgets.QGroupBox(Dialog)
    ' E5 b. x- H) b) A+ Y+ @7 ?( S1 @3 z* n! L: m1 M% U. O* G
            self.groupBox.setGeometry(QtCore.QRect(30, 20, 551, 511))+ i% z; h4 {) N; L
    6 ]! R' R# q$ G/ J, V
            self.groupBox.setObjectName("groupBox"). O* v* T7 _# Y+ m0 a# J% ], s
    & ]' \+ k+ \) G1 v/ s8 y. b# s
            self.label_2 = QtWidgets.QLabel(self.groupBox)
    1 ]% D3 U! `6 @; e+ b$ n
    ; j% V2 W# n* ~( @. @9 `        self.label_2.setGeometry(QtCore.QRect(20, 30, 31, 16))* }, H4 x0 v5 g3 b$ i! J9 ^

    * l, D% R! r( U3 Q2 |0 b& r# ^        self.label_2.setObjectName("label_2")8 V& W  k3 _# i' J3 T

    ( h  ]/ ?2 p* _5 z, D        self.comboBox = QtWidgets.QComboBox(self.groupBox)
    9 ?* i5 I8 ]" u* ^  e3 S7 a3 k: g
    + \3 `. q9 [2 R/ o+ D6 Q2 O        self.comboBox.setGeometry(QtCore.QRect(70, 30, 87, 22))
      U$ C: A2 J1 n  W& f  e8 z( W) d- q2 Q6 c+ }4 O$ B
            self.comboBox.setObjectName("comboBox")
    ; i& y# ]: ?8 N) E/ M" w6 V  j$ @& t& ~; D1 s9 G7 F
            self.comboBox.addItem("")
    * `) F0 r- E% ~0 p5 k
    8 l  i& M2 w9 w# J2 O9 M        self.comboBox.addItem("")! U, @5 \2 V, S0 N
    ' s) u9 s  Z2 o5 t2 y
            self.comboBox.addItem("")
    $ c5 y  V( K9 c( ], o* g  q) k$ Z% G7 D1 V. A, o: R9 z/ v) H
            self.textEdit = QtWidgets.QTextEdit(self.groupBox)
    % ^! o% N$ K4 [, n) R
    6 F+ B- Q9 f; F# ^- H# t4 o1 H; L        self.textEdit.setGeometry(QtCore.QRect(20, 70, 491, 411))) G( X6 A& O( b1 M) z
    9 o; Q9 g' Z" q% y  |" _8 n
            self.textEdit.setObjectName("textEdit")
      y7 S. Z+ I7 X8 L5 A5 J6 J
    ! X% F* S$ T, ]        self.queryBtn = QtWidgets.QPushButton(Dialog)+ T4 O3 J, I( x) u. t+ i

    % t. ~' s& {, w# K6 d9 _2 m5 v4 N- U        self.queryBtn.setGeometry(QtCore.QRect(490, 560, 93, 28))) ^$ S7 R- I& ?  V& y
    * d( u9 U# m) Z0 y
            self.queryBtn.setObjectName("queryBtn")* ]9 C' `2 Z+ n2 W* V2 q9 ]
    * U+ R5 }9 I4 R3 @7 Y3 O# f1 ^
            self.clearBtn = QtWidgets.QPushButton(Dialog)
    3 p0 g- C) c1 D+ y0 y3 ?) A* _
    5 Y& L7 h# L4 `# B        self.clearBtn.setGeometry(QtCore.QRect(30, 560, 93, 28))
    1 m% Y  ^, q1 z+ U
    8 {4 A# M2 O3 M0 r/ b3 @0 l        self.clearBtn.setObjectName("clearBtn")
    - `8 U$ \' o/ L8 ^1 }# ?/ h9 f- x
            self.retranslateUi(Dialog)
    & T6 F) ~4 g% R0 b3 v1 s0 m% @# ]
    ) o& W/ q0 u, H2 {3 ]        self.clearBtn.clicked.connect(Dialog.clearText)
    + c3 M. f+ d' W6 t
    8 v# O; W  w" z$ R) t        self.queryBtn.clicked.connect(Dialog.queryWeather)
    4 T2 M/ K5 S/ k" u9 E) o6 b1 x. ]) r
    ; m; J3 y% L% b* p! P/ v        QtCore.QMetaObject.connectSlotsByName(Dialog)! L) v2 K+ x. s% e

    6 b% h1 \# B; Z  S: C9 [) e( u    def retranslateUi(self, Dialog):
    ( F& K+ Y8 I( m& e
    ( X3 C+ {2 ^8 T3 w, m+ Q8 K$ J        _translate = QtCore.QCoreApplication.translate
    - `: B( [" _! m' S
    6 k, s8 U7 c6 ?* m# I, |5 z        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
    " n8 p* w8 K* k5 M9 H( w7 K3 J
    + t' D( G7 ], _8 Y. ~6 i        self.groupBox.setTitle(_translate("Dialog", "城市天气预报"))
    # n( ]( d  F7 u. L
    6 g$ r8 y! l4 K! F        self.label_2.setText(_translate("Dialog", "城市"))! c( _+ k8 D) d/ z$ K; p
    8 h% S* ~! K1 ?7 y5 t1 d. m
            self.comboBox.setItemText(0, _translate("Dialog", "北京"))
    " z+ }: R% K0 ]+ P% i. k
    # C9 S. n8 V0 r7 i8 j/ U1 m        self.comboBox.setItemText(1, _translate("Dialog", "苏州"))
    ( R& a) h- J, k5 x/ x& C7 v1 Y4 i( Y1 o3 R
            self.comboBox.setItemText(2, _translate("Dialog", "上海"))1 s2 k; p4 C; H* ^

    ' g% T" J' A) ]/ ~9 U& \/ [! C8 `        self.queryBtn.setText(_translate("Dialog", "查询"))
    6 N) g( b; j5 A+ N3 T9 d' P8 F7 B6 L( y. q- H# ]
            self.clearBtn.setText(_translate("Dialog", "清空"))
    1 _( e% G3 K6 h* H' V( F4 e' c) H& M' K& K- L
    3、调用MainDialog. g3 ^* W4 D( t4 P5 P
    3 l/ r7 n' J. A. n9 k
    在MainDialog中调用界面类Ui_Dialog,然后在其中中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。新增demo.py文件, 在MainDialog类中定义了两个槽函数queryWeather()和clearText(),以便在界面文件Weather.ui中定义的两个按钮(queryBtn 和clearBtn) 触发clicked 信号与这两个槽函数进行绑定。
    0 j, j2 z! A& x/ U* @- K5 ~+ o3 U& E; Z# I' N6 l9 Z/ u
    完整代码如下:/ R0 `' S' t# s+ F

    8 m7 B; G" [4 ^0 U3 b# Wimport sys2 z7 F+ o1 v2 ?# ?  Z
    1 W2 Z) j! L" n
    import Weather
    1 b4 b. g8 k  a
    , f& c5 }' E/ W% K/ Gfrom PyQt5.QtWidgets import QApplication, QDialog0 F+ `4 |$ g6 i5 T

    . s1 R* a' t% Z9 ^3 bimport requests6 _( c2 [7 P& H6 }# j! [
    ! ?, X7 [" w* L! ?* G1 Q
    class MainDialog(QDialog):& ]: {6 F9 i1 `; H7 k4 Y5 I
    / n( F4 B8 Q$ Q5 u3 _, V) u
        def __init__(self, parent=None):
    / _9 e* x3 o+ g$ ]/ H
    ) G  o/ b! i/ n6 C. f        super(QDialog, self).__init__(parent)
    # p8 Q9 z* ?% t/ w0 j$ j* z  h
    : a/ f1 c! _6 A        self.ui = Weather.Ui_Dialog()) d. a4 u6 f+ B  n
    ! w- E) B0 u" h3 o$ \* s& a& p% E3 b
            self.ui.setupUi(self)
    . g0 i# W! F% m# L  n! g, g
    6 @5 G) j% s2 ?- y" I    def queryWeather(self):
    / f& p6 ?+ ~- P! n3 g5 i2 v& y+ ?: Y7 ~/ P4 e. Y$ ]3 R
            cityName = self.ui.comboBox.currentText()
    " z* L9 Z8 b; C1 O1 H7 B7 x
    ( X9 s* R" M2 K        cityCode = self.getCode(cityName)
    + ]1 G+ k8 h+ E
    # L! v  r, P/ B; O1 l3 J        r = requests.get(1 u  }. B$ Z1 Q- Q
    0 W0 z6 m2 C2 c+ E
                "https://restapi.amap.com/v3/weather/weatherInfo?key=f4fd5b287b6d7d51a3c60fee24e42002&city={}".format(
    9 V( }3 T% p! @4 }! @
      [% U8 s  i. J( F2 T0 Y                cityCode))
    2 s; \4 A  e+ P) z! L/ Q  J$ \% v, n
    1 Y8 F' W4 A" k  b) B        if r.status_code == 200:  j$ t( K3 z9 A4 j+ `2 Y: G1 k# v
    ' M7 f2 i' x6 p/ P
                data = r.json()['lives'][0]
    & w1 K6 n6 \- {
    0 j0 m' u8 S  {* M  M1 x+ D5 w            weatherMsg = '城市:{}\n天气:{}\n温度:{}\n风向:{}\n风力:{}\n湿度:{}\n发布时间:{}\n'.format(
    ; J: I% \6 B( b9 e& w; x3 U) h
    $ Q# V6 d( H4 @  {1 L                data['city'],
    6 I) o$ g4 U# Z* I9 J3 G7 a+ m" E" M3 R; T4 i9 @; B
                    data['weather'],
    ) T- ]9 E9 d4 S0 s: E3 ?  [
    & |& t& ^4 b& V- Z                data['temperature'],
    " ^3 A# K8 j  a' W: x( m  L
    ; _9 }4 B7 P  a1 C* j9 g                data['winddirection'],
    & C3 W5 T6 _, W! ?3 G0 i% X/ b' i- F9 T7 t' q9 o2 b  |+ d! U5 _; F
                    data['windpower'],( p6 |0 ]1 E; z! O: X" a6 F  T
    . a7 t7 W/ e: k+ `
                    data['humidity'],$ q9 M6 S! c9 a

    $ b1 Y0 @2 z, s! r, z" |+ N                data['reporttime'],4 z& z$ k( J2 }6 H$ R% u/ x0 F
    , v, ]; R: J8 n# n" X, C
                )9 c5 q, q% X* [

    $ B' n- F! Q$ u# s7 ]- ]        else:2 x$ k3 t3 e9 d- \
    # I7 z4 K' O+ b/ F, D# l
                weatherMsg = '天气查询失败,请稍后再试!'
    8 z2 ?3 J8 A8 }. C5 Z' L( c. h( P9 a4 Y( [3 |8 S2 x
            self.ui.textEdit.setText(weatherMsg)
    6 D8 O) V$ X, m5 Y& Y2 z3 E. z" ]+ W! y: u( d& P/ _
        def getCode(self, cityName):1 {  F( E( W0 M5 r

    8 k! y! S, ]  o        cityDict = {"北京": "110000",
    + S" E# Z/ m3 `' G4 ]* l. k
    1 k/ {4 i% }1 k/ M- L  F                    "苏州": "320500",9 b6 p% z1 s% |9 k1 K& b3 K! t

    , E5 V5 [) L9 j                    "上海": "310000"}
    0 ?6 c! b/ Q' I1 [7 o
    " V3 E) V4 w1 d        **return** cityDict.get(cityName, '101010100')/ Z5 Y" `5 ?' U5 q3 a& W! L

    . c+ Q* C4 S$ b3 I9 E8 q+ j    def clearText(self):0 G. g' j" i4 b- P) X8 R1 Y
    : K% B& u) c4 _2 M5 s
            self.ui.textEdit.clear()
    7 e0 k! ]4 X# ^% j
    3 q5 ^! ^6 c" T: |) [if __name__ == '__main__':
    7 J7 N; P: m$ @+ H$ G4 G& f9 ]* V6 Z1 ?& v
        myapp = QApplication(sys.argv)5 d. p( z+ L- ]
    - x' v; P- s9 E. m! z- B
        myDlg = MainDialog()
    5 {0 Q+ P2 V9 H$ i8 E' A5 D  k, o( p' g, K  F  |, g' m+ Z1 ^1 I; A" o  k
        myDlg.show()) ]7 w" c; W0 C( J; I
    # m. S: U% L& n2 ^- i( e( v! N
        sys.exit(myapp.exec_())$ J) B$ J. t# q$ @6 Z* [( t% h
    / c: S# q; J8 G/ U# S- O6 J
    运行demo.py并执行查询后的效果:) M* j+ l* U- t  J
    6 ?+ m3 K  [. H: x& p. [
    - z- N$ E# P" d" w
    7 E2 {" x, j- C( w
    4、将代码打包成exe文件
    ' R7 n, a* N3 p2 i
    - K  a" ~: O. \2 t3 ]+ g将.py文件打包成可执行的exe在Python中称为freezing,常用的工具有:PyInstaller, py2exe, cx_Freeze, bbfreze, py2app等。功能对比:/ Y; a# `6 R. |- I
    3 B# {5 P2 g" d6 V6 y
    * I; K$ r' j- q

    * `6 n" S) N( Q3 Rpy2exe:软件更新已经不活跃,因此也就略过。
    $ n- k. a/ M8 j) p
    / I2 w# f" T4 a; }% j  G6 ppyinstaller:明确支持win8、win10、理论上支持win7,,支持apple Macos, linux。pyinsaller可以打包成文件夹形式内含exe入口执行文件的形式,也可以是一个单独的exe文件。
    ' [6 ~& q! \: Y: H3 S6 r
    4 R: K( _. ^3 H! ^" _0 A7 q' pfbs:基于PyInstaller,使用起来更加方便
    ' d2 x& |5 `& X) l' @) e% N+ [5 ?% Z6 V5 q) }
    这里选择了fbs来打包。fbs的安装方法:
    5 q1 |  G4 |; ^, G8 R$ L6 m5 q: J3 F$ W3 J
    pip install fbs1 @4 f- ]' S( f+ M  U, L5 I
    使用方法,在命令行中输入:/ W5 z* H. i: h* O9 Z; E1 d
    , C1 F6 p3 p7 f" y
    fbs startproject$ Z; Z) c9 x! C9 z9 V" J5 o) o
    执行完成后需要输入一些APP的名称等。完成后会生成如下目录:
    ( f. ~$ X0 i! {! H0 @, ]2 {& v/ H

    ! q# i& y- m8 V+ D0 d" W; v; V, q7 m% l: X! F
    将刚才编写的PyQt5的代码(demo.py和Weather.py)拖到src/main/python文件夹下,删除原有的main.py,并将demo.py修改为main.py。然后打开 main.py,在文件头部添加如下代码:
    5 j/ Z" t- X; r  x' m. \* Y$ X* L' H
    from fbs_runtime.application_context.PyQt5 import ApplicationContext5 r6 K' n3 r" L, c
    ```/ W, i1 L8 v* B9 e7 ~
    完成后执行:
    6 x5 `+ D: C5 X9 ?```
    6 M! H% f: Y2 w* b5 d% L: qfbs freeze" V$ T4 q- Z% s5 Z3 B; u
    ```, a+ u" @  z# ?6 s7 J5 a! F
    即可实现打包。生成的exe可执行文件在\target\MyApp文件下。, k% j: `9 h4 F% S+ L" l: s: \* e
    1 x" a/ N' x6 N$ L( N) `5 O2 H* |
    ————————————————
    4 C/ k( P3 H8 m: s; S, R) _版权声明:本文为CSDN博主「宋宋讲编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    & `7 i: f- H9 D- b% K1 Y3 ]- E原文链接:https://blog.csdn.net/qiqi1220/article/details/126289667
    , {: I: R; |. v8 T* y
    ' f* Z  K: N" k0 c6 E6 q+ N7 m: [8 N8 q$ c. k8 O
    * o# W' ^9 W  e' v1 V" ]9 M2 N
    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-8-26 15:45 , Processed in 0.486564 second(s), 51 queries .

    回顶部