# s( B h$ ]3 G" e3 c) L$ C% LPyQt5支持直接使用.ui文件:! r! g6 w' f6 n6 B- ?2 J" w+ M
, G( Y! j I$ F9 Y, K0 ]; Y( V' himport sys* g. j% v! `" D% X5 B) y7 v. W7 S
3 r( R6 Q% V4 I* m
from PyQt5 import QtWidgets, uic " }; ?4 Z2 u, b 3 H( J6 Q T# [+ m5 v. h4 Wapp = QtWidgets.QApplication(sys.argv)6 p! c! C; c% q, E+ h- g5 h
' u7 [# w, o) J
window = uic.loadUi("mainwindow.ui") 0 a, K0 z% A' h: h$ r1 V0 j . Y$ [5 t$ s9 }2 |3 [; Lwindow.show() ) D3 W% `! [& S 9 Y3 b H4 s8 H) W) H5 H" qapp.exec() $ _$ K( Q# ~, o, w8 f7 q9 Y# ~# @ E但是为了更好的自定义及修改上面的槽函数,可以使用External Tools – PyUIC,即可生成Weather.py,实际运行命令如下: * j* }0 M/ C) u; i: A* D * {$ l: X% Z( x ?D:\Program Files\Python36\python.exe -m PyQt5.uic.pyuic Weather.ui -o Weather.py! P- ^! n, c; `) i+ A4 K; w. t8 f0 ^
其中,我们需要把两个按钮绑定的槽函数: , d8 S/ A$ X9 o" p# W) ^5 |3 T6 q. ?3 {# [
\# self.queryBtn.clicked.connect(Dialog.accept) * B" _$ x5 K# G+ |9 W3 T5 T/ F" B" |& R. x4 A
\# self.clearBtn.clicked.connect(Dialog.accept) " K, z5 U; F% e8 e& V9 B # @8 x: _; J# X\# 修改为: ; K9 ?$ \2 Z- }$ i. N7 e; x ; V; |7 n! N* Q% U' fself.queryBtn.clicked.connect(Dialog.queryWeather) & y8 x+ ~% g) l# [2 Q6 f0 @* @0 e! i- R$ E& {9 l! I8 q
self.clearBtn.clicked.connect(Dialog.clearText)) m! d D: ~$ v! B9 \
最终的Weather.py内容如下: 7 ~# w0 d3 `& @) u& U* U% h! C. b5 t. v6 x5 S& Z9 z) _
\# -*- coding: utf-8 -*- 6 p( _" R: R' U; [9 [& V! t# N/ ]$ Z
\# Form implementation generated from reading ui file 'Weather.ui', g) K' }, Q1 [) Z
7 o4 f" q. S* d' J0 R: r: k i7 z
\# ) F, G0 X5 V% v& r9 u- {( R2 f8 u1 K5 \( E
\# Created by: PyQt5 UI code generator 5.15.4. j) e; U2 t! R1 g
0 P' K0 C& Q# ~2 G. |
\#, ?7 O/ E( i0 E, `
1 i. r" I# U t2 S4 Z; G0 B3 k* Q' B\# WARNING: Any manual changes made to this file will be lost when pyuic5 is6 z% W( Z7 S5 R$ e/ j- O
; {/ j1 R8 s6 S" a\# run again. Do not edit this file unless you know what you are doing. 1 _5 y' h, D0 T8 T A! ~- L/ Z( p* k* g
from PyQt5 import QtCore, QtGui, QtWidgets6 Q+ Y, \/ k3 i! O6 ]" j1 y
- w2 }$ w7 t2 }( M/ j
class Ui_Dialog(object): 2 C; i; g6 V) c( W+ k. L \5 S ' ?0 Q" z/ y U6 [8 Y def setupUi(self, Dialog): 2 ?) h" D% W; I2 V 7 `5 ^5 `1 d8 E Dialog.setObjectName("Dialog")/ h: T1 Q' E2 b: i
# _! U G" p. P3 e: F4 v v& i
Dialog.resize(600, 600) 4 i2 m6 ^; [. V8 y0 X9 u, {! _0 ^3 N1 }8 \
self.groupBox = QtWidgets.QGroupBox(Dialog)+ Z( X# Y/ ~: e
$ d. e( v- K3 P( j; ]
self.groupBox.setGeometry(QtCore.QRect(30, 20, 551, 511))3 f' ^; }9 Q ~$ Z
. s; b* g9 e; q! O# i
self.groupBox.setObjectName("groupBox") , o6 @% c1 F7 V) c' `4 N @& l0 o2 |4 | self.label_2 = QtWidgets.QLabel(self.groupBox)) D3 ?" I* C* u. j: e6 S
F3 H+ `, H1 g. M& u- D self.label_2.setGeometry(QtCore.QRect(20, 30, 31, 16)): W Q; A z! A, _
. Q% b) D5 ?3 r/ V" t9 [6 j; F$ E0 K
self.label_2.setObjectName("label_2") * ^) p8 H4 N7 i1 k* _$ \/ J , x Y" ]: X( a( M R( q3 o$ A1 M self.comboBox = QtWidgets.QComboBox(self.groupBox) ' I+ j) h2 o( O8 y* K, G4 V, j. q: q+ I0 i6 l7 Y
self.comboBox.setGeometry(QtCore.QRect(70, 30, 87, 22)) 6 | r* y/ t- Y w) M' g% T& k' M+ C! @6 K. [( E
self.comboBox.setObjectName("comboBox")7 `2 p3 G/ |7 v6 q
% |) n: D/ z0 t# n G5 o
self.comboBox.addItem("")5 @) D* N, Q- A3 j: |" Z$ A
: M9 M6 x4 A3 T
self.comboBox.addItem("") ! f, [% o. S( g$ f/ X8 {& V % T" j2 `; t# R: b8 F self.comboBox.addItem(""), { ]5 |/ [+ l- x* A9 G( i
9 z0 o3 R r& R' m) Y
self.textEdit = QtWidgets.QTextEdit(self.groupBox) ; }4 a! Q0 n3 L$ L& m% Z& a 7 b7 f' W2 V. ^' G) i, r; G self.textEdit.setGeometry(QtCore.QRect(20, 70, 491, 411)) w4 U: W2 O2 P& Q2 Q0 u
+ v5 f( f4 _3 j3 K J8 G
self.textEdit.setObjectName("textEdit") . N! _& H$ S" n( e! V0 ]/ O% p' S6 k, @ M
self.queryBtn = QtWidgets.QPushButton(Dialog)( V4 m- W/ m+ Z, `5 C$ d* `) a7 z& E
* @6 @" @5 l3 T9 y* q self.queryBtn.setGeometry(QtCore.QRect(490, 560, 93, 28))+ L' H8 ^5 g2 t
) ] F) w% K% k2 _% _
self.queryBtn.setObjectName("queryBtn") + Y. W% O9 [7 L7 K8 ~ 2 @. Z2 a4 C+ M( F; E6 d$ { self.clearBtn = QtWidgets.QPushButton(Dialog) . B6 l% h5 _/ r- L8 T# A, z , {% v6 h# C. s/ S- L3 O; ~4 S' r# \2 i; T self.clearBtn.setGeometry(QtCore.QRect(30, 560, 93, 28)) 7 A( d8 ^" p) h* G! K $ O- O6 n3 _1 ^$ g% O: {( u self.clearBtn.setObjectName("clearBtn") * y- Z) f2 s$ b& h ) S! I5 ^% y' n& F self.retranslateUi(Dialog). ~; V/ u: p) N
) I0 M6 t5 g z/ h' c) V v self.clearBtn.clicked.connect(Dialog.clearText)" L1 u) v# g+ x/ b9 Z
% b% [+ T8 v1 Z
self.queryBtn.clicked.connect(Dialog.queryWeather)" A7 `: K: n8 E
0 H# @/ T) ~- y. ^; b
QtCore.QMetaObject.connectSlotsByName(Dialog) 7 F" |+ P, L( s3 h+ _% z* M- A" {$ ]; y
def retranslateUi(self, Dialog): 2 F0 m5 |) {2 J% [* J4 T ( {: q4 k8 f0 V( q, p6 W0 a0 T) g _translate = QtCore.QCoreApplication.translate8 c' N& P! ]# O# L
; N$ d; d* M5 W `2 S Dialog.setWindowTitle(_translate("Dialog", "Dialog")) + _4 c/ G' @2 j3 a+ Z/ _# z( N: E2 O" B
self.groupBox.setTitle(_translate("Dialog", "城市天气预报")) ; h- x- Z5 J1 E4 H b. z+ \6 z c9 C % b" x+ h- q4 v1 s self.label_2.setText(_translate("Dialog", "城市")) 3 a9 j& ^/ f' `# ?$ Y( g1 ], Z: c4 l9 R - f( O3 {' @: @ self.comboBox.setItemText(0, _translate("Dialog", "北京")) 8 K* o0 W U/ o ' u. V) w$ |+ U, y self.comboBox.setItemText(1, _translate("Dialog", "苏州")) 7 N( z$ y4 L9 E5 P% `8 H9 T) H$ A1 @( D( u( c5 |6 ~
self.comboBox.setItemText(2, _translate("Dialog", "上海")) 0 u# l* J/ P d3 Q' P& a7 \) I9 U. D
self.queryBtn.setText(_translate("Dialog", "查询"))- z3 O) W4 Q8 c5 t% H d& e4 m
* ]3 Q# `% }, L3 L0 D
self.clearBtn.setText(_translate("Dialog", "清空")) , J* Q3 I; l# v3 \6 s7 J4 e8 W# v6 r% D9 U" ?/ w. m" A
3、调用MainDialog . K0 a7 W9 b* a* Q/ R6 d! h6 p3 r' V ! v- [# h! A+ l( G/ ~) J在MainDialog中调用界面类Ui_Dialog,然后在其中中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。新增demo.py文件, 在MainDialog类中定义了两个槽函数queryWeather()和clearText(),以便在界面文件Weather.ui中定义的两个按钮(queryBtn 和clearBtn) 触发clicked 信号与这两个槽函数进行绑定。 * k5 M3 |5 `$ B2 j1 _/ ~/ Q1 }4 p4 H. o7 r$ d
完整代码如下:) h; g1 a4 l9 z% f6 t
2 I1 p# d+ @2 o, e; B' O! Jimport sys! [" q- R! H! d+ F k2 u+ w6 W
7 a, I/ m: R9 Jimport Weather! E1 K/ {! @2 Z2 H5 l3 b. }
8 z9 a$ Z$ d Y8 ]$ }4 F
from PyQt5.QtWidgets import QApplication, QDialog {, ^+ g$ `/ F5 j b% [' n
1 u/ L6 L- D1 ^: U% b% i( `
import requests " [2 E. B; C0 H+ N; _" j. r 6 F4 F% v/ @ Q# f/ J/ A3 Xclass MainDialog(QDialog):4 E5 X% {1 y# @/ r i7 K* o
* f W% p6 n1 S" K$ R& \. v( u
def __init__(self, parent=None): . Z4 Z* j: _. j+ i 1 {* O% D. Z( O# F0 M3 V super(QDialog, self).__init__(parent) 9 L% `! Z& w/ Q: G3 S $ Z) p3 ]% y+ w& g self.ui = Weather.Ui_Dialog() 3 f( E/ f7 _; d / v1 [4 o" Y$ e# }+ z J self.ui.setupUi(self) 6 ^' H# z% w) } - z, g3 x( d$ w, c def queryWeather(self): 4 x! \6 P. K1 S" X3 p- k( N0 O# Z( `, H8 T; s
cityName = self.ui.comboBox.currentText() . [% Z4 N. O% m" P : G Z5 p/ F. [+ } cityCode = self.getCode(cityName) % K E1 p/ A: Y5 \8 D3 D6 R% o ' i* A) K# A7 p8 ?2 c& m r = requests.get(2 I( v# \9 m- b$ S5 c8 L. _: I
$ ^* o* m' h" ]
"https://restapi.amap.com/v3/weather/weatherInfo?key=f4fd5b287b6d7d51a3c60fee24e42002&city={}".format(- F* f* @; M; i) h, n7 S# H
( ~, m0 t! B6 G- G0 {5 ~
cityCode))3 F! i- }# g0 F' t( Q
8 Z' _+ p6 W2 S& R3 G% }
if r.status_code == 200:6 `+ ]3 L# A+ J9 x- ?' }
$ |! L/ i7 L+ [6 W8 L4 s4 v
data = r.json()['lives'][0] % z7 Z6 d1 Y! w B7 n0 G2 S" a1 q( f0 Y* A( O
weatherMsg = '城市:{}\n天气:{}\n温度:{}\n风向:{}\n风力:{}\n湿度:{}\n发布时间:{}\n'.format(2 i. h( e6 k; ~) H1 W- Z) _
2 Y. H7 H# {2 h- k/ r, r
data['city'], - t, q4 @1 h9 u: _: [: K% y3 x. a' X2 M9 d: a% `: x+ \
data['weather'], @* n/ n& G4 f1 @) m g+ W2 U6 ?" H, M" D# B4 i. T. a! @
data['temperature'],3 O* Z5 C! B: W! [- y" I6 j6 Z
5 h$ p/ x; m& g data['winddirection'], 1 w4 ?( w- `. Q+ e' h ; e0 l$ @8 E+ C) F data['windpower'], " C' X% p* g. o: b; I 6 Q1 I3 y2 ^2 s& [2 t8 k data['humidity'], 0 ^# V5 b# _5 H! W& _7 L) R3 f9 W' n2 ^
data['reporttime'],1 I( U5 w' `) J3 T- r
. M$ O0 L. E2 l; d8 r
)1 m) _3 X, }* p
; K/ J5 }! ^; r
else:" W6 v s* }7 l
# A1 h" |7 Z8 P- G9 T* C3 W weatherMsg = '天气查询失败,请稍后再试!'+ N( L1 a% t: w4 _
& v/ d( p4 o$ Q& P4 y- i8 K
self.ui.textEdit.setText(weatherMsg)+ f8 ^: v- [3 v5 `* t$ B' g
+ `$ a& v A# W! B \ def getCode(self, cityName): 2 a$ ]- i H' J9 S. z5 ?8 D1 A9 @ 6 a, U8 F# V6 q8 V! g' c cityDict = {"北京": "110000", $ l- q7 F9 y% M5 W. |1 M3 E" I% H3 S; |9 R. r
"苏州": "320500", # j( {' W' H& V" c* o1 L: } ! o6 x& h' Z6 t; E" V "上海": "310000"}) A; r3 W- k( m
6 J) C* z J( _9 U1 a) g. C2 k( y **return** cityDict.get(cityName, '101010100')0 I R* V7 Z2 D
4 \5 j9 S* t: l/ J) N' u
def clearText(self): g0 ?) M8 X7 m8 N# Q3 _" o1 Z4 t
B0 ~" I* d# a8 Y self.ui.textEdit.clear() I: _8 j" U3 o . h# d6 U4 Z: Z b" p% jif __name__ == '__main__':. p [. s) ~- t" _7 _& w
6 C) w# T0 _, q myapp = QApplication(sys.argv). X' P' z; B& D, L
" I$ G5 L ^! `! @" V- |; e myDlg = MainDialog() ! Y( n: Q: Y2 I3 t1 @% \( ` t ! a6 O0 ?& B3 l* K& w7 q2 P' E# X myDlg.show() 9 E5 _" O! d! n* ?4 p& q" n - n2 N9 B# [" U) G5 j sys.exit(myapp.exec_()) - I" i6 g5 Z8 m" H( y2 V1 W4 a s 2 R& T9 ~7 E0 |" g% i运行demo.py并执行查询后的效果:9 ~. ~% Q* P) w8 }9 T
6 B1 t: {1 J3 q4 O" `7 ~
; H9 p! N' Y2 Z1 N0 E
: l. K& E/ g5 C. w4、将代码打包成exe文件 . i) x8 H0 X/ [5 V. j, a g$ q e9 D' H a: \; \将.py文件打包成可执行的exe在Python中称为freezing,常用的工具有:PyInstaller, py2exe, cx_Freeze, bbfreze, py2app等。功能对比:- h6 v, ]* A+ N
5 o' l* H1 @# I* h5 X A E Q4 d2 \7 h2 O! E0 D; p7 g1 ?: b3 A; S& ~: k/ p! t
py2exe:软件更新已经不活跃,因此也就略过。 ( K1 S! r- r: z8 B+ G! U3 Z " Z, n# _* U8 Ipyinstaller:明确支持win8、win10、理论上支持win7,,支持apple Macos, linux。pyinsaller可以打包成文件夹形式内含exe入口执行文件的形式,也可以是一个单独的exe文件。" i/ H+ q1 V' f/ r# V; W! a
+ V& n- j! j+ k4 i, T2 o+ b5 s
fbs:基于PyInstaller,使用起来更加方便 " u1 `9 n. }6 k; `3 _$ j$ j1 y8 |3 ?$ D4 U( Y
这里选择了fbs来打包。fbs的安装方法: - Q8 j- d3 `6 A 9 ]4 A0 a8 t) h5 |+ E+ F, p/ ^pip install fbs 1 ?2 ?$ _2 u. U. c使用方法,在命令行中输入:, ^- N8 [/ W2 v8 ?" J' \7 f
7 x; c1 |8 h: ]8 K# s/ Sfbs startproject " e' |# _$ W0 H. D4 P1 V执行完成后需要输入一些APP的名称等。完成后会生成如下目录:. E! P# M' R) b9 L
1 r/ _0 l& R5 R: h
+ C+ I' S0 w9 G: {) g6 O
1 F0 z- _" A5 o8 s4 x0 q7 ]6 w将刚才编写的PyQt5的代码(demo.py和Weather.py)拖到src/main/python文件夹下,删除原有的main.py,并将demo.py修改为main.py。然后打开 main.py,在文件头部添加如下代码:# c4 l3 k( f7 Y# X- O9 h+ f
: v+ k) [4 f; P- `1 z
from fbs_runtime.application_context.PyQt5 import ApplicationContext# p M K7 S- j0 z7 d- V6 L
``` 5 B! V; A R) Y完成后执行:& {$ U% a. N; n/ q* b! [" u$ K( O
``` ) O, P* }9 l6 O3 b6 t* wfbs freeze # `7 ~$ ~! I9 N' b( Y``` : ?3 F" w& f/ X6 f2 B2 \即可实现打包。生成的exe可执行文件在\target\MyApp文件下。! ?' E8 `" \/ f% C' c6 P
, v1 c6 R7 t. |" s B
———————————————— 0 [" e0 f4 ], F3 s. e4 q版权声明:本文为CSDN博主「宋宋讲编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 + p/ B, c, P% X( Z$ @- K1 X2 r原文链接:https://blog.csdn.net/qiqi1220/article/details/126289667 $ C: y @3 {+ D; r" Z + O1 m+ g8 q7 ]% c0 K9 h' M. k 6 ^& `( u f: z) `+ W1 r: b. G8 _, {9 V1 W& \" q* k0 \! p