QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2192|回复: 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使用指南!
    6 S1 K$ P5 s5 ~( |. o3 H; ?; w* ]/ T3 X9 z+ _  I
    使用Python开发图形界面的软件其实并不多,相对于GUI界面,可能Web方式的应用更受人欢迎。但对于像我一样对其他编程语言比如C#或WPF并不熟悉的人来说,未必不是一个好的工具。8 J6 l7 C; c3 G# W  P. Q

    4 X' `7 }' S0 O, G常见GUI框架
    + p, w9 D' W. Y4 ?& b' a2 \" u
      h8 x& Z1 L. ?& B7 yPyQt5:Qt是一个跨平台的 C++图形用户界面库。QT一度被诺基亚拥,后出售给芬兰的软件公司Digia Oyj。PyQt5是基于Digia公司Qt5的Python接口,由一组Python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。
      J: @6 B% ]! m* C% k  D5 ~) K( p4 j
    Pyside6:Pyside是QT公司官方提供的Python包,上一版本为Pyside2,对应的是QT5,最新版命名规则进行了调整,更改为Pyside6,对应的是QT6版本。由于官方出品的比较看好,缺点是发布比较晚,网上的资料没有PyQt5多。
    " _1 \  s2 Z: ?4 Z5 v3 M2 H0 G% r. u
    Tkinter:Python内置的GUI框架,使用TCL实现,Python中内嵌了TCL解释器,使用它的时候不用安装额外的扩展包,直接import,跨平台。不足之处在于UI布局全靠代码实现,只有15种常用部件,显示效果简陋。- _5 w: O$ b$ n3 L/ A6 M* D

    6 @9 y6 a0 e0 r( rPySimpleGUI:PySimpleGUI 是 Tkinter 一层包装。使用 PySimpleGUI 实现自定义 GUI 所需的代码量要比使用 Tkinter 直接编写相同的 GUI 要少得多。* p  I0 k' d9 L, y* N% p2 M( [

    ' ~6 z' a+ I# w5 h7 L' N- V7 PWxPython:wxPython是Python语言对流行的wxWidgets跨平台GUI工具库的绑定。用得比较广泛,跨平台,C++编写,文档少,用户可能就需要根据编程内容对不同平台中的GUI代码做一些调整。遇到问题不好解决,代码布局控件,不直观。
    5 \  S: @2 q& }* D6 c. a+ z+ A1 g; g% D7 e. S  b: F' I
    Wax:基于wxPython ,为克服wxPython的问题而制作的一个包。, N' o7 W, K. J

    * L& o$ u" [5 |( v2 f6 b& DKivy:主要针对多点触控程序,智能手机平板等,也可以在没有触屏功能的系统上,全平台支持(Windows, Linux, Mac OS X, Android and iOS.)使用Python和cython编写,中文支持差,需要自己下载中文库并且制定路径。
    # t3 J& Z1 V. _6 |% x
    ' g& F2 @; H8 O8 U% I& ^BeeWare:Write once. Deploy everywhere.需要与Kivy配合使用。" n& B* L, z. m5 V: m

    ) g% }, O$ V' ^3 G6 jToga:一个使用Python开发原生APP的GUI工具包。Toga由一个具有共享接口的基础组件库组成,以简化与平台无关的GUI开发。Toga适用于Mac OS、Windows、Linux(GTK)以及Android和iOS等移动平台。
    , V% \5 [, c% t4 I* Q# N  g' x' d; s  s$ Y
    Eel:一个轻量的 Python 库,用于制作简单的类似于 Electron(但是比它更轻量) 的离线 HTML/JS GUI 应用程序,并具有对 Python 功能(capabilities)和库的完全访问权限。' i% E; a( s3 l0 g8 o1 K

    # ]0 e7 {- o3 r4 Z: L' {9 |Flexx:一个纯 Python 工具包,用来创建图形化界面应用程序。其使用 Web 技术进行界面的渲染。你可以用 Flexx 来创建桌面应用,同时也可以导出一个应用到独立的 HTML 文档。因为使用纯 Python 开发,所以 Flexx 是跨平台的。只需要有 Python 和浏览器就可以运行。
    $ p8 M# L/ c8 V+ h
    : ^0 B" V& [+ |; P+ C' H2 I- mpywebview是围绕 webview 组件的轻量型跨平台包装器(wrapper),它允许在其自己的本机 GUI 窗口中显示 HTML 内容。它使您可以在桌面应用程序中使用 Web 技术,同时尽最大可能隐藏使用浏览器构建GUI的事实。
    8 A" W, U0 _6 i
    # L0 U- W6 ?4 nenaml:一种能够让你用最小的努力就可以实现高质量GUI界面的的Python框架,也是一种独特的编程语言。enaml将声明性语言与基于约束的布局系统结合在一起,使用户可以轻松地定义灵活布局的UI。enaml应用程序可以在任何支持Python和Qt的平台上运行。1 A- X7 R' l8 U$ k! T4 l9 i7 c; O
    , P0 X) {8 ]6 D: ?9 N5 A
    个人想法:太多学不完,先学PyQt5,原因是资料多,学有余力再学pyside6,最后看下PySimpleGUI,看能否解决一些简单问题。* O* v% m1 N# X5 o
    $ j0 {9 H/ G& u' v* g# T6 L9 y
    PyQt5简介! l+ w3 Q' a* E& |' p

    % Q- Y. J7 P4 T2 DPyQt是Qt框架的Python语言实现,由Riverbank Computing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件,因此PyQt的API接口与Qt的API接口很接近,但PyQt不再使用QMake系统和Q_OBJECT宏。
    2 Q7 W3 s- k! W1 s/ Q. e) o  @! w
    PyQt5提供GPL版和商业版证书,自由开发者可以使用免费的GPL许可,如果需要将PyQt用于商业应用,则必须购买商业许可。0 p6 _2 p. H5 |, w

    : q$ M+ q6 t. ~2 TPyQt5特性如下:' h. h* M- A/ d7 O4 y' s! h
    # s1 i* o6 {. U% S6 q  @4 J* J" S1 o
    基于高性能的Qt的GUI控件集。
    7 m6 r, W' W9 K4 e7 A2 Z9 E: M* i5 l( T% L+ B, [
    能够跨平台运行在Linux、Window和Mac OS系统上。  L  e" p; a- l" }/ x/ E

    $ I& A. C1 m6 A. V使用信号槽机制进行通信。. P/ y" I5 I  S% Z+ m4 ]; g3 q( g

    / ~3 b' b5 [. p' F6 Y4 J# b对Qt库进行完全封装。
    1 q* n# g1 v. D4 h# Q. z4 u6 \
    , k% S4 W. L9 w% d& }& j9 ~可以使用成熟的IDE进行界面设计,并自动生成可执行的Python代码。
    3 E1 J8 f& f1 O5 ^4 ^4 v6 o7 X$ j
    9 c/ w  d1 e0 t3 |8 B' s# P! Z提供一整套种类齐全的窗口控件。& r6 c0 F4 r; q$ s% q4 f1 t
    0 ^8 r0 n6 z" g" @4 I8 ^
    PyQt5是由一系列Python模块组成,有超过620个类,6000个函数和方法,主要模块如下:
    : c1 @3 `7 S) g0 k5 b8 t2 c8 [; u" T- e/ I0 A
    QtCore:包含了核心的非 GUI 的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime 类文件、进程与线程一起使用。; [0 w6 Z8 I1 O2 S# i' A

    # ]7 {8 `- j; R5 Y. R4 nQtGui:包含了窗口系统、事件处理、2D 图像、基本绘画、字体和文字类。
    1 C1 B( s6 F! s0 }1 j( k# x; T7 r. J1 _6 r3 c& r/ W
    QtWidgets:包含了一系列创建桌面应用的 UI 元素。
    ) y4 Q/ l3 ^* P% N
    7 X. P, v$ \* x+ OQtMultimedia:包含了处理多媒体的内容和调用摄像头 API 的类。
    ( {: p1 v. q: b2 |. r" J$ K0 a9 u
    QtBluetooth:包含了查找和连接蓝牙的类。/ z  Y# i# R1 s3 T& U7 F

    2 \% f; f( t- A; NQtNetwork:包含了网络编程的类,这些工具能让 TCP/IP 和 UDP 开发变得更加方便和可靠。
    0 Q! ^0 p5 g  g
    ) E) C% s: u$ N( @: z/ c0 T0 CQtPositioning:包含了定位的类,可以使用卫星、WiFi 甚至文本。
    ( }: l% |# l+ F
    + N1 n5 a" o$ w2 I0 e4 D  \0 u) hEnginio:包含了通过客户端进入和管理 Qt Cloud 的类。" o& Y. ?  N( f, [7 g

    ( F+ s9 _; r  vQtWebSockets:包含了 WebSocket 协议的类。
    ) p+ y$ f0 P; M( f. I7 V3 ?+ _8 R
    ! c6 k: K' q9 `" I: n. P  U1 VQtWebKit:包含了一个基 WebKit2 的 web 浏览器。
    # J! }2 T- B2 p
    , ~0 `0 T% n; ]7 ^- y1 rQtWebKitWidgets:包含了基于 QtWidgets 的 WebKit1 的类。: j6 b- K+ U$ U" J

    " J# X- ~8 k5 Z3 MQtXml:包含了处理 xml 的类,提供了 SAX 和 DOM API 的工具。: d% ^+ @! `# i5 z- M, B8 R

    5 \0 V3 K& C( I6 w: `+ uQtSvg:提供了显示 SVG 内容的类,Scalable Vector Graphics (SVG) 是一种是一种基于可扩展标记语言 (XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。$ R% x4 N7 O8 f2 l3 a- w5 J; q% J

    4 A3 x. z4 B' Q( FQtSql:提供了处理数据库的工具。
    & c- Y5 B* E$ K9 p  i$ B1 j- b: V* b7 U) {
    QtTest:提供了测试 PyQt5 应用的工具。
    4 N! J) _* S- H3 {2 \+ Y! u- X( H/ w# T
    PyQt5的安装, f# i% x* a# i5 k8 a. X& {
    , C5 k$ P, U0 a! I& y# H4 ]( c
    由于后期要使用fbs进行打包,fbs对Python 3.7以后的版本可能存在兼容问题,所以我选择了Python 3.6.8进行了整个环境的搭建。主要内容为:Python + PyCharm + PyQt5 7 l+ ~7 p2 y8 l5 M

    . w8 n# ~8 o/ L安装PyQt54 C4 L6 r7 v: x/ O
    - z) l7 ~* R- U8 U: e6 a/ \5 B% }" q
    pip install pyqt54 u0 h' h! s1 d1 d- e+ A7 t

    ! l7 W9 Y# c. F+ t; u3 ~, n7 Tpip install pyqt5-tools
    ! W& f7 s6 y/ g" n0 d其中pyqt5-tools为Qt Designer拖拽式的界面设计工具。安装过程中可能会报如下错误:. V1 i/ }! [" A% Y% K( e9 ^
    9 s5 Y0 C! ]% H+ U# q
    qt5-tools 5.15.2.1.2 has requirement click~=7.0, but you'll have click 8.0.1 which is incompatible.. ^* w7 Z1 ^8 T: K$ y8 _5 Z" ~- |
    解决方案:
    ) |: e  k  G& R7 x( C( a8 ~$ a  ?/ Z! q7 P% Z
    pip install click~=7.0
    8 W0 r; [0 {: C3 ^; f! G; j. EQt Designer的配置
    - L' ^0 r; M9 O
    4 W0 I" ~' j7 V1 v8 [2 YQt Designer 是通过拖拽的方式放置控件,并实时查看控件效果进行快速UI设计。- j& `! g" Q9 D$ m' a7 M7 R

    # i5 x& t9 z% ^2 ?: {$ ^
    - \; Q/ w; v- v
    ( g1 }: m# D% v2 c% }' \* r: z0 ~整个画面的构成:
    " |) j" I. Y/ `" u3 e6 o
    $ e$ Z' @. q4 n( U) U4 u, T& H3 @/ d左侧的“Widget Box”就是各种可以自由拖动的组件
    5 o* x! M5 |: _- ?' C! o/ M
    9 w. l; j) j  {+ W) j* l  i中间的“MainWindow – untitled”窗体就是画布1 f  F7 a  Z8 d- s  s6 b8 ]# L
    " T3 e) X0 m) k# N9 y1 [! S
    右上方的”Object Inspector”可以查看当前ui的结构
    0 L! M- Z0 F& e0 s
    , x- I& u  J/ `6 d7 B3 x右侧中部的”Property Editor”可以设置当前选中组件的属性
    / b# Z8 c" [; L0 J3 j0 Q) d2 N3 L1 B- e# M; f( F
    右下方的”Resource Browser”可以添加各种素材,比如图片,背景等等/ e+ E# _3 ~3 M& R9 X- a

    + `2 ?; Z7 U  X+ w最终生成.ui文件(实质上是XML格式的文件),可直接使用,也可以通过pyuic5工具转换成.py文件。
    ' \( @( O. u1 v/ j6 j( O( Q: e" ^. W- e4 [* V
    QtDisigner配置
    # n. z- q2 D! O( n" i3 g( ]2 T8 h5 ?3 k& J" i6 Q
    在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:
    ! X/ Q& _& j% x0 v( P9 V0 a) h/ C0 a! G: ~/ C6 x9 f8 r
    Name: QtDisigner; L# C1 p& o+ Q& o

    ) s+ {+ h$ z& x5 Q1 Z4 M$ s1 QProgram : D:\Program Files\Python36\Lib\site-packages\qt5_applications\Qt\bin\designer.exe # 请根据实际修改
    : a7 d) G! l6 [0 H5 Y7 t8 V! i" W  g- ?8 {9 }: D7 Z2 x4 S2 D7 s
    Working directory: $FileDir$
      |  c8 f! A/ B9 xPyUIC配置
    ! @7 s$ u9 a: y# b$ m  @5 B; U; y* u
    $ ^9 V' Q8 c& ^# ^9 }PyUIC主要是把Qt Designer生成的.ui文件换成.py文件。
    7 l& M  ]$ {0 d8 J  r- c
    . ~9 H% u5 ^( f# ^8 S% S* X在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:! ~+ d: G+ Y) c6 C* Q  e' t
    - o0 w4 J5 C( {
    Name: PyUIC$ P0 O+ \' K. V& P+ Z, i

    , F7 ]- [3 n' U& X8 h& tProgram : D:\Program Files\Python36\python.exe # 当前Python目录,请根据实际修改/ m  z) D8 l) X

    ' n1 `- @9 R; [4 o) D8 TArguments: -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py" g- U& k! V! ~, t) {( S  ^2 W
    % l1 M, M7 @. _; L9 ]6 l& [
    Working directory: $FileDir$
    # i- _8 Y& W- n1 d2 oPyRCC配置: Q7 @- J( L4 H6 N" N
    $ z4 E& y* s+ P9 {" j
    PyRCC主要是把编写的.qrc资源文件换成.py文件。在Pycharm中,依次打开 File – Settings – Tools – External Tools,点击 + Create Tool,配置如下:) o! z& {; C$ s, P
    ; T/ i2 Q) v' L' l
    Name: PyRCC# r# p9 k  ?/ a0 I' Z) s6 `
    - Z  t5 e; l6 v) p6 ]4 y& Z
    Program: D:\Program Files\Python36\pyrcc5.exe # 当前rcc工具目录,请根据实际修改. B2 m  }" E5 x& o" ~6 c9 w
      ^& O$ B; ~# H8 V
    Arguments: $FileName$ -o $FileNameWithoutExtension$_rc.py# t  q3 X: A2 X; L: W; C6 C! f
    6 A( |* B1 h) m) B  ?- B
    Working directory: $FileDir$
    8 ^# J+ v* p9 i7 {# v% K) OPyQt5使用示例
    + U/ T* J' w/ E: A$ I1 j( f/ H  l3 I
    创建一个空白的界面:: a/ s- B' }7 a0 f. O6 L5 a
    % `8 g/ ?0 L! |% X" Q, Q
    import sys+ J$ M: s" y3 V
    2 ]2 c! x% G7 U5 g6 r( m+ x$ f- E5 H
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel7 n+ q& h: [) y0 V

    ; ~& m9 n& u7 `$ ^' K' C. F- Vapp = QApplication(sys.argv)
    * g4 z  }6 Z; ?7 F$ R: [8 o: {( e; ]- @" j5 H8 B; v
    win = QMainWindow()
    7 y' V& j3 m! N! _/ [$ D: f7 s8 J- m: S: u  E1 }
    win.setGeometry(400, 400, 400, 300)' q3 D) L& }3 _  d( a
    " d+ l6 \6 q; ]. s2 y- T0 b6 @
    win.setWindowTitle("Pyqt5 Tutorial")" C' }+ Y6 Z2 j9 w( h
    8 K! v! X5 a8 I9 r& u/ g1 q
    win.show()
    / P  J3 l/ }0 G4 L0 v/ K, F8 o  K( i# ?, j
    sys.exit(app.exec_())) t# K% Y! s: q" _. M, R
    ) p9 F$ w+ |, g) X4 s

    ' A) I; e' ?5 M+ o( L2 s* G5 R3 ]
    其中:
    3 O' i- a6 G7 `5 ~3 M! }* D( q- y  d6 ?  r% Y5 Y2 u$ J
    Qapplication():每个GUI都必须包含一个Qapplication,argv表示获取命令行参数,如果不用获取,则可以使用[]代替。
    ( @5 Y5 X+ j$ n  E, E' J
    0 J) Q1 W' P# A, \  H- C' b! xQMainWindow():类似一个容器(窗口)用来包含按钮、文本、输入框等widgets。arg标识可以获取命令行执行时的参数。8 j2 H6 V. p; z- N
    % _. u" i2 n5 {4 b, b6 V' g- M( g# ~' Z
    SetGeometry是用来定义 QMainWindow() 窗口的尺寸, 语法:setGeometry(x, y, width, height ),其中x,y为屏幕上的坐标点。
    8 x& ~; D( F: E
    $ ?' A$ d) ^& t8 }' Mshow():用来显示窗口
    - g1 L/ t  W0 L% [: w! _
    ; I1 q8 A+ g0 C- `  I6 w# dexit(app.exec_()):设置窗口一直运行指导使用关闭按钮进行关闭
    ' V5 Z' p, Y' b% z, e6 o3 [7 Y
    4 ?/ B/ A+ _2 D1 a2 P; QPyQt5支持的常见Widgets有:: C; `- f# w: f9 e/ X" M
    9 J, v9 u; E2 [
    ; V( \5 G2 G" c. V5 b. n- z

    ( @) L. v4 S- t4 s3 B从上到下,从左到右依次为:Qlabel、QcomboBox、QcheckBox、QradioButton、QpushButton、QtableWidget、QlineEdit、Qslider、QProgressBar2 Q; ]! f5 F3 e
    # C0 P# e" h% I/ H
    对于使用Pyqt5设置文本内容,我们使用Qlabel:
    6 z2 Z0 |: A3 p1 G3 v9 j! v& J* V5 M1 C. z
    import sys
    1 q0 G+ t/ ]( V6 g# ?1 Y* h
    / B/ d4 E) `# w( }. ^from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
    & ^. r3 p& y+ E% d; m, k+ |
    3 G2 l9 B: V: Q  n* L) bapp = QApplication(sys.argv)
    3 {8 i8 a- E" K, y7 s2 E8 \" G2 p; {, l% e- w
    win = QMainWindow()- Y5 n, K% S8 t2 |9 }6 U. b* c
    ( j. w" K( L4 U: C0 n
    win.setGeometry(400, 400, 400, 300)
    2 D% P5 Y: v& i) \$ V8 s
    . \/ z1 }  Z1 H- H8 k3 Vwin.setWindowTitle("Pyqt5 Tutorial")( }+ r+ S, y; O/ h+ }2 D8 X% D2 g

    " i0 G; ^' }. b* e2 w. y, y\# Label Text+ y" z/ k8 F, u( `$ \" u$ R
    0 I9 I$ h$ q& {
    label = QLabel(win)& o- s& a. e! a. j. M

    , B7 S  ]* H0 j' u. X* Tlabel.resize(200, 100)
    & @! i3 A% N8 y! A6 C/ t2 x% B% c# ~6 l1 u  N3 f* |7 R' T
    label.setText("Hi this is Pyqt5")
    / ~* F. p4 t, z/ O% _. C
    + k3 |9 [/ g) P$ ]* [9 glabel.move(100, 100)# `) @( D- ]$ Z( m+ ?  e8 Y4 K

    " g  }, c% Q" `5 i9 |win.show()
    . Q2 w1 V) H! s. y0 L( A# H& K) U" t0 i7 K
    sys.exit(app.exec_())2 J8 E) s- _, N" @  E$ s

    + x: v. q# A- R6 ~2 ?" \. C: F9 Y- p/ X! o, d/ B

    + r" P; @9 ?9 k+ g9 m按钮与事件:4 }. m4 O  F5 v- I4 o+ F! p

    / ]( c9 h8 c8 n! Q/ v( l- P$ \import sys" U( X  D7 {: }- X+ l. `" }6 F' ]
    " c1 X# O) |' e2 N5 N" ?9 l
    from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
      @, l* w! ?  t  {3 F
    % S+ z# m. X0 V# J$ u. r% j6 ^7 udef click():" h, k8 g. W% B* r

    3 N( F7 [# f# G+ Q# u( v2 ^    print("Hy Button is clicked!")
    $ z. n8 m6 D% c, L# P* d0 C# Y9 q5 n: c$ ]
    app = QApplication(sys.argv)% ^& [# O! C' @0 u
    ; o% k- r1 Q$ ~, [
    win = QMainWindow()1 r1 w. W& x9 ?$ n; X( T

    1 R  E1 y2 q/ c9 H. W9 z3 w; owin.setGeometry(400, 400, 400, 300)6 Y3 S! C8 U7 h# ]
    % _: `. V/ r8 ]3 @! T# w
    win.setWindowTitle("Pyqt5 Tutorial")
      l# n% W* c$ O5 j) I
    4 u3 x* e- x' j% I  X\# Button
    * {6 w7 |: y7 b- l$ U9 S
    " A/ F3 }. Y6 n1 ]button = QPushButton(win)/ \4 y8 I1 X, T1 z$ b: H8 x+ B+ K
    ( e* m+ `: F% T. a
    button.resize(200, 100)
      _9 b' N  i. A6 z8 z7 o$ {8 k. _6 y! D( P
    button.setText("Hi! Click Me")
    . b& x' Y. c2 _4 `8 _9 f7 A7 `- V- O  ~1 P, t2 \) _, v- H0 m
    button.move(100, 100)2 f$ J/ w. v" B5 |, }

    * K! C/ `; e( obutton.clicked.connect(click)
    9 P( O4 P* B0 v$ e
    ; g! ^2 h7 x% K% z- Bwin.show()# f; i, a8 u7 F
    # b3 y+ N6 o3 a7 H3 w4 `
    sys.exit(app.exec_())
    ' k! `( F' @; H! J
    $ B* n- S. T& U' C% T) V4 {& j( x) n0 u$ F+ i4 _
    & c% T  m$ c7 U( A& S( T+ E- d
    button.clicked.connect() 在按钮点击后执行特定的事件。: v  Z0 Q  d( i( @9 B1 K* l! A5 _

    1 V" g- O5 R+ v3 L, `- CPyQt5实战
    8 g9 `2 D$ R' a2 j0 F
    . ~6 z7 v4 J4 }! S' S实战项目:简易的天气查询软件, O/ L8 F9 J: c( Z
    & r, M5 H( Q) a$ \8 \; f
    1、使用Qt Designer设计一个界面5 [' h, k: ?' y. q0 P* P* ~: K

    9 _" E4 ]6 f6 S# |" A3 u9 ?! F/ z; h

    0 p! s! d- m% i/ L  }: w用到的控件有Button, GroupBox, Label,ComboBox,TextEdit,同时定义了两个按钮queryBtn及clearBtn,分别用来查询及清空天气数据。我们需要绑定槽函数,方法如下:# K2 {6 k8 G: o3 Y& A2 n

    8 U0 A! ?2 @" E, O# w/ Z, s在Qt Designer右下角选择 信号/槽编辑器,点击+号新增( U8 b- N8 [  W7 ^' t8 `% g5 u

    " [+ ~( @( F) |: |分别选择queryBtn及clearBtn,选择信号 clicked(), 接收者 Dialog 及槽 accept(),(槽函数这里不知道如何定义,后期在代码里再进行修改)
    ( U* ^' j; z/ R5 G% F1 e4 D7 k8 \# Y+ R
    以上完成后保存为Weather.ui文件。
    - E. Y* w+ N* b- {; z# w9 x# j: i" \6 \: ^
    2、转换.ui文件为.py文件
    1 S+ O0 J' C" ?0 n9 [
    5 I8 w! z3 Y' s% h$ ^, @PyQt5支持直接使用.ui文件:7 d# w0 H8 S& R- K6 N) b
    $ |% J. ]! N- K1 W4 p; ]
    import sys
    % p0 }( @- S1 h7 ?9 k5 i! N, H( {7 t; w# K, i# A
    from PyQt5 import QtWidgets, uic# Y/ Y: U: a7 ]+ D' ~

    + o$ R" i# S) q9 N" zapp = QtWidgets.QApplication(sys.argv)
    3 h+ M# H; V  H. R4 C) D
    " x+ @* s# i, j) ~! hwindow = uic.loadUi("mainwindow.ui")
    5 K/ {3 a) f; f. k1 o6 n$ F$ F3 a2 {. a2 L
    window.show()
    2 z- T# _! m+ v6 i0 E
    8 x8 x  c. d! B( ]! k( C' Y, Papp.exec(), r7 J- k; t* ]5 u
    但是为了更好的自定义及修改上面的槽函数,可以使用External Tools – PyUIC,即可生成Weather.py,实际运行命令如下:( @8 I' ?$ w+ W! N* F; R, E

    + P% ^# i! c1 @3 C  K  O9 j( E3 |5 mD:\Program Files\Python36\python.exe -m PyQt5.uic.pyuic Weather.ui -o Weather.py% z+ z" A5 J; v' z' l" D
    其中,我们需要把两个按钮绑定的槽函数:, p% d3 i/ B+ V( f4 o0 g
    # r: E. w: [2 ^. E# v* V* J
    \# self.queryBtn.clicked.connect(Dialog.accept)
    ( p0 _- M& C* I! c4 }
    6 g; x$ d0 o+ f! }& k! `9 S9 ]\# self.clearBtn.clicked.connect(Dialog.accept)4 M5 `% f9 G% P  {5 B
    ! a1 ]' C1 A. o! l" J
    \# 修改为:
    & Z3 a/ m5 M+ k, z4 Y% F! t, y; _- G9 n9 s9 u
    self.queryBtn.clicked.connect(Dialog.queryWeather)
    1 F& G* O; N5 Q5 B; V; A* k) K
    2 D7 Z+ g* t" u$ n8 z% e! t/ pself.clearBtn.clicked.connect(Dialog.clearText). q, y# A1 R4 S- q
    最终的Weather.py内容如下:
    / x. ~! X/ K5 f: u0 b* ~4 o7 u( v+ |% _7 [+ }7 H
    \# -*- coding: utf-8 -*-
    ! w) a2 K; Y5 T! e: \3 ?1 l
    " t) I0 B; W+ o  J" h0 V* Q9 {\# Form implementation generated from reading ui file 'Weather.ui'+ \% h- b; n/ Q8 v) s

    $ |0 U/ t  [% g0 i% [9 I: P\#
    9 F" a+ ?$ ~+ Q0 k2 ^( e4 \/ {( l
    \# Created by: PyQt5 UI code generator 5.15.4
    / O; l( A* b7 D- q$ o7 E5 M* Q" _. }9 K6 m4 ~
    \#
    # T3 U3 V1 R+ T2 A$ n2 W* \1 J& }2 k% ]7 n
    \# WARNING: Any manual changes made to this file will be lost when pyuic5 is
    + L% @: P9 r* N9 R8 y0 `/ H5 s; t
    # P. T$ `* r* w3 ?* c3 R: Q\# run again.  Do not edit this file unless you know what you are doing.
    3 G% G* }  I5 m- H% M& q8 O1 b
    ) s' ~) Q' _, u- }4 f+ [from PyQt5 import QtCore, QtGui, QtWidgets% \" y! g1 ]2 \( a0 O; N
    : F  j3 y& E7 m# c+ n6 {% c2 a& z
    class Ui_Dialog(object):
    ( v2 ?* l- }5 j0 ?
    + l) S& h9 Z$ Q7 j# Z    def setupUi(self, Dialog):' E2 M/ {* h2 x" i
    ' {; s  L& A& s* p; z
            Dialog.setObjectName("Dialog")
    * \! k1 L; N3 z/ y! Y2 g
    7 P9 e1 z: @, i- h8 d1 I2 `        Dialog.resize(600, 600)' D& }7 A; e3 l% v& \- c, h) Y

    0 I! \8 I0 d9 D) [$ C        self.groupBox = QtWidgets.QGroupBox(Dialog)1 W4 Y/ B' y2 T$ n$ j0 a
    + e  d& _- r/ ?) X* A9 G1 `) z8 o
            self.groupBox.setGeometry(QtCore.QRect(30, 20, 551, 511))8 x, t6 b; ^  t! P

    # t* ~( n5 |0 F4 D0 I- s8 R        self.groupBox.setObjectName("groupBox")
    # B/ b- `+ Z9 }; X7 e: f! Q3 y$ w' @; W9 U( H0 W' E, d( c2 y
            self.label_2 = QtWidgets.QLabel(self.groupBox)
    . c* N# u' {; K& n- v# a9 g# k3 E) m1 t# W+ d+ d
            self.label_2.setGeometry(QtCore.QRect(20, 30, 31, 16))& n( j, P8 I" g5 F+ z
    ; t% i* p6 K1 P! O( T$ p
            self.label_2.setObjectName("label_2")
    5 S& h5 |' L+ a& M- \- f2 S2 C( b7 y& n" D
            self.comboBox = QtWidgets.QComboBox(self.groupBox)
    . B% H# c; O0 {8 o2 p1 R) ^: ]8 u% d2 R
            self.comboBox.setGeometry(QtCore.QRect(70, 30, 87, 22)), a0 l+ ~( a0 v

    ' s& `/ j0 R3 q! k" q+ u- r        self.comboBox.setObjectName("comboBox")
    . c0 s& A6 i* I7 C4 p
    & t; x0 c- b! j        self.comboBox.addItem("")
    , V1 b& T5 G4 R' w9 T2 e* D+ m0 k- i( i& ^' |* @" q  U. e; w& s9 M  s
            self.comboBox.addItem("")! G1 E, ^6 i/ k4 G5 {0 [7 Z2 ?

    ! v7 e' N- ^4 `, q" ?        self.comboBox.addItem("")
    - B* U  c9 K; |, H/ E8 H7 S0 k: {  K( {
            self.textEdit = QtWidgets.QTextEdit(self.groupBox)
    $ V% T' h+ y: F+ \: R% a7 X7 U. f1 o; i/ ?  a* t* P7 J& D7 }& Z1 @
            self.textEdit.setGeometry(QtCore.QRect(20, 70, 491, 411))
    ; Z% V4 x' o+ R$ h
    - V0 H+ S+ H+ j) q2 p* j        self.textEdit.setObjectName("textEdit")" v: _$ u. `6 r; }6 T& V7 V" Q: g8 r

    / F5 c1 T) B: b0 T/ O        self.queryBtn = QtWidgets.QPushButton(Dialog)
    8 ?2 b( Y6 F* x8 Y5 t: J( V  i& y/ W" Q) v  s7 W5 \
            self.queryBtn.setGeometry(QtCore.QRect(490, 560, 93, 28))
    5 Z# C& ~9 {4 ]  Z8 x) ~. ~3 @
            self.queryBtn.setObjectName("queryBtn"): b, _, u% g0 H* j
    ' }  k, B, ]3 U* x$ E9 o
            self.clearBtn = QtWidgets.QPushButton(Dialog)
    ! v; p( ?- T$ K5 M! V( J: g
    ! I7 H$ h8 U) L6 p$ S2 Q' b        self.clearBtn.setGeometry(QtCore.QRect(30, 560, 93, 28))
    1 R4 u5 R+ \( _; v! p4 O4 Y' a$ X' }. q: R0 b0 z" k, t' ^+ N( T
            self.clearBtn.setObjectName("clearBtn")' Z9 `; M1 L  \7 N( j
    $ W2 J/ g* ~/ X3 c1 U3 o
            self.retranslateUi(Dialog)
      C. F) }# G3 m! u) e" m5 D; U. r9 z( e  r' t. M
            self.clearBtn.clicked.connect(Dialog.clearText)0 N8 B8 z4 C  }- A! n0 e# ~- g$ z. s

    ) j! i1 Q* J, r, z: Z0 ]        self.queryBtn.clicked.connect(Dialog.queryWeather): z5 I# d! W2 v' H' Q0 m8 X! E
    # a7 {- Z9 y, Q$ d* b  M6 v
            QtCore.QMetaObject.connectSlotsByName(Dialog)1 g2 ]) N- z$ n: _1 {- D4 e0 T$ b

    : I9 r' u1 U, @% f$ f    def retranslateUi(self, Dialog):5 g+ {* ~) P, t9 i# T
    ; m* Y- x" |! E2 |/ t0 S
            _translate = QtCore.QCoreApplication.translate1 h" a9 j6 O1 q  `6 H
    - w5 S% F- w4 ]1 a: Z
            Dialog.setWindowTitle(_translate("Dialog", "Dialog"))  V1 [, s( i1 \2 q4 {
    6 _6 @0 u+ K( L) \0 C8 }
            self.groupBox.setTitle(_translate("Dialog", "城市天气预报"))
    % b2 q3 J+ r' U0 F5 ^% v/ @  w3 K2 @, B( i- J" y* C8 w
            self.label_2.setText(_translate("Dialog", "城市"))- `) s4 p0 U+ C* R
    4 P5 f, ?  N/ o7 F
            self.comboBox.setItemText(0, _translate("Dialog", "北京"))
    ; F* e$ G) p  p5 S) x; T% b# K, e8 m5 x* l1 L. n2 }/ S* v1 {
            self.comboBox.setItemText(1, _translate("Dialog", "苏州"))3 |+ }* H2 q' W, `
    . p0 `, V* t. {7 u- C# q: _
            self.comboBox.setItemText(2, _translate("Dialog", "上海"))
    ( d+ }; Y0 \6 c, P- w
    ( ^! c) ^. b# t! c; n6 b* b$ W5 O        self.queryBtn.setText(_translate("Dialog", "查询"))( r3 e9 N5 [" v

    7 h4 o1 E  W. y1 `5 U7 v0 o        self.clearBtn.setText(_translate("Dialog", "清空"))
    7 Z$ R: n0 D; n- B. M
    ; r  x  E1 K: [8 i- }( m3、调用MainDialog$ K! z! e6 R, u8 x9 R& L% w

    6 P7 S7 L) Z  c% [; ^, b7 K1 B( {在MainDialog中调用界面类Ui_Dialog,然后在其中中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。新增demo.py文件, 在MainDialog类中定义了两个槽函数queryWeather()和clearText(),以便在界面文件Weather.ui中定义的两个按钮(queryBtn 和clearBtn) 触发clicked 信号与这两个槽函数进行绑定。
    + t- h, U1 m+ h, i0 s' j, {3 o- C0 A# ^% b
    完整代码如下:6 f5 t& G% w% y3 _8 Z+ x/ L1 Z

    8 o( Z! j8 `2 u9 [& N1 m$ nimport sys, X( _" }7 v# }5 X

    0 y: F" l; a8 \8 V7 simport Weather
    2 w0 F* j: G$ c" t& g1 B0 C6 n; P# e; ^. A7 ~
    from PyQt5.QtWidgets import QApplication, QDialog
    3 p# A5 b' J, r# L' a6 q$ i% e0 k( b7 d
    import requests
    9 d. U3 ^% I% n6 A( L' a; _0 T8 D+ f
    class MainDialog(QDialog):  w/ y! {# A, F% K8 h$ m! q

    % Y( y) w) h  p% [    def __init__(self, parent=None):
    5 W' f) D+ A( |0 X# d+ `) u0 Q7 w9 [! g1 Q0 ^$ T. @* ^* u8 l: ~- [/ K
            super(QDialog, self).__init__(parent)) P' v% Y  J6 N, a8 _0 d

    $ x! t- \# j) U5 c6 e3 E        self.ui = Weather.Ui_Dialog()$ @, L* L) [" Z1 S6 d' E

    & g  h1 t; J, x        self.ui.setupUi(self)
    , q; @/ N$ z* y  [
    ! M, y0 q- v' ^* h8 s! R    def queryWeather(self):
    , f1 F2 t0 V  n5 s8 T2 }& V: u- F" ?8 H7 ?$ D3 a( P
            cityName = self.ui.comboBox.currentText()
    0 D2 D* I7 k# B/ B# F6 M2 O6 y' s5 r8 o
            cityCode = self.getCode(cityName)$ Z, P- o% ?9 K. I
    ; z- G/ a. L2 o1 }% w; V6 [
            r = requests.get(; a1 C. E! A; e* Z) ?
    # I( ^! h: e9 Y# M4 {2 T# b# G
                "https://restapi.amap.com/v3/weather/weatherInfo?key=f4fd5b287b6d7d51a3c60fee24e42002&city={}".format(  S, a8 l/ [' ?1 u# B1 t# Q" y

    3 x; T. P5 P- n' D% ]                cityCode))
    & K$ @) Y! k' f5 \2 t% {: }. f4 x4 L, L4 b
            if r.status_code == 200:
    ) N0 C% y& `; m! o& P9 v# T4 z  E/ [& ?* }$ h6 Q
                data = r.json()['lives'][0]8 k3 a; f1 Q, |6 J$ [0 f
    ( O4 G0 j5 U/ A0 ~" {
                weatherMsg = '城市:{}\n天气:{}\n温度:{}\n风向:{}\n风力:{}\n湿度:{}\n发布时间:{}\n'.format(
    6 F9 @& [* t8 J7 \& w5 Q; s5 q& D1 t1 P- J; u- p+ a& n
                    data['city'],
    ( R2 v5 j+ x+ L* g- [6 N' G3 E9 h# a" l# K( Q3 ?6 W
                    data['weather'],
    . [5 R. W) }/ B
    % @3 H5 G7 O" Y0 S; ]1 m* Z                data['temperature'],
    ' t+ N3 h) l' N7 U: V' T4 f  j
    " \7 W' ^# f( u9 X. G0 ?: |1 G* Q                data['winddirection'],3 k8 ~; |6 Q. q7 g

    7 C3 j- Z" [: `4 s                data['windpower'],
    2 e$ g0 F1 J; m9 N
    ) M1 a0 N" v0 \4 D, F5 Z                data['humidity'],
    3 w/ Y& C' R. l) C0 P' o8 M
    & T( M3 c6 u- [+ t, u; W5 O& [' K; h                data['reporttime'],
    . f) T) W) J7 C& ~$ J9 D$ e- S- L5 \& O$ q& R. G0 S: g
                )
      g  t7 t2 j, |, {
    ' x+ |- ]2 _1 w1 `        else:/ P& c  C) |8 h# G6 C( k# F
    " M6 [5 a0 ~  f* P6 U4 G, B7 w4 \
                weatherMsg = '天气查询失败,请稍后再试!'
    # D5 ]* ]$ T" k7 \; Z# l2 |2 V$ e3 ^" c
            self.ui.textEdit.setText(weatherMsg)( N, `/ {7 j3 E6 K/ B2 o/ c$ C

    # U- A) j5 K1 C    def getCode(self, cityName):$ ]/ Z) ^& l% X

    ( J9 o$ ^+ \% [( M& W        cityDict = {"北京": "110000",6 J/ r( w2 `# f% l/ \

    4 H8 J3 L$ Z  H                    "苏州": "320500",
    0 @5 {4 D9 [% F2 J! a" J# Z; f" O# _  x& g# ^2 g
                        "上海": "310000"}
    ( W! A* p4 u+ ?8 h5 j+ _5 X2 k; d- I
    ( H7 r$ I7 e; S+ m8 K, u        **return** cityDict.get(cityName, '101010100')0 [4 E/ z$ F  q! G! V1 D4 T1 S
    1 D: \- `, D: N; M2 N% U
        def clearText(self):8 h+ E6 J5 B7 u( v9 O% n9 R6 I5 S

    & z7 U' G' U& Y7 s; |/ ]! n7 s        self.ui.textEdit.clear()
      L. M4 Q. t# J. G: c/ Z  k2 \
    3 c& c: H2 T7 j% H2 xif __name__ == '__main__':' d& e: w& E; `" Q& ?$ \* g2 K
    $ Y2 w4 i3 b1 l# R  J
        myapp = QApplication(sys.argv)1 [9 X' D% x: i( b
    4 g' C1 |; j& P: d" c
        myDlg = MainDialog()
    1 P3 [" X( b7 R. @. l; H+ T( E! f8 E9 |/ U0 ]0 A7 N
        myDlg.show()
    ; N! P8 w* q5 Z% E, Q! ~8 P- j' M% G2 C$ j, v9 \; Z! q- n6 Y' P
        sys.exit(myapp.exec_())0 @/ I1 c8 n4 J8 {5 m; z! e
    & V9 O* n7 ~) f2 r5 {5 @
    运行demo.py并执行查询后的效果:- o# ^$ F% X+ W

    2 i: E; B- y- v* {, [, x) e; C0 Z. W4 ~( @4 U) S( ]" Z
    * r2 k; I3 a- J2 _' I
    4、将代码打包成exe文件7 d  V& F/ y* v3 K7 }$ }

    ' h2 ^; `) V1 D! S将.py文件打包成可执行的exe在Python中称为freezing,常用的工具有:PyInstaller, py2exe, cx_Freeze, bbfreze, py2app等。功能对比:
    ( z& f" r2 N' L8 s# E
    0 q" E+ {! {# E1 o5 _* Y! S: m, ~

      ?' D. D. |- J/ l. R  Ypy2exe:软件更新已经不活跃,因此也就略过。" q8 z: [- e1 |

    , W7 \5 s+ Z4 f% q6 epyinstaller:明确支持win8、win10、理论上支持win7,,支持apple Macos, linux。pyinsaller可以打包成文件夹形式内含exe入口执行文件的形式,也可以是一个单独的exe文件。
    / K; Z. b5 e7 K  ~9 n8 |( k7 ~1 ~
    ' ]# l0 y* b1 o1 A3 }9 tfbs:基于PyInstaller,使用起来更加方便
    ) [" M( E! i* z3 T) T5 A, W
    ; |# Q$ D/ q/ B# \! Z, h8 @& z这里选择了fbs来打包。fbs的安装方法:6 A" i% X  i3 b

    0 L- S; x7 R# y" N8 jpip install fbs
      P" i& r5 c- J8 D; e7 ^5 Y2 @1 f使用方法,在命令行中输入:
    - Z6 B$ F* ~1 c% B7 _0 n  p6 F
    + f7 d# _3 e9 G5 P* \; `9 _2 @: Pfbs startproject
    # ]' W2 |! |9 \  @执行完成后需要输入一些APP的名称等。完成后会生成如下目录:3 |6 j* I, _7 W. A5 k& N

    / I, C, Y7 t2 Y" k  c9 Q/ V" m- `
    , b1 j5 i( H- ?
    将刚才编写的PyQt5的代码(demo.py和Weather.py)拖到src/main/python文件夹下,删除原有的main.py,并将demo.py修改为main.py。然后打开 main.py,在文件头部添加如下代码:+ T! m. X# r! `; a
    ! I* O$ y% |3 e8 R6 ^$ f
    from fbs_runtime.application_context.PyQt5 import ApplicationContext
    1 u0 b9 Y! X2 I: u1 B```. L/ b& T- ]+ K
    完成后执行:9 u- v) c* V% Y% q2 O
    ```, U: C% @. k5 ^4 n
    fbs freeze
    ! t$ {! _2 }' s9 ?( N$ T- u$ k```* }9 B2 y. H& d# i9 m, K' D& g
    即可实现打包。生成的exe可执行文件在\target\MyApp文件下。8 W3 Z" L' k% n0 {
    . O3 E' a% @/ Q, `
    ————————————————
    0 e) X, M) V0 ?% s1 i版权声明:本文为CSDN博主「宋宋讲编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    6 q' _6 ?  R. x8 ]( p  ~- n原文链接:https://blog.csdn.net/qiqi1220/article/details/1262896670 q  T. T  L- b0 O

    & X4 Y" _8 w0 Q0 E3 J. }- U
    + W' B; _, e1 s! V) M) _2 V$ A- e% R/ h( R
    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-4-15 13:05 , Processed in 0.604934 second(s), 51 queries .

    回顶部