QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2284|回复: 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使用指南!
    7 N' f( R( Y" {$ H) ]* v/ u( T
    8 S5 V& Q7 M* M. z# T6 J使用Python开发图形界面的软件其实并不多,相对于GUI界面,可能Web方式的应用更受人欢迎。但对于像我一样对其他编程语言比如C#或WPF并不熟悉的人来说,未必不是一个好的工具。
    ' [+ ]  c' P; H4 g' v
    / y9 D4 K* D: m% X7 t* ]3 ]" c% W+ Q' V常见GUI框架
    % v3 w1 `% m! }
    ; r& p) s7 M" \PyQt5:Qt是一个跨平台的 C++图形用户界面库。QT一度被诺基亚拥,后出售给芬兰的软件公司Digia Oyj。PyQt5是基于Digia公司Qt5的Python接口,由一组Python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。
    5 C5 Y8 o/ ]$ Q6 X7 \! O
    ! A+ ?- f( K. p; dPyside6:Pyside是QT公司官方提供的Python包,上一版本为Pyside2,对应的是QT5,最新版命名规则进行了调整,更改为Pyside6,对应的是QT6版本。由于官方出品的比较看好,缺点是发布比较晚,网上的资料没有PyQt5多。8 `( I2 l$ D& b* ~3 t  j# [

    6 J4 Z% S9 g! H1 |# nTkinter:Python内置的GUI框架,使用TCL实现,Python中内嵌了TCL解释器,使用它的时候不用安装额外的扩展包,直接import,跨平台。不足之处在于UI布局全靠代码实现,只有15种常用部件,显示效果简陋。/ m5 I4 n0 P$ S% Y5 d) a+ z5 s6 R/ K

    8 P; \* P1 u/ jPySimpleGUI:PySimpleGUI 是 Tkinter 一层包装。使用 PySimpleGUI 实现自定义 GUI 所需的代码量要比使用 Tkinter 直接编写相同的 GUI 要少得多。" q6 p% N& p& `" d9 ?3 H$ W( u
    8 p" }# a3 n- z/ t( I/ e
    WxPython:wxPython是Python语言对流行的wxWidgets跨平台GUI工具库的绑定。用得比较广泛,跨平台,C++编写,文档少,用户可能就需要根据编程内容对不同平台中的GUI代码做一些调整。遇到问题不好解决,代码布局控件,不直观。
    , D% P( d2 p) ?& c- q' _. B1 F( C
    2 Y! G, R; i& _% B& AWax:基于wxPython ,为克服wxPython的问题而制作的一个包。
    6 T3 \. X7 I, N  Q8 V$ R& a, `5 t7 H5 m. l4 E! S, U8 u& R( e
    Kivy:主要针对多点触控程序,智能手机平板等,也可以在没有触屏功能的系统上,全平台支持(Windows, Linux, Mac OS X, Android and iOS.)使用Python和cython编写,中文支持差,需要自己下载中文库并且制定路径。, u% J. m' c3 w/ g

    & x' w8 u) |0 |- C9 _; uBeeWare:Write once. Deploy everywhere.需要与Kivy配合使用。
    : u, Y# N+ z0 \5 M( S! q$ F+ @9 j2 `
    Toga:一个使用Python开发原生APP的GUI工具包。Toga由一个具有共享接口的基础组件库组成,以简化与平台无关的GUI开发。Toga适用于Mac OS、Windows、Linux(GTK)以及Android和iOS等移动平台。& e9 C* j( j2 }$ `
    9 v  D) Q. {6 @" J
    Eel:一个轻量的 Python 库,用于制作简单的类似于 Electron(但是比它更轻量) 的离线 HTML/JS GUI 应用程序,并具有对 Python 功能(capabilities)和库的完全访问权限。  Q! ^) a% Q' D8 l' s: t; @
    ; U( n1 E" d6 o. C5 Q& V
    Flexx:一个纯 Python 工具包,用来创建图形化界面应用程序。其使用 Web 技术进行界面的渲染。你可以用 Flexx 来创建桌面应用,同时也可以导出一个应用到独立的 HTML 文档。因为使用纯 Python 开发,所以 Flexx 是跨平台的。只需要有 Python 和浏览器就可以运行。8 e. S4 K7 J) ~1 o- `3 T, m
    1 K" a" q% V/ l% Z9 Y) d
    pywebview是围绕 webview 组件的轻量型跨平台包装器(wrapper),它允许在其自己的本机 GUI 窗口中显示 HTML 内容。它使您可以在桌面应用程序中使用 Web 技术,同时尽最大可能隐藏使用浏览器构建GUI的事实。
    & s, _! i5 M9 J- i, I; G- q2 p5 {' E; e  [4 B
    enaml:一种能够让你用最小的努力就可以实现高质量GUI界面的的Python框架,也是一种独特的编程语言。enaml将声明性语言与基于约束的布局系统结合在一起,使用户可以轻松地定义灵活布局的UI。enaml应用程序可以在任何支持Python和Qt的平台上运行。( M$ j- a8 ]- V$ B7 O

    2 M* ]3 f. G! r* M个人想法:太多学不完,先学PyQt5,原因是资料多,学有余力再学pyside6,最后看下PySimpleGUI,看能否解决一些简单问题。( [( i2 O  K( I: b

    ' w, v/ L) D+ e% hPyQt5简介
    ) E$ p, ]* T) Z& Q1 Y
    7 K2 H; V% r' t! G$ NPyQt是Qt框架的Python语言实现,由Riverbank Computing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件,因此PyQt的API接口与Qt的API接口很接近,但PyQt不再使用QMake系统和Q_OBJECT宏。" _5 \8 }7 h" \& C1 G, @' D; t5 k
    8 e% y( r+ W% i) u% J
    PyQt5提供GPL版和商业版证书,自由开发者可以使用免费的GPL许可,如果需要将PyQt用于商业应用,则必须购买商业许可。
    9 K# c# _" S' a$ I& l- p0 F5 g+ ^5 j9 d% h. H3 O8 E% \1 k9 ?
    PyQt5特性如下:$ B: A: M6 N: Y8 a) E( H/ f1 [

    + M0 f: ?; p8 o基于高性能的Qt的GUI控件集。% N( w& H$ `$ B% T5 ~7 h* ^' K
    ( D. l' e& t9 N: S
    能够跨平台运行在Linux、Window和Mac OS系统上。
    - D9 c8 v, r2 r5 d8 s$ m, T  w- y, t! ~
    使用信号槽机制进行通信。8 A* F/ W' ~+ u& \# e) F7 G

    % [% |) ^! y% Q, ^" S对Qt库进行完全封装。
    8 U2 `9 R. t/ [" l7 q; W& v9 Z2 ^7 D1 e# x4 y1 V) Z7 L
    可以使用成熟的IDE进行界面设计,并自动生成可执行的Python代码。1 q! g) h6 G; {( M5 `" i3 O

    0 t8 B. n4 N, C7 Q提供一整套种类齐全的窗口控件。; z+ G  D8 h, w9 U
    4 F' }( m3 k- e7 {1 |" o$ `& C
    PyQt5是由一系列Python模块组成,有超过620个类,6000个函数和方法,主要模块如下:
    , \. ^# b" }3 u) ]: H/ R* W! Z2 U2 }# C2 W+ f! A& z
    QtCore:包含了核心的非 GUI 的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime 类文件、进程与线程一起使用。
    / X% w# @& x7 N! h9 O6 L0 |  w* l7 ]6 m0 ~7 Y
    QtGui:包含了窗口系统、事件处理、2D 图像、基本绘画、字体和文字类。
    ( w+ a6 f/ I5 |1 O0 d) i$ ]: M4 [# {5 z. H
    QtWidgets:包含了一系列创建桌面应用的 UI 元素。
    : N: g3 g  h/ c- j9 p" |: H
      a' C/ ^, H* T4 e: ^- t. HQtMultimedia:包含了处理多媒体的内容和调用摄像头 API 的类。
    # z1 k9 X  d# `$ @5 [
    $ F/ `! W: }' H6 _; U; c7 wQtBluetooth:包含了查找和连接蓝牙的类。3 s/ h# s& y: S, x8 f; C

    # |! Y, o1 ]' T$ K9 E; Z# t) JQtNetwork:包含了网络编程的类,这些工具能让 TCP/IP 和 UDP 开发变得更加方便和可靠。! x5 M$ w; z+ e" X
    ) I, m$ P6 {9 }# V" m5 T# ~$ q
    QtPositioning:包含了定位的类,可以使用卫星、WiFi 甚至文本。
    # L( t% o. P6 x" R, L& Z$ O2 o& M0 M2 X
    Enginio:包含了通过客户端进入和管理 Qt Cloud 的类。# w9 r$ H; P3 f4 o& @  C/ L. Z8 ?
    . E: u2 T; H$ n% z% [
    QtWebSockets:包含了 WebSocket 协议的类。2 l- x( H: b9 z

    3 j, I/ O9 Z7 v+ X/ f7 P9 mQtWebKit:包含了一个基 WebKit2 的 web 浏览器。- K% g+ s' [9 i% b4 o
    * F. E. u1 t6 Y+ ]* d
    QtWebKitWidgets:包含了基于 QtWidgets 的 WebKit1 的类。* s/ t# W9 @) j& a: ^9 i
    4 m, I) c9 |5 h. c2 h, `
    QtXml:包含了处理 xml 的类,提供了 SAX 和 DOM API 的工具。
    5 y& a. u/ f" R) h! d! b
    6 ?' }! _; I" S+ w* Z% J5 iQtSvg:提供了显示 SVG 内容的类,Scalable Vector Graphics (SVG) 是一种是一种基于可扩展标记语言 (XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。, B+ ~$ f' U' ?  Y$ L1 o
    3 A' J1 Q* t$ A
    QtSql:提供了处理数据库的工具。
    ! L# r5 X# `# a0 L7 I9 ^  o! H& f3 C2 C- t
    QtTest:提供了测试 PyQt5 应用的工具。
    6 ^9 P6 _3 P9 l4 r; X. V( Q" }7 \$ Z( W
    PyQt5的安装! ^4 V8 J" P0 L7 @% L( t) e

    2 L0 B6 J. U% z# N由于后期要使用fbs进行打包,fbs对Python 3.7以后的版本可能存在兼容问题,所以我选择了Python 3.6.8进行了整个环境的搭建。主要内容为:Python + PyCharm + PyQt5
    9 {- ~+ M, Z3 k8 s0 G
    ( V; Z0 @' [0 X, l( O安装PyQt5" p8 Q" W" J* z- }
    1 Y2 q) C8 h* S) D! J
    pip install pyqt5* N: t! _4 P5 J8 o: L

    : B, V8 ^5 O" }$ J" p- |pip install pyqt5-tools, Q( ?6 H8 L: T( f5 R! F  N
    其中pyqt5-tools为Qt Designer拖拽式的界面设计工具。安装过程中可能会报如下错误:; ]; H. D3 L0 H* @/ }
    6 e; N! F: ?% G
    qt5-tools 5.15.2.1.2 has requirement click~=7.0, but you'll have click 8.0.1 which is incompatible.1 L9 z; b# @4 p# Z+ d, j
    解决方案:8 A+ t5 N' y9 N; D1 w

    : D$ Y( E. G8 rpip install click~=7.0
    + r, {" f* B  r7 s3 f- JQt Designer的配置
    ) q2 r7 n8 G( w! b$ q  L" S
    2 D& @! K+ Y; ]" a3 L0 HQt Designer 是通过拖拽的方式放置控件,并实时查看控件效果进行快速UI设计。4 s# t0 I' b  v2 G

    ( A9 C& I9 \3 A
    9 f8 L$ z9 u; F4 w; P7 l
      W0 Y+ t/ n+ [整个画面的构成:
    1 ]. O& _$ h# u+ F
    ; y. L# m0 I7 q左侧的“Widget Box”就是各种可以自由拖动的组件% N! V( U& \: w$ r. D9 r
    * \7 w/ S3 `( h
    中间的“MainWindow – untitled”窗体就是画布6 c9 X0 D+ X6 A" v4 P

    : g3 i" O5 _/ e右上方的”Object Inspector”可以查看当前ui的结构1 T0 u" }9 \: L1 z$ H* r/ @0 c- n

    : @2 I; v9 o# k' r* m+ s右侧中部的”Property Editor”可以设置当前选中组件的属性/ k8 A$ T* @! K' Z8 x! A( H5 P
    # c( _- b/ U4 j7 E
    右下方的”Resource Browser”可以添加各种素材,比如图片,背景等等
    3 I' I1 o" h! ^4 z7 |0 E6 `
    7 t) G; L0 N3 g1 k# _5 A" u最终生成.ui文件(实质上是XML格式的文件),可直接使用,也可以通过pyuic5工具转换成.py文件。
    ( S3 F9 i2 a5 x! x  {& M' g
    8 b5 a9 s8 M9 U; K2 wQtDisigner配置
    2 O# A. u( G! h4 w' Y% m+ r* c. T" ~* x! p
    在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    ) m. Q0 `, [6 ~' L/ P
    * W; D. W9 k1 E" e! a% yName: QtDisigner
    , Z& ~+ }4 T6 K1 L0 _1 S/ V# Z/ ~( _5 T( s4 a  f+ M
    Program : D:\Program Files\Python36\Lib\site-packages\qt5_applications\Qt\bin\designer.exe # 请根据实际修改
    0 w0 m6 K9 G4 C
    0 ^, C; X$ d& p5 G; F( cWorking directory: $FileDir$- o4 O% V) S  k+ T
    PyUIC配置
    ! f, x$ J' u$ ]  ?; ^
    1 x( E# |/ f  \& e! E# U6 r) x& \& TPyUIC主要是把Qt Designer生成的.ui文件换成.py文件。% i/ o5 X2 k9 l4 Y
    6 |8 @3 i3 u4 |$ _
    在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:' }( l1 A2 J9 |; N% x% Q) Y+ o
    : G% Y8 m$ c& c, S
    Name: PyUIC8 c& b" u+ E: Z7 e& ^

    & a( ]3 W* h( p$ i! O: `$ K. Z* v6 mProgram : D:\Program Files\Python36\python.exe # 当前Python目录,请根据实际修改
    5 V: C9 @- T! l9 i. j7 Q9 L
    , ^5 K  D5 M  P3 e; V% S& _Arguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py
    5 }! M+ K; B" {# r4 v
    1 `- j  T: ~) `: E2 K; i; ~Working directory: $FileDir$% {: U( A8 y4 A2 W  }. O. ?+ c' H/ q+ e
    PyRCC配置" g8 M& T* I, U5 b/ Y

    3 B2 H- @+ a. S9 x# \PyRCC主要是把编写的.qrc资源文件换成.py文件。在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    4 G5 p$ J; L# P" }5 b& |1 w1 f8 O: n! M& i% ]" O- i
    Name: PyRCC
    $ A+ a4 a0 q' A8 _/ L
    - \, I* q: J( Z' F1 _Program: D:\Program Files\Python36\pyrcc5.exe # 当前rcc工具目录,请根据实际修改% Y* C5 @2 w- j% \0 D
    / _! O% x  h+ ~# t9 N9 ^* e8 P
    Arguments: $FileName$ -o $FileNameWithoutExtension$_rc.py
      y( U5 H" M" q: }
    % z! N/ Y2 p3 ^Working directory: $FileDir$
    2 Y+ a. y# E4 v- X! |PyQt5使用示例/ n9 l% v4 b- k/ ^" @% n4 i

    * I5 I# ]  s8 @) [# @创建一个空白的界面:
    ) H7 j7 \( [: j4 L0 c
    % k' [) v  r, M; l3 W; W& ~import sys
    5 F$ P" G" s  y) a. X* D1 ~. \: f. u/ D. o4 J; {
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
    - G; b: v& s4 y7 F+ f& \6 _3 o( t0 E" I
    app = QApplication(sys.argv)
    , F' b; M, a) Q% j" b: n- P- x0 L! T) c) f" j7 k& W7 l  _
    win = QMainWindow()/ l. H5 b' d' k* Q

    4 R3 ^% J# c& jwin.setGeometry(400, 400, 400, 300)
    0 s! Q' I! w; K) I+ l
    3 c5 R- s  J% a+ e; ?win.setWindowTitle("Pyqt5 Tutorial")
    & W8 R* e: D. L) U4 P& \7 n6 @" D3 ^7 F$ `
    win.show()& k4 k: ]3 {  C
    8 |5 C& L- o6 o4 s. p
    sys.exit(app.exec_())3 x  d9 z: Q8 S* d+ v

    $ f+ ^& \0 g' Z2 ]$ ]. S8 l( E# r/ A6 _' L! }  c
    ! k7 t) E, S$ u/ y4 D1 W+ H" n' D9 _
    其中:
    " Y6 C$ m& z% p' a8 d' s% V6 h6 t8 V0 |5 ]4 {8 x  C
    Qapplication():每个GUI都必须包含一个Qapplication,argv表示获取命令行参数,如果不用获取,则可以使用[]代替。- l' A. c+ h! ?- y; i0 N' n# F. |
    ! \1 Z+ ?; W& [$ z8 Z1 Z2 n6 H& z
    QMainWindow():类似一个容器(窗口)用来包含按钮、文本、输入框等widgets。arg标识可以获取命令行执行时的参数。
    9 |4 Y7 I1 N( j
    , K4 y7 T- U) {- n  Y- nSetGeometry是用来定义 QMainWindow() 窗口的尺寸, 语法:setGeometry(x, y, width, height ),其中x,y为屏幕上的坐标点。
    2 L. R7 J: d2 G$ V7 t  r1 ?- K- z: I1 ~
    show():用来显示窗口/ j$ f/ ]# U# Y  C

    $ @# X" B2 w, d: j9 w7 Vexit(app.exec_()):设置窗口一直运行指导使用关闭按钮进行关闭
    4 j! [$ X1 E/ _
    % y0 d! s5 I* i  b' G& M' A. PPyQt5支持的常见Widgets有:1 K  \; P1 B  T: |8 N6 D3 k7 u

    - o- q6 s. N. g3 T6 W! J2 p+ ]2 v
    1 W5 n& |* c: A& v+ x% T4 @. @, [' A4 t- C
    从上到下,从左到右依次为:Qlabel、QcomboBox、QcheckBox、QradioButton、QpushButton、QtableWidget、QlineEdit、Qslider、QProgressBar& o, K5 j+ O; j; u

    ! X, z0 I" X' L4 e& r1 F' ^/ y6 P# i对于使用Pyqt5设置文本内容,我们使用Qlabel:; y4 J0 I" I* ]2 o
    # b7 Q$ x$ |0 O* {: Z, x/ O& c/ D
    import sys
    " |" Q4 {) T% \$ I
    $ S! }% _' J' z, F3 n0 Nfrom PyQt5.QtWidgets import QApplication, QMainWindow, QLabel2 @4 M" m( }. F9 [

    7 w5 M% w  I; y! [app = QApplication(sys.argv)* {$ @. R, A( `7 E2 c! h# C

    ; m8 v% ~+ |) @) F8 |win = QMainWindow()
    - @% r6 W7 Z& ]! h& F( }" m1 U2 H) q- N* U' W' O
    win.setGeometry(400, 400, 400, 300)
    ! H1 L; p1 J/ K" m
    - q- s5 f3 X* a* ^& ywin.setWindowTitle("Pyqt5 Tutorial")
    $ C! ]4 ~) d- W, a$ L# g
    . r* U  e6 }- F2 O, g0 l\# Label Text
    1 d& B* V2 e8 T
    ! T  r4 ]( ~0 R6 P' Klabel = QLabel(win)
    ) y0 \. Y) Z1 N) u1 k1 i
    9 l% J4 o6 r: o9 I1 w) `label.resize(200, 100)1 E7 V  T: y9 h: K

    " o! b8 @3 b  p: flabel.setText("Hi this is Pyqt5")% M2 K: `8 F" ^; f: p/ J5 H
      J; E: r# W, N
    label.move(100, 100)6 S8 h" h& C: ~, T

    3 t+ a% ~$ u6 s& g$ jwin.show()/ @* Z/ g+ x+ b3 U' x# _
    8 U8 J4 R) Q# @- v$ u
    sys.exit(app.exec_())1 Y+ q4 {+ k% x; T! a- N8 k  ?! i' c

      ?; m% m' r  Y' s
    ) n: U/ O- v% b) L+ r# f5 S# K9 Q- m1 ?- v5 ^  |. Q% g
    按钮与事件:
    * k$ d1 B% f7 _+ d& L7 w
    % i( n! _3 T) g# V% B- |: E) Aimport sys
    ' Y4 O5 r& S* k( V; ?: q  r7 e6 Q
    + U/ {; B) ~" Rfrom PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
    9 \$ a9 C: Z: M- z2 w- h# g% O* c+ |. ^. k$ P) o
    def click():
    1 A7 y$ ~; f: O# m& \4 [1 A/ V/ {. L9 M; e8 \
        print("Hy Button is clicked!")5 c) o3 W; w3 r
      f  l5 H1 E4 u
    app = QApplication(sys.argv)
    ! W0 P8 }; C2 R2 H
    0 l# U: V% b& Z9 @9 \win = QMainWindow()
    + |  D) k9 }9 H6 @1 v" H) o0 Q
    - c) O2 m7 u4 a4 uwin.setGeometry(400, 400, 400, 300)
    / L* J5 Z1 l0 Y/ ~$ P6 B/ |& Z+ u5 Q8 l& O1 U* p, D
    win.setWindowTitle("Pyqt5 Tutorial")
    + W& k" ]1 f  M! Y0 g: G3 `; E8 o3 t8 {
    \# Button
    4 S7 j! H' q. b" E9 Q; |% P3 Y& Z6 [* v  h( D
    button = QPushButton(win)
    3 k+ w* ~2 ~) U* u4 C
    # g7 a; H5 E4 J* x* `+ E# }button.resize(200, 100)2 |# u" r: d! R
    ' ~5 V$ Y7 G) H( H& U; U1 g$ `
    button.setText("Hi! Click Me")
    1 T7 u1 }: U- i" r" t- L! G$ A, o& O' x
    button.move(100, 100)% u! e) Q7 V+ G
    ( f" e' ]& r+ ?- T  z! ~& A/ z
    button.clicked.connect(click)7 x) M. @/ g+ Q4 Q! j2 N3 @( A

    9 e1 h! g; Y9 Pwin.show()) Z' }$ v6 D5 q: ^" A6 e

    3 F0 k' o4 o% `, h% h) j: Bsys.exit(app.exec_())- y6 K* [" N9 M7 B0 K& D) L8 U  \
    1 w% F3 g* J' d7 f7 R- b3 ^2 u

    6 [& f  B+ _2 z9 N0 |% x  y$ d8 [/ ?4 q: Z/ B4 [+ r% ?
    button.clicked.connect() 在按钮点击后执行特定的事件。9 p& o1 U) B8 ~) o1 j
    8 R* C9 X6 W& q
    PyQt5实战
    , k/ _9 C% \( D
    4 H- P! v) Y4 P7 M; B: O实战项目:简易的天气查询软件  Z7 Y' M$ s+ A1 A5 t  y# Z

    - }, A3 ~. N' H7 z+ A7 a( ?0 m1、使用Qt Designer设计一个界面
    & ]" p- e. y% t1 B+ m$ Y! T& y% I! o3 c2 q
    7 R/ M" n/ S2 C6 D9 Y; ~
    & V- e& T: [  ^( _
    用到的控件有Button, GroupBox, Label,ComboBox,TextEdit,同时定义了两个按钮queryBtn及clearBtn,分别用来查询及清空天气数据。我们需要绑定槽函数,方法如下:
    ! C) S! }5 \( w9 H  w2 v* }
    , A% L* j" i) C/ F# B% v) Z6 ?在Qt Designer右下角选择 信号/槽编辑器,点击+号新增! w: P5 u# s/ K5 E) F
    ( |/ C3 g0 A( u. G% B
    分别选择queryBtn及clearBtn,选择信号 clicked(), 接收者 Dialog 及槽 accept(),(槽函数这里不知道如何定义,后期在代码里再进行修改)* {3 E" K4 p7 V/ k9 G

    ! d4 g8 O/ ^( o% N# X/ l2 Z以上完成后保存为Weather.ui文件。
    7 ?% c& Z" S) E/ T# w: K; t, ^
    # Z4 H: e8 m% p. f1 {8 d7 m2、转换.ui文件为.py文件) x2 \" b" }+ J, ^0 j) r7 T( S: S

    % r$ h3 O# U  ^2 g, `PyQt5支持直接使用.ui文件:9 m$ E; m; m! X* m1 C7 a5 w
    . n1 e* d! n" M$ u" n
    import sys
    ( b" H/ p( X9 l7 g& {* s' V3 M) c
    # I3 `0 u/ w- W; A$ d3 M0 U; P$ Ffrom PyQt5 import QtWidgets, uic: k3 ~0 q5 p6 j0 a
    : m7 a' A1 C- g' Q* H6 C4 L
    app = QtWidgets.QApplication(sys.argv)
    * V. I* [( Z0 y8 e; e- s. V
    ) A3 q, h7 b+ b! y- u$ R; ]window = uic.loadUi("mainwindow.ui")6 |# C4 c# n; Y6 R
    4 \( \; _  P5 X7 S+ P& y% K
    window.show()5 q; C/ b/ N4 I8 v
    4 v. |, F, F6 o* y2 l
    app.exec()9 \- f; C% n  H* \; k# c: k  _
    但是为了更好的自定义及修改上面的槽函数,可以使用External Tools – PyUIC,即可生成Weather.py,实际运行命令如下:$ i7 b4 T3 g6 l8 x
    : S( T, S5 l" c- T
    D:\Program Files\Python36\python.exe -m PyQt5.uic.pyuic Weather.ui -o Weather.py. H- x6 g+ [6 V% e
    其中,我们需要把两个按钮绑定的槽函数:$ V* v! K' n( ~0 X9 A( E: k

    $ y4 I% z+ c2 K& [; H, T\# self.queryBtn.clicked.connect(Dialog.accept)
    2 r! a$ S  p( S4 N0 k4 x3 Q9 l( q4 \6 F3 U: M& e6 @
    \# self.clearBtn.clicked.connect(Dialog.accept)  I* W( _; {# u' }( y- T
    ) I* b6 s8 C2 T" h
    \# 修改为:
    4 c1 b2 [! M% r) f$ r& p% D
    ! r, d. Q1 o( ~: A2 q: f+ }self.queryBtn.clicked.connect(Dialog.queryWeather)( \. M2 Y# C' x% }8 s2 W

    7 ]/ p! a7 z  |  ]: R" b' x3 G7 P* `self.clearBtn.clicked.connect(Dialog.clearText)& N) @3 ~" Y( [$ L! w- B7 L9 o
    最终的Weather.py内容如下:- K0 l. X1 d! Q6 ]3 e, a& I- e2 W

    8 I1 n7 p) d8 C- a" l' I\# -*- coding: utf-8 -*-
    4 ]  m: ~( T* |7 a- I1 ^! @
    : Y1 G2 x0 Y6 `\# Form implementation generated from reading ui file 'Weather.ui'
    7 O5 S9 N! ]! ?. n$ h
    2 @& U$ B1 z1 m0 l# v; o( U6 ]\#9 Y7 b. Q* M8 T+ J& |
    + \! }" ~7 g6 h$ x; l% h
    \# Created by: PyQt5 UI code generator 5.15.4
    8 }# u$ R" o- {2 ?! h* ^# u
    2 K, t2 w3 P; r7 k) B8 N% L\#
    3 Y  {0 w- i3 ^
    * F8 q  z' O" Y\# WARNING: Any manual changes made to this file will be lost when pyuic5 is
    + `8 W* Q+ w9 }" T& [2 y& V. j5 z9 `2 M. ~6 Z$ y0 E$ I
    \# run again.  Do not edit this file unless you know what you are doing.
    8 N% u- O& ]3 B- r7 ?, X0 Q* ~8 ^7 j, s. N7 ~% c
    from PyQt5 import QtCore, QtGui, QtWidgets
    * d; `" j, m+ ?5 Y8 e) H/ w2 g9 i+ B( O  q5 c  A
    class Ui_Dialog(object):& w3 c  _: I* \- w
      [- {6 B9 F' X' [2 X3 ^
        def setupUi(self, Dialog):- p1 o$ g$ [+ x# [% v: }5 y

    8 Q5 }$ w" J/ C6 m2 g        Dialog.setObjectName("Dialog")( s4 v7 a- }( G0 g3 C0 i

    % m) H7 j0 D8 f7 v$ \+ ~; i& u- }        Dialog.resize(600, 600)( v# s$ v. z9 G/ \
    % }, L0 V6 i4 e9 F2 i7 F9 K
            self.groupBox = QtWidgets.QGroupBox(Dialog)3 R2 i) q# Q. a7 a
    ( L* H) w' ^9 @, l% l5 G, t
            self.groupBox.setGeometry(QtCore.QRect(30, 20, 551, 511))
    ' W+ M, k* U3 M& @: y
    : K: h7 h9 v6 D6 \1 ~0 O# Y        self.groupBox.setObjectName("groupBox")6 C+ D( b4 k8 ?/ }) i( ~5 Y* e
    8 x, C, B% p6 S! k
            self.label_2 = QtWidgets.QLabel(self.groupBox)
    4 Z6 k* M. I7 s" N% P$ m2 C' q( b
    2 R0 o0 F) [+ J8 D        self.label_2.setGeometry(QtCore.QRect(20, 30, 31, 16))
    & w# N9 ]4 q* f* T6 K
    8 v# ~' N' M' n- K+ ~% S        self.label_2.setObjectName("label_2")# u% N- }. Z% m% @
    , y, ^& |/ ~0 }* }0 i. }# o
            self.comboBox = QtWidgets.QComboBox(self.groupBox)
    5 T* d2 f! f" p% t: z
    9 f1 n; C7 B8 C, R$ A4 ?4 r        self.comboBox.setGeometry(QtCore.QRect(70, 30, 87, 22))
    , q! ?" k/ C( k2 }2 n% Q3 b
    $ x! S4 C' v1 O! a6 r, @        self.comboBox.setObjectName("comboBox")
    * Q6 W* N8 }% K. F  G  r: e! l' W$ A2 Z
            self.comboBox.addItem("")
    # v& v. X  k5 ^; e! u: c0 Y& K+ v
    , Y3 O: L8 `4 |. t        self.comboBox.addItem("")- y% @! V+ q! ~! G6 T

    4 d* B2 F) z4 a* v        self.comboBox.addItem("")! ^; l9 S# l- H
    - T8 A# d. |; P( {# ~
            self.textEdit = QtWidgets.QTextEdit(self.groupBox)
    ) }5 Z5 E) y$ q3 E6 o' e  Y9 S$ r# x' c/ }2 `' F
            self.textEdit.setGeometry(QtCore.QRect(20, 70, 491, 411))
    9 \( \1 Z) i& o5 e
    . k1 t2 m7 k# _2 t) A, w. k" O+ P        self.textEdit.setObjectName("textEdit")
    / X8 ]7 q, r0 I9 E% k( ]; \( }$ d
    6 @+ d+ G- }' @& r        self.queryBtn = QtWidgets.QPushButton(Dialog)
    + {4 ^, e- a. O7 n% h5 G
    ' N/ _0 t1 ?3 B/ L5 S: h        self.queryBtn.setGeometry(QtCore.QRect(490, 560, 93, 28))
    - {; \2 K, ^  {, g$ d" ~) e: g3 p6 d/ c/ S% D
            self.queryBtn.setObjectName("queryBtn")
    1 g2 {/ [8 _7 O3 c
    9 f; R( p# s* T        self.clearBtn = QtWidgets.QPushButton(Dialog)7 g" A2 G, I- y8 ]6 }

    * Q, A6 D; C6 @+ i) I' w9 O        self.clearBtn.setGeometry(QtCore.QRect(30, 560, 93, 28))6 o- {; U  F6 T, ?- w5 h1 V3 p! e7 c

    & d$ j3 `4 b) j; i        self.clearBtn.setObjectName("clearBtn")  t/ g8 a1 y  I# {  ~$ K

    * [# V: q8 V& f2 m8 H" ]. b* W) r        self.retranslateUi(Dialog)
    % ]5 X6 u$ S+ d+ A
    " J' |9 _- Z; q8 N1 S        self.clearBtn.clicked.connect(Dialog.clearText)" ?1 Z  f+ {# L6 |) Z: |/ Z6 S

    6 [; j9 _! @  ?9 R2 A- u+ `: f: H1 ?        self.queryBtn.clicked.connect(Dialog.queryWeather)
    * W" E; q9 N( c: E8 I$ c: ?" G  H
            QtCore.QMetaObject.connectSlotsByName(Dialog)
    : T9 Z/ f0 p0 M, m1 A. E% a0 e; j9 c( \: n! `
        def retranslateUi(self, Dialog):
    9 Y9 U0 R7 p9 C8 M8 }" A9 X* A2 m3 K) J* r( O
            _translate = QtCore.QCoreApplication.translate
    ' y7 i8 E8 ]/ G7 R+ h, {7 S# M5 `: A1 Y( O: \& a
            Dialog.setWindowTitle(_translate("Dialog", "Dialog"))# Z) i9 w) D- |, f' a
    ' d0 U3 g. _5 A# E
            self.groupBox.setTitle(_translate("Dialog", "城市天气预报"))
    ! `1 w; C6 E7 b! i: I6 n3 J' X0 o
            self.label_2.setText(_translate("Dialog", "城市"))# }$ O: O$ [  T$ ?
    3 v" q2 W% Q* A: V. |
            self.comboBox.setItemText(0, _translate("Dialog", "北京"))% g0 _5 u: _6 Q$ Z1 `0 P. |' B
    ; n5 N) M4 ^; a( P2 L5 r* e* b4 a1 N; w
            self.comboBox.setItemText(1, _translate("Dialog", "苏州"))
    1 g* b9 L+ |: {4 l8 L8 k) C" w- F( I
    $ l  Z6 {6 O/ k0 O        self.comboBox.setItemText(2, _translate("Dialog", "上海"))8 w4 q3 C  x$ A! W% A- h* o
    8 f# j2 f5 u$ A
            self.queryBtn.setText(_translate("Dialog", "查询"))  ~4 Y/ t6 |) e( m

    5 p% M/ H6 [  {# O0 T5 w- ~        self.clearBtn.setText(_translate("Dialog", "清空"))& I7 l1 w6 b- O- i
    * f5 p9 }9 g) f* I; s0 P* m9 H
    3、调用MainDialog
    3 D% o; M2 T! B, {  A( S+ x& s* D# z; W
    在MainDialog中调用界面类Ui_Dialog,然后在其中中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。新增demo.py文件, 在MainDialog类中定义了两个槽函数queryWeather()和clearText(),以便在界面文件Weather.ui中定义的两个按钮(queryBtn 和clearBtn) 触发clicked 信号与这两个槽函数进行绑定。& h$ \+ G; o: T1 w1 v
    # B* L6 [( z  O5 b
    完整代码如下:
    5 y8 c" s9 }6 X2 I. H
    9 S! B+ j7 M; W- @/ l6 w3 Ximport sys
    ' Q0 J, ~, f+ p/ K2 S" i: {$ L- L) K% w
    import Weather. _' j$ c/ Q! X: [
    ' H5 h9 y/ I6 r) n
    from PyQt5.QtWidgets import QApplication, QDialog
    " X9 k" C! R- @6 D) H+ n" m; {! I+ ^( I. `3 t; K1 C1 k- S
    import requests
    + q% X4 @: Z" K6 ]" s: ^, p9 y, n/ P5 N; i
    class MainDialog(QDialog):8 X/ W; Y+ g' B' w/ c9 |
    4 t7 t: D5 \. I" z6 ]: D. }) M; e
        def __init__(self, parent=None):
    8 J8 H/ U& i! O( o% N( g5 n) L* r8 d3 ^5 F- |5 t. k$ O! m( Z
            super(QDialog, self).__init__(parent)
    / Y4 f( p2 n# u+ {8 k4 t3 M! i5 C/ S0 l9 F+ N
            self.ui = Weather.Ui_Dialog()
    ( m/ n% V/ n: b% [  V
    $ @. @! Q7 n7 P- q: H5 k- v, m        self.ui.setupUi(self)* j7 M. N. u% q5 t

    % o8 n0 x( A1 f6 F! o    def queryWeather(self):4 I( E9 ?0 o& v3 f- v
    $ w- L' J0 T, x, i, p* V+ g
            cityName = self.ui.comboBox.currentText()
    3 i5 {: T, {2 F8 F) w$ ?! d% e
    # X! t; T  c3 }' T        cityCode = self.getCode(cityName)9 q4 t! K* i' T  Z$ Y( v4 J6 O
    8 _- Q1 z9 i3 T9 Z0 h' X* M
            r = requests.get(
    . X. K. c* U; i% ?
    - P& {* x+ ?+ F, \" {, K            "https://restapi.amap.com/v3/weather/weatherInfo?key=f4fd5b287b6d7d51a3c60fee24e42002&city={}".format(
    - G: V$ w; M* f- D7 D) X7 i
    & a1 K  S1 X& h. ?& j, `4 J                cityCode)); f8 f) j* Y6 u- x3 K! t
    + N5 h$ T+ @" U) Y
            if r.status_code == 200:5 r+ K5 ?; h; c" C4 D/ R
    ; Q6 v. ~( d. u: ]: U  ~8 z# @
                data = r.json()['lives'][0]
    & P7 C- [) A" A$ K3 I# j% Q. B1 O3 }1 ]+ _" b$ {2 h+ D
                weatherMsg = '城市:{}\n天气:{}\n温度:{}\n风向:{}\n风力:{}\n湿度:{}\n发布时间:{}\n'.format(/ O: i8 A' k- Y2 p' Y

    6 u: T2 O, n7 h  E+ o6 c                data['city'],8 E# K- t- j) u5 s0 ^3 Q# R

    % }" ?% L/ E+ S                data['weather'],; ?7 q8 K8 y% k' c
    5 I, L7 g  ?# s: m6 x
                    data['temperature'],
    8 Y" q+ k9 w4 W2 o+ a8 U# ?; E. a  i) N8 }
                    data['winddirection'],7 Z+ r3 R% Z* t2 F  Y+ R  i
    8 L" J6 E7 v* U% b3 X0 u
                    data['windpower'],
    . T3 J* Q! G: ]& V
    , z: }( R. ~; C4 Z( _, ^& h                data['humidity'],
    ' M6 h0 l$ j7 m! d# j
    ! D! \/ F  S& f, k# `8 J                data['reporttime'],
    4 x1 `9 C  g7 j: k4 b- c
    0 q& c& D2 D5 B5 _8 k            )
    ; K6 c$ i/ H; _" E
    , g% Z- @$ a  R/ r5 H4 Z        else:
    # ?8 |  s) O7 I( o; j/ s1 h- w- V6 n" X* [
                weatherMsg = '天气查询失败,请稍后再试!'4 v+ I0 a2 h. H. ^$ t. p
    % o* H3 d% F6 H9 @7 m7 Q. h/ w
            self.ui.textEdit.setText(weatherMsg): o4 h9 ~8 W  w- f9 g

    3 ^) u  v& P; o# T7 _) a3 Q    def getCode(self, cityName):" A2 T1 @3 ?% B* h$ E) f

    $ i2 S) b# G3 \6 N# N, h        cityDict = {"北京": "110000",& ?7 |8 H& a5 m+ z+ l- j! P

    0 I" _2 N% K4 O+ L, N  q                    "苏州": "320500",
    $ z6 |/ r+ Z; X: r
    7 o1 A  y) E) l6 t7 \1 ~" |                    "上海": "310000"}
      H) h# h6 Q6 G* y" w( G* B  W
    " o( M0 b( H( V, w6 E' ~0 g        **return** cityDict.get(cityName, '101010100')
    . M9 b& h% Q5 b8 d, b9 c  l
    3 }5 z, g/ u* a2 a. e/ z    def clearText(self):9 y' [0 W' n# L0 K" ^9 ]. b3 _
    1 T8 @- ~6 Y9 ]' |, M
            self.ui.textEdit.clear()5 |' [# b& S5 m6 p  `4 T
    5 n$ A) |" z7 U% a( U9 O/ L
    if __name__ == '__main__':
    " n' n6 ~/ q' a: ?6 E: I6 p0 k$ K$ |+ K+ n( U; ?
        myapp = QApplication(sys.argv)
    6 Q4 E: ^6 Y8 a5 I( B6 a5 K5 h! [4 C; v$ S4 g3 d/ K$ c9 T6 a4 y
        myDlg = MainDialog(). |0 J# ^" r3 _+ G

    ' C* o3 `3 W: L    myDlg.show()
    1 d+ m. q3 I4 {# W2 s6 j# k. _
    0 C, b/ G8 M3 Z    sys.exit(myapp.exec_())
    5 S& p. u2 l3 T6 j8 N1 E2 q3 p9 r7 Q% P# B* J9 X
    运行demo.py并执行查询后的效果:
    ( L) Y% d( i" K8 ~/ d6 m5 R1 `# Y! k# |# P# Z1 ^! u, g

    " H, J  E" D! E& _' z# S( Z8 {2 n
    $ |3 e5 r& W. E" J# Z+ ]% M% Q8 o4、将代码打包成exe文件1 }9 u+ v, I) y2 A4 s0 R
    * ^8 K4 e8 H# D3 `
    将.py文件打包成可执行的exe在Python中称为freezing,常用的工具有:PyInstaller, py2exe, cx_Freeze, bbfreze, py2app等。功能对比:
    ( I. [% ~' F" h0 ?8 h: L$ H2 j! I; u9 t. e% a+ C+ K
    ( n! M7 z. q% ~

    9 k- K) v$ I1 l: ^) h5 Wpy2exe:软件更新已经不活跃,因此也就略过。
    , C6 {1 u0 f8 Y) V' s
    : f; r, j/ k# p5 i& c$ {  spyinstaller:明确支持win8、win10、理论上支持win7,,支持apple Macos, linux。pyinsaller可以打包成文件夹形式内含exe入口执行文件的形式,也可以是一个单独的exe文件。
    ; `# _+ J5 S' d% k9 c! b
      I8 e$ a% L4 T4 C5 a/ K  o; G5 M. Efbs:基于PyInstaller,使用起来更加方便
    " W1 n, c1 R9 {9 o: _( p
      F2 K5 B* x% A1 u& H" {1 Y( @这里选择了fbs来打包。fbs的安装方法:; Q, v" a6 [6 t, P# @( v/ p2 Z6 X

    & M7 n2 \5 r$ u. }0 s8 Y+ d8 }pip install fbs! Y" V: Y. U3 s5 P0 f( V
    使用方法,在命令行中输入:; o! x" ]$ b/ c$ W  G9 z7 }

    . p' }8 w) Y/ p/ Z, ]fbs startproject4 f) F3 R8 [& {. {, ]7 S
    执行完成后需要输入一些APP的名称等。完成后会生成如下目录:. c3 I1 N0 |) y7 b! ?4 P! z

    1 |3 E% I5 s8 Q( K
    2 u: {6 z6 w5 f% c; u  T5 P' s4 o2 ~9 k/ g4 X, f
    将刚才编写的PyQt5的代码(demo.py和Weather.py)拖到src/main/python文件夹下,删除原有的main.py,并将demo.py修改为main.py。然后打开 main.py,在文件头部添加如下代码:) S6 W* i, A) g$ W
    * }1 _- f( n! C. V
    from fbs_runtime.application_context.PyQt5 import ApplicationContext0 X4 _7 c9 _; b# ?' y* D
    ```5 g+ ]% x5 V6 z  t' O" S
    完成后执行:
    9 `2 \2 K7 A( e1 F4 P```
    % m/ h7 t7 U/ P" A$ afbs freeze& ]# w. E/ B& i  K5 R* E2 e
    ```
    . U$ ?; G/ |  Q2 b, R# I, K2 V即可实现打包。生成的exe可执行文件在\target\MyApp文件下。
    / j8 H/ n# {% R5 w* w3 y1 d; s: C  U1 T: y0 R, L4 T5 L
    ————————————————# l% h: ]' W; t3 s1 K5 O
    版权声明:本文为CSDN博主「宋宋讲编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    ! T; F% y3 ~; ?0 B0 Y4 K2 X, t& X9 [原文链接:https://blog.csdn.net/qiqi1220/article/details/126289667
    / D. {/ X+ Z8 @( e' W4 I0 ~
      ^2 l3 R9 p8 h" o% D2 k, T8 K1 a3 A) G2 ^; R9 F. `

    3 q/ {9 Z" {- v4 L  d; `; J% t$ D
    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-10-18 03:12 , Processed in 1.805867 second(s), 51 queries .

    回顶部