QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2225|回复: 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使用指南!
    ; y' o# ]+ v! \# r! f% N8 e+ ~3 l( k# r6 t9 w( }
    使用Python开发图形界面的软件其实并不多,相对于GUI界面,可能Web方式的应用更受人欢迎。但对于像我一样对其他编程语言比如C#或WPF并不熟悉的人来说,未必不是一个好的工具。
    9 j7 m& }4 r1 ?+ r/ K
    # w: v- t- G9 b( u( e6 h9 ?1 i常见GUI框架
    4 J8 T" D; Y( ^. f. J. f- v! M3 J! t) F2 b
    PyQt5:Qt是一个跨平台的 C++图形用户界面库。QT一度被诺基亚拥,后出售给芬兰的软件公司Digia Oyj。PyQt5是基于Digia公司Qt5的Python接口,由一组Python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。# m9 i8 o) v" E4 U9 m3 E# Z

    & Y1 @4 v& G" t6 z- _4 T% ~- d' k5 jPyside6:Pyside是QT公司官方提供的Python包,上一版本为Pyside2,对应的是QT5,最新版命名规则进行了调整,更改为Pyside6,对应的是QT6版本。由于官方出品的比较看好,缺点是发布比较晚,网上的资料没有PyQt5多。  L' x2 H6 o( r
    " j5 Z4 @3 i1 ]. k9 u  B
    Tkinter:Python内置的GUI框架,使用TCL实现,Python中内嵌了TCL解释器,使用它的时候不用安装额外的扩展包,直接import,跨平台。不足之处在于UI布局全靠代码实现,只有15种常用部件,显示效果简陋。1 v& c; q" u- q

    ! T% V2 N2 I7 B* ?  `3 zPySimpleGUI:PySimpleGUI 是 Tkinter 一层包装。使用 PySimpleGUI 实现自定义 GUI 所需的代码量要比使用 Tkinter 直接编写相同的 GUI 要少得多。* K* [+ J  w/ Y) K

    3 d( \2 U6 @' X- D4 ^) u0 l1 OWxPython:wxPython是Python语言对流行的wxWidgets跨平台GUI工具库的绑定。用得比较广泛,跨平台,C++编写,文档少,用户可能就需要根据编程内容对不同平台中的GUI代码做一些调整。遇到问题不好解决,代码布局控件,不直观。5 p: K1 i: [) `

    0 T" x% {- f& y1 H2 x/ vWax:基于wxPython ,为克服wxPython的问题而制作的一个包。
    % o3 C/ r9 O% ?( H0 e6 [4 e
    ' E' d# e6 H" q1 ~4 pKivy:主要针对多点触控程序,智能手机平板等,也可以在没有触屏功能的系统上,全平台支持(Windows, Linux, Mac OS X, Android and iOS.)使用Python和cython编写,中文支持差,需要自己下载中文库并且制定路径。; @8 `$ M' K' q; I, t

    & h; L0 y* Y: c' iBeeWare:Write once. Deploy everywhere.需要与Kivy配合使用。( \- x( a4 ]' |) {& M# W) J

    0 a2 Q1 `' p9 k( |& ~Toga:一个使用Python开发原生APP的GUI工具包。Toga由一个具有共享接口的基础组件库组成,以简化与平台无关的GUI开发。Toga适用于Mac OS、Windows、Linux(GTK)以及Android和iOS等移动平台。: C: g# O- e/ u: D3 q' ~) }7 l
    0 R6 `8 w% v) E% _7 `
    Eel:一个轻量的 Python 库,用于制作简单的类似于 Electron(但是比它更轻量) 的离线 HTML/JS GUI 应用程序,并具有对 Python 功能(capabilities)和库的完全访问权限。; o4 k0 j8 s6 V* X6 ~! l8 ~( S

    ) W, d' p: h( Q8 ]8 H& hFlexx:一个纯 Python 工具包,用来创建图形化界面应用程序。其使用 Web 技术进行界面的渲染。你可以用 Flexx 来创建桌面应用,同时也可以导出一个应用到独立的 HTML 文档。因为使用纯 Python 开发,所以 Flexx 是跨平台的。只需要有 Python 和浏览器就可以运行。
    ; G, M; N: ~% v1 E. C2 d" O6 |  Y
    pywebview是围绕 webview 组件的轻量型跨平台包装器(wrapper),它允许在其自己的本机 GUI 窗口中显示 HTML 内容。它使您可以在桌面应用程序中使用 Web 技术,同时尽最大可能隐藏使用浏览器构建GUI的事实。9 Y* k! B0 k9 W  g& y& H. Z

    # @5 k- M3 O: j' M7 S  Senaml:一种能够让你用最小的努力就可以实现高质量GUI界面的的Python框架,也是一种独特的编程语言。enaml将声明性语言与基于约束的布局系统结合在一起,使用户可以轻松地定义灵活布局的UI。enaml应用程序可以在任何支持Python和Qt的平台上运行。
    ) t3 y8 v# _# h; M
    ! ^: p# h" D8 Y% T( Q个人想法:太多学不完,先学PyQt5,原因是资料多,学有余力再学pyside6,最后看下PySimpleGUI,看能否解决一些简单问题。2 Q! K, N! D/ m& q: W, D$ I
    # U# L* F. O) D& Y, U. i
    PyQt5简介8 a( F9 Q4 u& E# g* l) F8 y
    % n3 }( a$ F9 ]: d0 v7 f# j" g! W
    PyQt是Qt框架的Python语言实现,由Riverbank Computing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件,因此PyQt的API接口与Qt的API接口很接近,但PyQt不再使用QMake系统和Q_OBJECT宏。
    / M+ b3 c" ~5 Y
    + Q2 V" t/ V7 _! qPyQt5提供GPL版和商业版证书,自由开发者可以使用免费的GPL许可,如果需要将PyQt用于商业应用,则必须购买商业许可。
    ' r6 ?- m5 f+ r9 {0 }% A$ ?+ d2 @( [9 y5 i8 Q9 z8 D" O7 Z
    PyQt5特性如下:
    ; L9 B5 m* C3 X1 T  f7 Q$ J7 x& P, [
    基于高性能的Qt的GUI控件集。% x% {5 {: y6 K/ Q/ `
    : u$ W; P4 n8 |. t4 I. _
    能够跨平台运行在Linux、Window和Mac OS系统上。
    " L3 ]& v( T7 A5 E+ @
    + c% B& z( l7 `3 a5 `使用信号槽机制进行通信。
    ) m8 n& m3 I5 R- F# ]' H
    4 O; \2 q- B9 `1 Z; L, N对Qt库进行完全封装。* l8 I& v2 |5 T& i. Q. P

    + ?( z% i# m. K/ r可以使用成熟的IDE进行界面设计,并自动生成可执行的Python代码。
    0 q1 }- F1 F7 g. b+ Z; x( L" K* ~8 o* E1 h* t
    提供一整套种类齐全的窗口控件。
    : a4 O2 E7 z4 E9 L
    7 E* K& y5 o% k' Z' h9 N+ k% KPyQt5是由一系列Python模块组成,有超过620个类,6000个函数和方法,主要模块如下:3 t. W* E6 O3 K& ?! c

    4 _6 }- R" w# |" J4 ?QtCore:包含了核心的非 GUI 的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime 类文件、进程与线程一起使用。* q, h3 L' m: ]: i5 Y) ^

      K$ h  J) V4 O  l( R: |/ D$ xQtGui:包含了窗口系统、事件处理、2D 图像、基本绘画、字体和文字类。7 q6 E; D. \2 d

      G8 o. k. p( x( ~7 i. O& aQtWidgets:包含了一系列创建桌面应用的 UI 元素。  V2 p5 E* B, z1 a  B' Q

    % h1 M" G9 `7 j$ W0 S* z; VQtMultimedia:包含了处理多媒体的内容和调用摄像头 API 的类。. O" d1 J  o5 \/ l! D8 N0 v

    ! s) f5 N; z* t7 K- o4 qQtBluetooth:包含了查找和连接蓝牙的类。: s" w4 H& c5 Q/ x
    2 w9 D3 e! Z2 F* E: N
    QtNetwork:包含了网络编程的类,这些工具能让 TCP/IP 和 UDP 开发变得更加方便和可靠。
    7 _& A1 Q- z5 C+ P: ?% h; f( ?9 O1 `3 D
    QtPositioning:包含了定位的类,可以使用卫星、WiFi 甚至文本。
    % T2 n1 L. Y, N6 |7 w  w$ K" ]  J# m2 r0 F. v/ b7 U$ M8 c7 N/ E
    Enginio:包含了通过客户端进入和管理 Qt Cloud 的类。/ Y$ H: z+ O' _$ O
    3 N8 G8 W0 R- |( _9 G1 a
    QtWebSockets:包含了 WebSocket 协议的类。, S5 n2 V! `# m8 m* u  `# p

    6 x1 r6 N  i  t2 s, e) tQtWebKit:包含了一个基 WebKit2 的 web 浏览器。
    1 E+ v( y0 J6 @/ ]  A
    0 R9 e- T2 {. E4 r/ ZQtWebKitWidgets:包含了基于 QtWidgets 的 WebKit1 的类。
    % _+ ?  U! [3 ]* y8 l* N  U' [! K$ z/ m. x3 ?/ |  s  M2 C! @
    QtXml:包含了处理 xml 的类,提供了 SAX 和 DOM API 的工具。' J9 _) r# Y* K3 h/ g3 S; P
    # q1 S6 y) h6 L, }
    QtSvg:提供了显示 SVG 内容的类,Scalable Vector Graphics (SVG) 是一种是一种基于可扩展标记语言 (XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。, @) [" E( t; @+ h- p3 w

    : N! B; s  m2 x" [QtSql:提供了处理数据库的工具。
    % u( e1 H. w* g7 x
    8 ^7 H2 b0 o7 f; P8 M1 h3 n" rQtTest:提供了测试 PyQt5 应用的工具。
    % o7 {1 q+ \' r! b& d1 ~7 w) p( s1 l& G7 t+ j6 o- C2 S+ Y
    PyQt5的安装! n4 Q+ j6 m% ?1 K! J; Y
    & d2 ?3 a8 z- f9 e: x$ _1 U  J' p; E
    由于后期要使用fbs进行打包,fbs对Python 3.7以后的版本可能存在兼容问题,所以我选择了Python 3.6.8进行了整个环境的搭建。主要内容为:Python + PyCharm + PyQt5 9 F' Z0 O8 O. W, n7 k. d( U2 @7 ~

    ! Q& S8 P/ ^5 }4 r, j" e" Q: C$ @安装PyQt5
    6 f* T$ t1 R! S2 _* W
    / O5 ?7 g; X5 V! [0 S( Npip install pyqt5' c  ]0 a. n- W

    ' t  @; C9 T6 Apip install pyqt5-tools8 r& K3 ~. Z$ u/ c
    其中pyqt5-tools为Qt Designer拖拽式的界面设计工具。安装过程中可能会报如下错误:
    3 r2 B$ ]% S- I, {
    8 ]! Z9 Y0 N4 `. Y$ y' n( A/ mqt5-tools 5.15.2.1.2 has requirement click~=7.0, but you'll have click 8.0.1 which is incompatible.
    % y; s2 M& f. {, q1 x+ D解决方案:
    3 S) f9 [! w; B* K7 `" F9 L
    8 J8 F8 Y6 m$ j! z# N' M+ f3 }# A  bpip install click~=7.00 Z0 ~# G$ z- _3 ^
    Qt Designer的配置
    % \# X! _4 o5 |
    0 b0 K: L8 r  F; w9 b; l6 ]( ~Qt Designer 是通过拖拽的方式放置控件,并实时查看控件效果进行快速UI设计。8 E1 x+ ^9 O7 V9 w! @. N8 U( h

    6 K  I7 B$ z5 m9 E! b# `- A& x* c2 v7 l2 a9 d

    ) G3 |! F0 y! g3 v; l整个画面的构成:2 L. _# b# G1 `8 P5 V! M% f% l

    9 a7 k; V" M9 X# r. V5 {! G, {- ^左侧的“Widget Box”就是各种可以自由拖动的组件% X/ h5 V8 J5 l* I' Y1 R
    # ]! Q. T. m# `  Z. s" W% o# i3 K
    中间的“MainWindow – untitled”窗体就是画布
    $ U( ~# B6 v) I
    / N. I& h0 G# A" |$ a7 a' t右上方的”Object Inspector”可以查看当前ui的结构
    ; ^! @" A9 m- x+ i6 k" {( W+ G4 |; d& P' f
    右侧中部的”Property Editor”可以设置当前选中组件的属性. `9 Y" v2 y: n" R9 C  `/ k

    - B# `1 x7 V; G8 {' T4 _  B. m右下方的”Resource Browser”可以添加各种素材,比如图片,背景等等
    / {; C  q/ Y6 H8 F
    8 U" o5 \" j7 t最终生成.ui文件(实质上是XML格式的文件),可直接使用,也可以通过pyuic5工具转换成.py文件。
    ' `  I# A5 d0 v. Q, ?' v# X
    . a3 \" q$ I8 S6 }QtDisigner配置9 c: w. t) k3 X3 A" J3 Q( [8 e

    ' U0 M0 Q- E4 `; c在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    % P! g& ~  C  c/ b2 P$ U2 h9 r( {) [$ m7 d- r8 V! X
    Name: QtDisigner
    ) x0 x6 T: O. H! u' L2 n( g, ?  R
    Program : D:\Program Files\Python36\Lib\site-packages\qt5_applications\Qt\bin\designer.exe # 请根据实际修改, D/ e/ `7 r+ u  C, X3 w7 H  Q) b6 `

    1 e) l# {2 H: OWorking directory: $FileDir$
    ; \6 j. V" G! }, d+ H- ?2 iPyUIC配置- W9 l; j* l5 q( ^+ w( I$ @' l; ]

    2 q: h. W# t2 g3 u% b- w6 {PyUIC主要是把Qt Designer生成的.ui文件换成.py文件。! Y4 n' B0 p" K/ o/ p: m
    $ w2 J$ s2 ]' W& S3 g
    在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    & O" l9 ?0 o1 u# a. }: u# N8 _
    ( m3 F- \7 y) uName: PyUIC4 j# c; v$ f2 E5 s1 w, g3 P! O

    7 O% b: l9 O  ]7 X& h5 d8 J$ {, fProgram : D:\Program Files\Python36\python.exe # 当前Python目录,请根据实际修改( s+ ~& c# T4 j

    ; J- b; [  Z6 z' F" @# yArguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py( F" R3 ]$ D) [6 g; P# O

    % ~* ]8 e+ {8 n. kWorking directory: $FileDir$  a' j: O- u/ V( F( ^" v
    PyRCC配置8 I  B  |& F* b, t( `

    - e- H, ]  {" b9 |# {) a; E( O$ XPyRCC主要是把编写的.qrc资源文件换成.py文件。在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    $ H. F+ L* Y# S! L
    . x% E2 ?: j' l* w/ ]" kName: PyRCC4 [! a9 {/ i- O8 A7 M2 d
    4 w) {' E6 J, Z  C5 I
    Program: D:\Program Files\Python36\pyrcc5.exe # 当前rcc工具目录,请根据实际修改
    - T* W, u' z1 S- c0 C8 x! m3 l: \: @, M" F3 C+ Q# I' ?
    Arguments: $FileName$ -o $FileNameWithoutExtension$_rc.py
    ' `& Y4 _4 z! X; i6 B& T, U! \# T% D9 z
    Working directory: $FileDir$
    $ n+ h' [2 E8 i7 qPyQt5使用示例
    7 n6 q- R' U( l( t- u
    . E! x2 j/ J- S1 b, W! m, A2 K; m+ i创建一个空白的界面:9 k! {9 B8 Q" E7 n6 L

    $ k% c( z% J9 y- ]import sys
    6 Z( |/ L: G! B3 n6 T* n8 V/ i# x! p9 v: C9 m( ^! V
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
    * i4 @  C6 c9 q$ d5 ~' ?) ]: H- A- E$ s5 z+ r! x6 t/ A+ u0 N
    app = QApplication(sys.argv): i5 c* i) z% X9 S! R0 K1 U, l
    2 J* i% e% c6 H: J
    win = QMainWindow(). O, |9 u" M0 v, ^

    7 U# P7 b) O! y/ E+ u! cwin.setGeometry(400, 400, 400, 300)
    4 w+ b$ u1 }" m8 F+ L6 g
    8 u3 F' w- z# }; zwin.setWindowTitle("Pyqt5 Tutorial")
    3 v* L. I$ Q7 Y. L7 ~4 W# ~4 z- e6 z: y2 I- o
    win.show()
    : m, B6 ]% S* ?* K1 }  {2 h2 P6 a
    sys.exit(app.exec_()). c, T7 c2 U6 H* x5 b/ @3 D0 d
    0 \2 @% V  s0 `- ^9 }6 k4 @: ?# f
    + l+ E/ n' u+ Y( M: u$ B
    : N' _/ y3 L+ r) c9 Z. w" {
    其中:2 \! ^( t: e+ K
    ' d  T, S4 C* }  A: y
    Qapplication():每个GUI都必须包含一个Qapplication,argv表示获取命令行参数,如果不用获取,则可以使用[]代替。
    , n$ V9 u" b: q
    . G6 X8 ]- t, R, }QMainWindow():类似一个容器(窗口)用来包含按钮、文本、输入框等widgets。arg标识可以获取命令行执行时的参数。8 {* Z" ?% B- k( s) }+ X

    + K$ J1 T0 Y/ b5 D6 Y; RSetGeometry是用来定义 QMainWindow() 窗口的尺寸, 语法:setGeometry(x, y, width, height ),其中x,y为屏幕上的坐标点。
    9 Z4 A+ t- U8 S- _* j0 A! t3 b: ]' o
    ; f$ k" k! \& |5 H0 d1 Bshow():用来显示窗口
    ( g- k7 J3 O+ S/ t; A) c! Y  z; W  c) u; j
    exit(app.exec_()):设置窗口一直运行指导使用关闭按钮进行关闭
    4 Z8 B( U. m6 {1 }( ]" \
    # m2 Q( M5 t" fPyQt5支持的常见Widgets有:
    7 l2 z( e3 F) e+ [/ t
    / r, K6 i; R* V1 E+ q5 @% [! C) p1 C0 M" ]) u
    8 K2 M. a, Z3 H& O' S. a) k
    从上到下,从左到右依次为:Qlabel、QcomboBox、QcheckBox、QradioButton、QpushButton、QtableWidget、QlineEdit、Qslider、QProgressBar
    ) y( C+ |0 _5 `+ E2 |0 e* A( W0 s$ a2 l. P4 E2 x5 m$ k
    对于使用Pyqt5设置文本内容,我们使用Qlabel:
    ) @/ H% t5 |0 X: L2 T0 _& _% [( |  e3 b' C7 b) f- m7 w' s
    import sys
    & `6 k! h" `' V, c; L9 K! @7 {9 H# ~6 T! i- ]7 B
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel0 T; C0 m! w  M4 p# h6 j. ^( X
    * c) c% _5 z$ @
    app = QApplication(sys.argv)+ L2 h5 L+ [& A' ]' z% a* a
    7 N' Z$ [, i3 t4 X2 |/ j/ z
    win = QMainWindow()
    + K' [9 w$ t/ [4 Q+ \5 T- c, \+ f+ Y
    , @* F) e6 W6 `8 Nwin.setGeometry(400, 400, 400, 300)
    8 H0 J) v5 t8 w4 Z# l# a* |/ d
    , N3 Y* P* L( F4 C" N4 D3 jwin.setWindowTitle("Pyqt5 Tutorial")
    0 J0 V' |- R. A1 Z' y2 }* r% a) I$ @5 r, i
    \# Label Text7 R; w) P; n3 o8 d' N9 u# p" [
    2 P" P+ D+ ~8 ~1 N4 e9 |/ S( E
    label = QLabel(win)
    ) ?  g$ ~2 R$ O7 C8 m  f% Z% H, J, X& F6 M  A
    label.resize(200, 100)2 C9 J4 z$ C9 u- w, \+ l4 c

    % _0 S, f2 Q. |5 W. Jlabel.setText("Hi this is Pyqt5")- N. T: d3 z  F

    - V" W% x/ N1 ylabel.move(100, 100)9 T% r) r) p. f$ |* J7 q

    2 u; Z4 R% L6 w4 g- U5 G7 S2 g6 Bwin.show()& C" b0 H5 n) |% `/ O6 j

    . l9 Z; R) r' ]6 u6 ]sys.exit(app.exec_())4 g. N+ J$ |( [6 X: o6 U
    1 J. B/ c5 k* C0 |7 F
    : {% e7 E9 h( a3 M7 S

    : w0 O2 v2 Z$ _. U1 _8 E: c- C按钮与事件:9 _2 H( y/ B7 X
    9 _1 R9 n3 o6 L5 d& X
    import sys& d: W) u: }* L3 L: Q: M
    4 T# T+ f# D9 q1 M: x0 a( M
    from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
    * `4 y( i; Q* g- \7 v) |$ i: X6 q1 t' B4 N
    def click():
    " b4 Y1 Y# C0 G7 I  S  N6 `
    4 s! b: Q8 r, N# @6 y    print("Hy Button is clicked!")/ L2 @$ h2 g7 {0 h, ?
    7 T3 ^+ y# O: X
    app = QApplication(sys.argv)
    4 ]( [6 y# r+ o1 S2 @
    * d0 L. s( m  d1 h4 w: Swin = QMainWindow()
    * s- p  m8 m. D9 l4 p
    4 M3 t/ K2 C2 R3 t7 X  L# gwin.setGeometry(400, 400, 400, 300)" @$ P5 o# p" s4 I

    ( r/ Y; r1 d: j0 ?( kwin.setWindowTitle("Pyqt5 Tutorial")  C3 b# @8 W" i5 H" L$ |

    2 v# S5 d3 Q# L. k- \& Z6 D\# Button% ~' j" a. q+ p8 m

    $ f. m! q; Q" q& z7 t1 l5 T6 S3 Abutton = QPushButton(win)
    5 e8 w9 J9 o. z4 ?( c9 p
    ! d6 |  j  x6 {; E+ fbutton.resize(200, 100)8 q6 f0 k/ p8 I) |; {9 {
    5 }7 M+ |# i$ \, }/ V6 T1 ^$ H9 V2 A
    button.setText("Hi! Click Me"). @" |* N* Y# L
    5 E: n; S0 ~, l* X+ a
    button.move(100, 100)- r; C' t2 B9 {  Z! V

    ' F; i" O/ n9 c/ @2 Qbutton.clicked.connect(click)6 V/ s7 |4 r, c2 d7 t0 I0 [
    5 i8 j& |' M) W; B- Y0 m
    win.show()% L4 u% q. \: @  m2 E* u
    5 a$ c, g7 `( B& e9 v& p. h
    sys.exit(app.exec_())1 M. a" J# y3 j! K, f; w

    1 H  t; P1 l+ D: R( ^  Z; |/ X& C9 R& \5 c
    * `8 x; ~7 L0 E! w9 K. H" X
    button.clicked.connect() 在按钮点击后执行特定的事件。5 p8 l, N! r% g4 c
    4 j9 X9 j( p6 ~& l; A6 [
    PyQt5实战, S; y" E1 ~$ j3 D5 K; q
    0 S. R" u/ U/ J& g/ G* t
    实战项目:简易的天气查询软件8 _) d. g% h0 `
    ) _% w1 @( J1 ~9 e* H' D7 B% w
    1、使用Qt Designer设计一个界面5 M7 N+ S. q7 j6 o  `

    + ?! k' w9 M: O5 l' v" K$ h7 l/ H, e) W4 G
    % f: W6 y/ r% D1 V
    用到的控件有Button, GroupBox, Label,ComboBox,TextEdit,同时定义了两个按钮queryBtn及clearBtn,分别用来查询及清空天气数据。我们需要绑定槽函数,方法如下:
    # a' j  j) Y4 a1 x8 d
    1 ]5 E+ e" }: Z7 D在Qt Designer右下角选择 信号/槽编辑器,点击+号新增: K& G/ r5 E+ I! S, e  |% G

    + H* \/ _) [" E% X分别选择queryBtn及clearBtn,选择信号 clicked(), 接收者 Dialog 及槽 accept(),(槽函数这里不知道如何定义,后期在代码里再进行修改)/ M2 _  ?' ~2 \' ~
    1 ?; h* }5 A5 A; E
    以上完成后保存为Weather.ui文件。
    9 G1 d& a, m- F  [8 x% B( N7 ?$ _- y( B. X
    2、转换.ui文件为.py文件
    ' I& [1 x) o3 E' L7 o% Q: S
    3 w' v  ^0 @  z6 i4 U* ]  LPyQt5支持直接使用.ui文件:
    ' x: @1 [1 Z! ?# _9 L+ j1 i, }7 b( u9 e
    import sys
    & T% H! \/ L, t) |& B% P& Q' k; ^5 Y0 i5 t  q! F$ g2 X
    from PyQt5 import QtWidgets, uic
    4 J  `) m4 B6 Q- \' p; `
    5 U9 ?# P& ^, R$ B& Y" ^, Xapp = QtWidgets.QApplication(sys.argv)
    * d  T8 ^. s5 e: d4 r% }" \) p; U' E
    0 J8 O2 H' b" I* e. h6 x7 Swindow = uic.loadUi("mainwindow.ui")
    2 i$ r8 @3 ]6 C5 b4 f3 R. ?# B
    , }* J5 p- c. Z. f$ _! w9 owindow.show()
    / N4 Z# g( k( N5 n  _
    7 [! Z+ u0 \: ^# P" I  f3 ?  M" Kapp.exec()* e5 ^7 a. N# j* K3 e
    但是为了更好的自定义及修改上面的槽函数,可以使用External Tools – PyUIC,即可生成Weather.py,实际运行命令如下:
    + d$ W8 _1 x( d1 @0 }! u6 C7 n5 F) b1 k# `+ _
    D:\Program Files\Python36\python.exe -m PyQt5.uic.pyuic Weather.ui -o Weather.py
    : g% X, d' ^9 ~* A/ k  }其中,我们需要把两个按钮绑定的槽函数:
    / V' e# G# J) _$ B7 ?
    " ~! v! l. @2 r. ~0 q4 L6 Z\# self.queryBtn.clicked.connect(Dialog.accept)! E; Y* ]( \% g4 i; @# n

    : M! @8 p+ S3 L/ `' y9 M\# self.clearBtn.clicked.connect(Dialog.accept)
    * y5 Q  {- Z; I) s) Z7 b$ U, P- R$ Y! d  _
    \# 修改为:- f( L4 ]% T- J0 M* f

      i- ^! A! g3 ]- q# e. E$ Vself.queryBtn.clicked.connect(Dialog.queryWeather)+ |7 c7 }; J! T" F; l) x% Z3 t  ]
    0 Y% w! F& Y2 z
    self.clearBtn.clicked.connect(Dialog.clearText)7 V9 }4 e0 D$ ?+ D" P
    最终的Weather.py内容如下:
    6 h) H) X5 I3 b! I1 V! l! X$ z, D
    \# -*- coding: utf-8 -*-1 J7 o+ e8 H9 T8 _0 ?4 i5 U, c  {

    - b5 J- Q" z, M8 ^\# Form implementation generated from reading ui file 'Weather.ui'. c/ @3 H, @1 [: W4 f: e

    ( }1 _, V% G" {\#
    ( C: L  E1 }+ c
    5 {' s1 z/ X& o, K\# Created by: PyQt5 UI code generator 5.15.4) r- `* u7 T0 u8 U
    8 X9 G9 y7 u7 I; b' r5 R
    \#
    / o- J: ]( N7 W* q4 T, T& |( e# W/ o! `
    \# WARNING: Any manual changes made to this file will be lost when pyuic5 is
    * A1 t+ T6 P, C0 J3 w
    : {+ b, b$ L$ @% o. M- s* y' ^\# run again.  Do not edit this file unless you know what you are doing.
    9 U2 J# q, ?8 i1 r5 z- u% \1 q+ ^. |, y4 x- c+ g, T4 `
    from PyQt5 import QtCore, QtGui, QtWidgets
    . s6 Y* S, \2 }: E
    ! k$ V2 P  L+ R" gclass Ui_Dialog(object):
    # C% c$ k8 L0 K/ G) p8 W( L9 s# o6 r: M8 c) w6 S7 }: N! X
        def setupUi(self, Dialog):
    + d* q' _" U3 ~/ V! w+ J6 c! v' A6 O* o7 }: S' h$ N( o
            Dialog.setObjectName("Dialog")4 C9 E' X, f7 J0 R$ Z& T; m$ h1 {
    ) C: D6 ]2 @: J5 |) A9 X6 B3 O
            Dialog.resize(600, 600)
    ! m, x/ z. i& t- P' {3 D
    ' @" G4 o/ `. z0 Z        self.groupBox = QtWidgets.QGroupBox(Dialog); @# h* M4 Z% M' Q/ Y) e

    8 G+ [2 L6 E( c0 [        self.groupBox.setGeometry(QtCore.QRect(30, 20, 551, 511))
    3 y- i% B$ X& X/ c7 d" s: b4 y9 C0 s  B, x4 c- ?; T
            self.groupBox.setObjectName("groupBox")
    8 o" [' {: \1 m
    3 d5 {5 v* d  z4 `; |1 Q$ h        self.label_2 = QtWidgets.QLabel(self.groupBox)
    + u* a# Q- x* s$ R/ K% P% Z& v6 K6 @: k
            self.label_2.setGeometry(QtCore.QRect(20, 30, 31, 16))  `- |; o' R9 R" |7 n0 j$ i) H

    3 x5 s# i' J! o4 }0 L3 D        self.label_2.setObjectName("label_2")
    ) x. t# F. \" `1 K1 h. H6 ~4 R
    6 K8 ]' f! h: w6 @: |0 t' [        self.comboBox = QtWidgets.QComboBox(self.groupBox)8 Y; Y9 {, C- `1 P# i$ S! S
    . D6 o1 H9 u2 ?
            self.comboBox.setGeometry(QtCore.QRect(70, 30, 87, 22)). |: T! {/ j; _, ~' n/ N% i7 L8 v
    7 t: K& U: G1 |$ V% `& W
            self.comboBox.setObjectName("comboBox")
    7 I! i( z0 V* b/ C9 l
    5 @; Y. \5 k/ p7 J8 t. Z        self.comboBox.addItem("")- D8 o/ H+ S& @* {8 F7 O
    ' ?) ]- m/ o  }1 \
            self.comboBox.addItem("")
    / e* f1 m5 S" r3 A) Q. C. ?. ~" g$ v
            self.comboBox.addItem("")& I' M' P8 N9 b$ V9 A

    3 n2 k% R6 B+ f7 S. H        self.textEdit = QtWidgets.QTextEdit(self.groupBox)
    5 m. H9 ~. M2 a  k
    " |) P) C) v3 \        self.textEdit.setGeometry(QtCore.QRect(20, 70, 491, 411))
    % Z7 A; L: M. v/ J& m1 d
    ) k" ^5 x* W2 Z0 Y" @        self.textEdit.setObjectName("textEdit")4 `: Q( I0 W6 E0 c( B, C8 M1 R1 o' G

    6 m4 h8 v" `4 K7 Q/ }* `5 x        self.queryBtn = QtWidgets.QPushButton(Dialog)" t4 A8 e& l; N1 z1 W( T" |! n

    9 K9 ?' y9 O- J4 y        self.queryBtn.setGeometry(QtCore.QRect(490, 560, 93, 28))# W: i/ ]3 h+ G+ y- S1 l3 k$ K1 h
    % l  ]8 m9 }1 y2 G. x6 s5 P5 o
            self.queryBtn.setObjectName("queryBtn")% H. @2 `4 n5 ~  N2 ]

    & L; A4 m( U1 G- m' v0 V        self.clearBtn = QtWidgets.QPushButton(Dialog)+ |, U' |6 L: y/ R1 d6 D0 x

    7 f- u3 a- w) r' X& J        self.clearBtn.setGeometry(QtCore.QRect(30, 560, 93, 28))
    . s% \8 E, z/ K: w7 x6 ?
    / a7 Z) y+ @9 N8 y* S        self.clearBtn.setObjectName("clearBtn")
      S; M* s* I% B! S$ [0 S! L$ D5 `/ p. `
            self.retranslateUi(Dialog)
    " X$ |/ T. I+ \4 Y& I
    ) T2 t5 V" F/ r, q  M; a' k        self.clearBtn.clicked.connect(Dialog.clearText)0 ?. ], Q& g1 k5 X" |% C

    , f1 `( k2 U5 B. N        self.queryBtn.clicked.connect(Dialog.queryWeather)
    7 U# s5 h3 I! w1 `5 s3 l3 {
    7 C. b" _1 H, O5 p( E* o3 B, ?7 }$ B+ C4 x        QtCore.QMetaObject.connectSlotsByName(Dialog)
      k$ P# g, j( j9 K1 n
    : _/ C6 c- J$ @1 `0 Y    def retranslateUi(self, Dialog):
    1 b7 x# ?* g, x$ \% Y! r% B% A& Z8 p% O2 ^
            _translate = QtCore.QCoreApplication.translate( G$ L9 d, {$ C
    " R% Z1 c; S0 r: b9 f6 A7 }
            Dialog.setWindowTitle(_translate("Dialog", "Dialog"))+ m: N5 b% \1 A0 j' }
    " c1 ~( N2 g1 I0 H$ f
            self.groupBox.setTitle(_translate("Dialog", "城市天气预报"))
    2 @6 E! `3 h4 h
    : O0 }6 t9 ]' w# y$ N2 t; x0 ~+ n: z        self.label_2.setText(_translate("Dialog", "城市"))# p4 ]/ S* p3 n& H( I1 @1 t
    % q8 K/ a. H' `% p
            self.comboBox.setItemText(0, _translate("Dialog", "北京"))- ]- |) j2 }% V3 J( U3 f
    4 \, |1 G& l, s3 X
            self.comboBox.setItemText(1, _translate("Dialog", "苏州"))
    9 M* S! g$ b) L$ g5 X$ H/ x/ A8 n6 H. M5 U
            self.comboBox.setItemText(2, _translate("Dialog", "上海")), c& Z" m6 n4 p" _
    ) b4 t' l8 }' ^( h, f
            self.queryBtn.setText(_translate("Dialog", "查询"))& |. |+ O5 Q2 ]5 N; b3 J3 y7 r2 P
    / T% n1 ]1 q! W! y  T: k1 s
            self.clearBtn.setText(_translate("Dialog", "清空"))7 l) F( r4 m0 |4 H4 o0 U9 t5 ?+ w
    - i# f# W* ~/ e+ @3 m! _+ x
    3、调用MainDialog8 a: j% a, F' o# ^
    9 ~$ y: w. i8 {1 x1 a" X6 r
    在MainDialog中调用界面类Ui_Dialog,然后在其中中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。新增demo.py文件, 在MainDialog类中定义了两个槽函数queryWeather()和clearText(),以便在界面文件Weather.ui中定义的两个按钮(queryBtn 和clearBtn) 触发clicked 信号与这两个槽函数进行绑定。
    ; F3 e1 V6 T$ v* `5 S9 B, I1 _' X/ B3 d& O& o) r9 L0 z
    完整代码如下:5 a) R* ~3 `8 A# P' z+ B

    - U% v! G" F. L3 B7 G, [import sys
    . h* h+ O* t  r9 r
    / _9 _! e) V* {import Weather
    : c# Y6 O5 Z9 Y2 N: J0 w& A. V* }- b' |
    from PyQt5.QtWidgets import QApplication, QDialog
    . v, _' s9 k! C! t+ n
    9 q+ i! p7 ]& b" u) c) J0 jimport requests
    1 t$ T: d6 o9 k9 x4 z: M
    9 ?5 I5 b: d. Vclass MainDialog(QDialog):
    4 ?0 z- |; Y! _( @9 Y5 r& @% J; |( L1 Z8 O
        def __init__(self, parent=None):) m1 }) s+ H. @9 I5 a6 @" H# B
    ( P) K! j4 l) a5 z/ P- z8 b- R
            super(QDialog, self).__init__(parent). l! E- l) Q8 n' ~# T" b( w

    7 e0 T% m; b1 ^6 z# H        self.ui = Weather.Ui_Dialog()2 Y8 w; P0 y, x0 r% i8 O2 C) U

    3 W. i6 E6 L& s        self.ui.setupUi(self)
    # b% q( `) |5 `4 {7 b; }( p4 k4 l9 z: @
    & R- `0 [. h8 t4 a/ M% V0 c+ ?3 q    def queryWeather(self):
    1 t5 x% Y; \. |+ t. A
    , P5 g$ k- ]8 v* p- C, Y! d        cityName = self.ui.comboBox.currentText(). I6 q' w& a& b* _4 X
    4 M. s2 h! r9 z) ]: O
            cityCode = self.getCode(cityName)- a* O( Q5 [) `' o7 R
    / }! |+ z4 P' n+ t
            r = requests.get(6 N9 k) V; m+ h7 p

    ' ?3 [) j: |  e* v' P3 s) j' N            "https://restapi.amap.com/v3/weather/weatherInfo?key=f4fd5b287b6d7d51a3c60fee24e42002&city={}".format(, f/ q" B, b' m, M! V6 W6 D/ t( X

    # A" ~) b' Y2 y) l4 a, v3 D- M" ]                cityCode))8 @8 p1 D4 M- ]* k

    ( O) m, h- q! K        if r.status_code == 200:0 V# Q% Q0 F% m! p
    8 [: j  O9 z3 T# K" g
                data = r.json()['lives'][0]$ x  j+ `9 Q6 J

    ( O, N% K/ U: }+ g) I- {            weatherMsg = '城市:{}\n天气:{}\n温度:{}\n风向:{}\n风力:{}\n湿度:{}\n发布时间:{}\n'.format(, t+ P3 t7 ^2 j2 _; j
    4 Y$ D: R/ m4 s5 t* \7 @$ e
                    data['city'],' z+ J4 {, U' w. O% t; ?

    8 s5 u: \( w- j2 c                data['weather'],
    # z/ J; v% g% L: v$ M3 B. E, e: j' q5 p% P0 y- I) C0 M- P
                    data['temperature'],
    * W! Y, ?2 L) I) t) _
    + J3 v  C  l8 G$ U2 H. I                data['winddirection'],
    ' e- c4 v7 d3 ~, s/ ?0 G8 I- H0 w& {. z, F
                    data['windpower'],
    7 O, L/ _7 ~  S: @- ~# k. D! X
    % y* j# X- x6 q" V% b# C1 T$ V                data['humidity'],* l: A* s" [3 Z# W& F$ w
    9 V. O1 N3 D6 i- M9 s3 l5 {
                    data['reporttime'],
    # a; L3 h" N+ D5 A
    * \4 p/ l! h5 X            )
    , L0 c% {- f% b+ F" Q/ [: A9 V
    9 p" G* |3 O, e% J8 _+ a        else:* ^/ s, ^8 `& |1 A0 D

    0 A6 L4 i/ q$ \            weatherMsg = '天气查询失败,请稍后再试!'
    " z; \( J7 S2 e# s2 D5 a; h
    . f. p, ~4 C$ y7 m' T        self.ui.textEdit.setText(weatherMsg)& |% E4 s9 `* d# G0 |1 q$ U

    & I8 v" x8 I/ `$ `/ G. e- Y    def getCode(self, cityName):
    ! `( W3 ?1 p8 @9 r6 ~. b
    9 ?) D. u, R- E7 Q        cityDict = {"北京": "110000",
    ; {! a  b5 b! a2 x/ I
    " I& `0 X$ |( P5 P, O, J3 r+ V                    "苏州": "320500",
      s, M9 I- w  M6 q. F( D# Y) x$ W
    4 W6 C5 t. U8 w! z                    "上海": "310000"}5 B% k' Z# }. \. P9 r% J. ^1 l+ x
    % X& T, Q% ~3 p" P: O9 P) ?
            **return** cityDict.get(cityName, '101010100')
    + `" {" o; w3 ?2 [9 }1 D" ~  G8 @! M/ j6 Z
        def clearText(self):+ O% x* J# q# S" J' j$ j

    * L0 {6 N1 Z3 K0 ^$ H: A0 h, x1 r        self.ui.textEdit.clear()- ], u4 Q1 |% D, z+ }# A1 T9 d

    . K8 H+ I  z9 b! rif __name__ == '__main__':, G* Q# h& t3 s8 }6 X
    / X' \6 ^6 G; i# N, r) S
        myapp = QApplication(sys.argv)' a4 b* j: D  F' e2 U
    1 m* H( l# }/ G/ [$ g
        myDlg = MainDialog()
    % v4 e" f, t* n2 C% A/ m5 T7 ?7 X/ k& Y% V* _3 s5 v
        myDlg.show(); \! \$ l4 f6 ^% k* Y4 F
    % m1 Q( r1 l/ ?' E, f/ g
        sys.exit(myapp.exec_()); A, {1 L+ q) w5 O
    1 f, C2 V: d, e- W) k
    运行demo.py并执行查询后的效果:
      Y9 E6 C& w. L0 |8 S* y( r2 H3 \- O

    8 Z  ~& F9 ]( A2 ^/ c3 G8 d( P1 s% P5 |$ \9 J& c
    4、将代码打包成exe文件  S* o3 j8 Y* V4 F2 T

    7 O1 t" k0 C$ ]2 U5 K2 {7 z, i将.py文件打包成可执行的exe在Python中称为freezing,常用的工具有:PyInstaller, py2exe, cx_Freeze, bbfreze, py2app等。功能对比:! E1 U! @9 M9 A3 H5 ~# L9 J

    ' Z; u8 Z. n8 B7 K* R) @! p6 \: v' P3 }

    ) s5 _' t2 w8 Y6 ~1 e5 {. Opy2exe:软件更新已经不活跃,因此也就略过。$ T" A; p) |: q2 `- _

    - {4 z" ^: t4 l( q% p1 j4 I; vpyinstaller:明确支持win8、win10、理论上支持win7,,支持apple Macos, linux。pyinsaller可以打包成文件夹形式内含exe入口执行文件的形式,也可以是一个单独的exe文件。* ~, C. J. M! B: d

    , F. _  w; u4 t7 Z( ]fbs:基于PyInstaller,使用起来更加方便
    . ?( Y1 m8 z9 |+ W& w0 T# @- Y$ |9 o# R1 f/ H' {0 D% o1 a
    这里选择了fbs来打包。fbs的安装方法:
    3 e/ T  u( j: V6 c" N& F! N
    2 E8 k" a# h: P# b1 Q. d7 {pip install fbs& o- Q: }3 ~. W5 `6 B7 R
    使用方法,在命令行中输入:
    . F) f; x4 o9 V$ ^3 Z' H
    + _3 @  N: K0 s  T( F% @fbs startproject
    ) k0 `9 ^6 q" [2 {执行完成后需要输入一些APP的名称等。完成后会生成如下目录:
    / F( z, E* `% Z4 c6 Y( K% b" q* l; {" |/ J

    ( a+ D4 y# s) \7 y! E) H+ `; x& a
    ! z$ w; g; n7 B6 j4 w% u" `; \将刚才编写的PyQt5的代码(demo.py和Weather.py)拖到src/main/python文件夹下,删除原有的main.py,并将demo.py修改为main.py。然后打开 main.py,在文件头部添加如下代码:
    , S2 \3 G: [6 ?, W% [  A4 g; [! H4 ?3 Y, }! k
    from fbs_runtime.application_context.PyQt5 import ApplicationContext
    ' F9 x4 Y$ u$ Y```
    2 |2 e( D( Q9 b+ p$ V% ?/ V6 u完成后执行:
    ! Q9 v- i# F6 x6 t% I: |+ K" Y```+ p5 W0 v2 V# b/ _  B( @, `
    fbs freeze
    ) D4 R% p+ \/ F* O5 E4 w3 S& X```
    % ?- Q7 d; |' C/ O0 ?1 i: A即可实现打包。生成的exe可执行文件在\target\MyApp文件下。0 L( X( p+ l( Q' i/ A

    0 u" C" ~* G* B* t' y1 Q& B  A! ^————————————————2 a# [0 U7 o' @
    版权声明:本文为CSDN博主「宋宋讲编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。, L! Y, c1 m: J" y
    原文链接:https://blog.csdn.net/qiqi1220/article/details/126289667
    % c; f0 t' g# s3 u5 `) E  s1 V, O

    8 r7 x$ U7 S+ M* F' r* I2 X" n3 E7 s
    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-6 22:20 , Processed in 3.902121 second(s), 51 queries .

    回顶部