最近考虑换工作,面了一家居然是用pyqt5来做桌面应用开发的公司,QT通常都是C++去做的,用python对于一个做python全栈开发的我,这毋庸置疑是一个挑战,毕竟没有接触过QT,面了几次了,还要给我两天时间学习一下pyqt,在这里我就把我这两天的学习成果总结一下。
PyQt5 简介
本教程的目的是带领你入门PyQt5。教程内所有代码都在Linux上测试通过。PyQt4 教程是PyQt4的教程,PyQt4是一个Python(同时支持2和3)版的Qt库。
关于 PyQt5
PyQt5 是Digia的一套Qt5应用框架与python的结合,同时支持2.x和3.x。本教程使用的是3.x。Qt库由Riverbank Computing开发,是最强大的GUI库之一 ,官方网站:www.riverbankcomputing.co.uk/news。
PyQt5是由一系列Python模块组成。超过620个类,6000函数和方法。能在诸如Unix、Windows和Mac OS等主流操作系统上运行。PyQt5有两种证书,GPL和商业证书。
PyQt5类分为很多模块,主要模块有:
- QtCore 包含了核心的非GUI的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime类文件、进程与线程一起使用。
- QtGui 包含了窗口系统、事件处理、2D图像、基本绘画、字体和文字类。
- QtWidgets
- QtMultimedia
- QtBluetooth
- QtNetwork
- QtPositioning
- Enginio
- QtWebSockets
- QtWebKit
- QtWebKitWidgets
- QtXml
- QtSvg
- QtSql
- QtTest
QtWidgets类包含了一系列创建桌面应用的UI元素。 QtMultimedia包含了处理多媒体的内容和调用摄像头API的类。 QtBluetooth模块包含了查找和连接蓝牙的类。 QtNetwork包含了网络编程的类,这些工具能让TCP/IP和UDP开发变得更加方便和可靠。 QtPositioning包含了定位的类,可以使用卫星、WiFi甚至文本。 Engine包含了通过客户端进入和管理Qt Cloud的类。 QtWebSockets包含了WebSocket协议的类。 QtWebKit包含了一个基WebKit2的web浏览器。 QtWebKitWidgets包含了基于QtWidgets的WebKit1的类。 QtXml包含了处理xml的类,提供了SAX和DOM API的工具。 QtSvg提供了显示SVG内容的类,Scalable Vector Graphics (SVG)是一种是一种基于可扩展标记语言(XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。 QtSql提供了处理数据库的工具。 QtTest提供了测试PyQt5应用的工具。
QT环境配置
安装pyqt5、pyqt5-tools
pip install pyqt5
pip install pyqt5-tools
pycharm配置QT开发环境,主要包括Qt Designer,Pyuic, Pyrcc的配置,具体配置参考:https://blog.csdn.net/zrt8019/article/details/102418472
Qt Designer用于配置QT拖拽式界面设计,生成*.ui文件(本质上是一个xml文件);
Pyuic用于将生成的ui文件转换为python文件。
PyQt5入门学习资料:https://maicss.gitbooks.io/pyqt5/content/%E4%BB%8B%E7%BB%8D.html
PyQt5中文学习github地址:https://github.com/maicss/PyQt5-Chinese-tutorial
以下便是我基于pyqt5写的一个比较low的计算器:
主程序代码:
# -*- coding: utf-8 -*-
# @Time : 2019/12/4 9:20
# @Author :
# @Site :
# @File : main.py
# @Software: PyCharm
import sys
from PyQt5 import QtCore
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QMainWindow, QApplication, QMessageBox
from mycalc import Ui_MainWindow
class CalcSignal(QObject):
"""
自定义信号
"""
signal_number = pyqtSignal(int)
signal_method = pyqtSignal(str)
signal_clear = pyqtSignal(int)
signal_result = pyqtSignal()
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.first_number = 0
self.method = ''
self.sec_number = 0
self.is_get_result = 0
self.mysignal = CalcSignal()
# 绑定信号和槽
self.mysignal.signal_number.connect(self.deal_number)
self.mysignal.signal_method.connect(self.deal_method)
self.mysignal.signal_clear.connect(self.deal_clear)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.lineEdit.setText('0')
self.ui.lineEdit.setFocusPolicy(QtCore.Qt.NoFocus)
self._init_button()
def _init_button(self):
"""
初始化所有的button click事件绑定对应的回调函数
:return:
"""
# 设置按钮
self.ui.zero.clicked.connect(self.num_click)
self.ui.one.clicked.connect(self.num_click)
self.ui.two.clicked.connect(self.num_click)
self.ui.three.clicked.connect(self.num_click)
self.ui.four.clicked.connect(self.num_click)
self.ui.five.clicked.connect(self.num_click)
self.ui.six.clicked.connect(self.num_click)
self.ui.seven.clicked.connect(self.num_click)
self.ui.eight.clicked.connect(self.num_click)
self.ui.nine.clicked.connect(self.num_click)
self.ui.point.clicked.connect(self.deal_point)
# 计算方法
self.ui.add.clicked.connect(self.method_click)
self.ui.sub.clicked.connect(self.method_click)
self.ui.multi.clicked.connect(self.method_click)
self.ui.division.clicked.connect(self.method_click)
# 结果
self.ui.result.clicked.connect(self.deal_result)
# 清空按钮
self.ui.clear_all.clicked.connect(self.clear_click)
self.ui.myclear.clicked.connect(self.clear_click)
def num_click(self):
"""触发数字按钮信号"""
number = self.sender()
self.mysignal.signal_number.emit(int(number.text()))
def method_click(self):
"""触发运算符信号"""
method = self.sender().text()
self.mysignal.signal_method.emit(method)
def clear_click(self):
"""触发清空信号"""
clear = self.sender().text()
if clear == 'C':
self.mysignal.signal_clear.emit(1)
else:
self.mysignal.signal_clear.emit(0)
def deal_number(self, val):
"""
点击数字回调函数
:param val:
:return:
"""
temp = self.ui.lineEdit.text()
if temp in ['+', '-', '*', '/']:
self.ui.lineEdit.setText(str(val))
else:
if temp.find('.') == -1:
temp = self.ui.lineEdit.text().lstrip('0')
self.ui.lineEdit.setText(temp + str(val))
def deal_method(self, val):
"""
加减乘除运算处理回调
:param val:
:return:
"""
temp = self.ui.lineEdit.text()
if self.method == '':
if temp not in ['+', '-', '*', '/']:
self.first_number = eval(temp)
else:
if temp not in ['+', '-', '*', '/']:
self.sec_number = eval(self.ui.lineEdit.text())
if self.method == '+':
self.first_number = self.first_number + self.sec_number
elif self.method == '-':
self.first_number = self.first_number - self.sec_number
elif self.method == '*':
self.first_number = self.first_number * self.sec_number
else:
if self.sec_number != 0:
self.first_number = self.first_number / self.sec_number
self.sec_number = 0
self.method = val
self.ui.lineEdit.setText(val)
def deal_clear(self, val):
"""
两种清空回调函数
:param val:
:return:
"""
if val:
self.first_number = 0
self.method = ''
self.sec_number = 0
self.ui.lineEdit.setText('0')
else:
if self.sec_number == 0 and self.method == '' and self.first_number != 0:
self.first_number = 0
self.ui.lineEdit.setText('0')
elif self.sec_number == 0 and self.method != '':
self.ui.lineEdit.setText('0')
elif self.sec_number != 0:
self.sec_number = 0
if self.method != '':
self.ui.lineEdit.setText(self.method)
else:
self.ui.lineEdit.setText('0')
else:
self.ui.lineEdit.setText('0')
def deal_result(self):
"""
处理等号事件
:return:
"""
temp = self.ui.lineEdit.text()
if temp in ['+', '-', '*', '/']:
self.method = ''
self.sec_number = 0
self.ui.lineEdit.setText(str(self.first_number))
self.first_number = 0
return
self.sec_number = eval(temp)
if self.method == '':
result = eval(temp)
elif self.method == '+':
result = self.first_number + self.sec_number
elif self.method == '-':
result = self.first_number - self.sec_number
elif self.method == '*':
result = self.first_number * self.sec_number
else:
if self.sec_number != 0:
result = self.first_number / self.sec_number
else:
result = 0
print('除数不能为0')
self.alert()
self.method = ''
self.sec_number = 0
self.first_number = result
self.ui.lineEdit.setText(str(result))
def alert(self):
"""
除数为0时重置所有,并弹框
:return:
"""
msgBox = QMessageBox()
msgBox.setIcon(QMessageBox.Warning)
msgBox.setWindowTitle(u'提示')
msgBox.setText(u"除数不能为0")
msgBox.setWindowIcon(QIcon('./favicon.ico'))
# 隐藏ok按钮
msgBox.addButton(QMessageBox.Ok)
msgBox.button(QMessageBox.Ok).hide()
# 模态对话框
msgBox.exec_()
def deal_point(self):
"""
小数点事件
:return:
"""
temp = self.ui.lineEdit.text()
if temp in ['+', '-', '*', '/']:
self.ui.lineEdit.setText('0.')
else:
tempindex = temp.find('.')
if tempindex == -1:
self.ui.lineEdit.setText(temp + '.')
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.setWindowIcon(QIcon('./favicon.ico'))
main_window.setWindowTitle('我的计算器')
main_window.setFixedSize(560, 450)
main_window.show()
app.exec()
界面文件
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'mycalc.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(639, 600)
font = QtGui.QFont()
font.setPointSize(10)
MainWindow.setFont(font)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(9, 62, 541, 71))
font = QtGui.QFont()
font.setPointSize(24)
self.lineEdit.setFont(font)
self.lineEdit.setObjectName("lineEdit")
self.seven = QtWidgets.QPushButton(self.centralwidget)
self.seven.setGeometry(QtCore.QRect(9, 197, 121, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.seven.setFont(font)
self.seven.setObjectName("seven")
self.four = QtWidgets.QPushButton(self.centralwidget)
self.four.setGeometry(QtCore.QRect(10, 260, 121, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.four.setFont(font)
self.four.setObjectName("four")
self.eight = QtWidgets.QPushButton(self.centralwidget)
self.eight.setGeometry(QtCore.QRect(150, 196, 131, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.eight.setFont(font)
self.eight.setObjectName("eight")
self.five = QtWidgets.QPushButton(self.centralwidget)
self.five.setGeometry(QtCore.QRect(150, 264, 131, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.five.setFont(font)
self.five.setObjectName("five")
self.nine = QtWidgets.QPushButton(self.centralwidget)
self.nine.setGeometry(QtCore.QRect(310, 194, 111, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.nine.setFont(font)
self.nine.setObjectName("nine")
self.six = QtWidgets.QPushButton(self.centralwidget)
self.six.setGeometry(QtCore.QRect(310, 260, 111, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.six.setFont(font)
self.six.setObjectName("six")
self.point = QtWidgets.QPushButton(self.centralwidget)
self.point.setGeometry(QtCore.QRect(10, 384, 121, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.point.setFont(font)
self.point.setObjectName("point")
self.zero = QtWidgets.QPushButton(self.centralwidget)
self.zero.setGeometry(QtCore.QRect(150, 384, 131, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.zero.setFont(font)
self.zero.setObjectName("zero")
self.result = QtWidgets.QPushButton(self.centralwidget)
self.result.setGeometry(QtCore.QRect(310, 386, 111, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.result.setFont(font)
self.result.setObjectName("result")
self.multi = QtWidgets.QPushButton(self.centralwidget)
self.multi.setGeometry(QtCore.QRect(440, 194, 101, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.multi.setFont(font)
self.multi.setObjectName("multi")
self.division = QtWidgets.QPushButton(self.centralwidget)
self.division.setGeometry(QtCore.QRect(440, 260, 101, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.division.setFont(font)
self.division.setObjectName("division")
self.add = QtWidgets.QPushButton(self.centralwidget)
self.add.setGeometry(QtCore.QRect(440, 384, 101, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.add.setFont(font)
self.add.setObjectName("add")
self.clear_all = QtWidgets.QPushButton(self.centralwidget)
self.clear_all.setGeometry(QtCore.QRect(307, 141, 241, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.clear_all.setFont(font)
self.clear_all.setObjectName("clear_all")
self.one = QtWidgets.QPushButton(self.centralwidget)
self.one.setGeometry(QtCore.QRect(10, 324, 121, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.one.setFont(font)
self.one.setObjectName("one")
self.two = QtWidgets.QPushButton(self.centralwidget)
self.two.setGeometry(QtCore.QRect(150, 324, 131, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.two.setFont(font)
self.two.setObjectName("two")
self.sub = QtWidgets.QPushButton(self.centralwidget)
self.sub.setGeometry(QtCore.QRect(440, 324, 101, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.sub.setFont(font)
self.sub.setObjectName("sub")
self.three = QtWidgets.QPushButton(self.centralwidget)
self.three.setGeometry(QtCore.QRect(310, 324, 111, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.three.setFont(font)
self.three.setObjectName("three")
self.myclear = QtWidgets.QPushButton(self.centralwidget)
self.myclear.setGeometry(QtCore.QRect(9, 141, 271, 41))
font = QtGui.QFont()
font.setPointSize(16)
self.myclear.setFont(font)
self.myclear.setObjectName("myclear")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 639, 23))
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.myclear.clicked.connect(self.lineEdit.clear)
self.clear_all.clicked.connect(self.lineEdit.clear)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.seven.setText(_translate("MainWindow", "7"))
self.four.setText(_translate("MainWindow", "4"))
self.eight.setText(_translate("MainWindow", "8"))
self.five.setText(_translate("MainWindow", "5"))
self.nine.setText(_translate("MainWindow", "9"))
self.six.setText(_translate("MainWindow", "6"))
self.point.setText(_translate("MainWindow", "."))
self.zero.setText(_translate("MainWindow", "0"))
self.result.setText(_translate("MainWindow", "="))
self.multi.setText(_translate("MainWindow", "*"))
self.division.setText(_translate("MainWindow", "/"))
self.add.setText(_translate("MainWindow", "+"))
self.clear_all.setText(_translate("MainWindow", "C"))
self.one.setText(_translate("MainWindow", "1"))
self.two.setText(_translate("MainWindow", "2"))
self.sub.setText(_translate("MainWindow", "-"))
self.three.setText(_translate("MainWindow", "3"))
self.myclear.setText(_translate("MainWindow", "CE"))