后面的配置均对齐下面的配置:
项目目录: D:\python_project_2\Python-Easy-Chess-GUI
项目使用虚拟环境目录: D:\python_project_2\Python-Easy-Chess-GUI.venv
1 安装 pyqt5 and pyqt-tools
.venv 虚拟环境可以通过 pycharm 或者 命令行来创建:
python -m venv .venv
.venv\Scripts\activate.bat
使用虚拟环境的 pip 来安装python 依赖包
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyqt5
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyqt5-tools
2 pycharm 环境配置
# 2.1 Qt Designer
Qt Designer 是通过拖拽的方式放置控件,并实时查看控件效果进行快速UI设计。
最终生成.ui文件(实质上是XML格式的文件),可以通过pyuic5工具转换成.py文件。
在Pycharm中,依次打开 File - Settings - Tools - External Tools,点击 + Create Tool,配置如下:
我用的是python 虚拟环境
2.2 PyUIC
PyUIC主要是把Qt Designer生成的.ui文件换成.py文件。
在Pycharm中,依次打开 File - Settings - Tools - External Tools,点击 + Create Tool,配置如下:
2.3 PyRCC
PyRCC主要是把编写的.qrc资源文件换成.py文件。
在Pycharm中,依次打开 File - Settings - Tools - External Tools,点击 + Create Tool,配置如下:
3 简单的例子
需求: 做一个IP 归属地查询的例子, 用下面的API 接口:
https://webapi-pc.meitu.com/common/ip_location?ip=121.8.215.108
浏览器请求上面的URL, 返回的是:
{
"reqid": "a442fc747d71c8e5aa22c4dffa775b1a",
"code": 0,
"data": {
"121.8.215.108": {
"area_code": "86",
"city": "广州市",
"city_id": 160063402,
"continent": "亚洲",
"continent_code": "AP",
"country_id": 100000,
"isp": "电信",
"latitude": 23.3283,
"longitude": 113.75837,
"nation": "中国",
"nation_code": "CN",
"province": "广东",
"province_id": 440000,
"subdivision_1_iso_code": "*",
"subdivision_1_name": "广东",
"subdivision_2_iso_code": "*",
"subdivision_2_name": "广州市",
"time_zone": "UTC+8"
}
}
}
我们的界面需要有一个文本框用TextEdit来输入IP地址, 一个查询Button按钮用来触发查询命令, 还有一个TextBrower用来展示API输出的信息。
3.1 界面设计
启动QT designer
简单设计一下如下的界面:
在右下角的信号/槽函数, 增加一行, 发送者是pushButton, 信号是单击 clicked()
接受者和槽函数随便选择的, 后续换成我们自己定义的。
在 PyQt5 中,信号和槽是实现对象之间通信的一种机制。这是一种事件驱动的编程概念,可以帮助我们创建交互式的 GUI 应用程序。
信号(Signal):当某个特定事件发生时,一个 PyQt5 控件(widget)可以发出一个信号。例如,当用户点击一个按钮时,按钮可以发出一个 “clicked” 信号。
槽(Slot):槽是响应信号的函数。当关联的信号被发出时,槽函数就会被调用。例如,你可以创建一个槽函数,当按钮被点击(“clicked” 信号被发出)时,这个槽函数就会被执行。
最后将设计文件保存在 ip.ui
3.2 转换.ui文件为.py文件
将ip.ui 文件转换为 py 文件。
选择上线的工具后, 会自动执行下面的命令:
D:\python_project_2\Python-Easy-Chess-GUI\.venv\Scripts\python.exe -m PyQt5.uic.pyuic ip.ui -o ip.py
下面是本例子涉及的两个文件:
ui.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ip.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(50, 60, 371, 41))
self.textEdit.setObjectName("textEdit")
self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
self.textBrowser.setGeometry(QtCore.QRect(50, 120, 571, 411))
self.textBrowser.setObjectName("textBrowser")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(460, 70, 93, 28))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.pushButton.clicked.connect(MainWindow.query_IP) # type: ignore
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "查询"))
上面代码中, 特别的我们改动了这一行:
self.pushButton.clicked.connect(MainWindow.query_IP) # type: ignore
要改成我们自己的逻辑函数
主脚本文件 demo.py
import sys
import traceback
import ip
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow
import requests
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.ui = ip.Ui_MainWindow()
self.ui.setupUi(self)
def query_IP(self):
try:
ip_address = self.ui.textEdit.toPlainText()
print(f'ip_address: {ip_address}')
r = requests.get("https://webapi-pc.meitu.com/common/ip_location?ip={}".format(ip_address))
print(r.json())
if r.json().get('code') == 0:
result = r.json().get('data').get(ip_address)
else:
result = '查询失败,请稍后再试!'
self.ui.textBrowser.setText(str(result))
except Exception as e:
traceback.print_exc()
if __name__ == '__main__':
myapp = QApplication(sys.argv)
myDlg = MainWindow()
myDlg.show()
sys.exit(myapp.exec_())
运行截图:
简单的例子, 界面交互少, 对于复杂的界面, 要好好规划, 特别是各种交互。