写在前面
这篇文章主要是记录自己在摸索将进度条嵌于主界面时的一些问题。(已经解决,但才疏学浅,仍不是很清楚,不知道如何解释,如果您知道,或者您觉得哪里有错,欢迎指出。水平有限,轻喷。谢谢)
关于将进度条嵌于状态栏,详见此文:pyqt5 嵌于主界面状态栏的进度条
问题描述
在参考他人文章时,明明代码一样,运行却没有效果(进度条不动)
仔细看了一下类的定义和函数入口,才发现我的代码和别人的有点不一样,现整理出来,还请认真对比。
需要说明的是:2份代码顶部引入的包也有可能不一样。
无法运行的代码(进度条不动)
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QProgressBar, QLabel
from PyQt5.QtCore import QBasicTimer
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
#这里是object不是QMainWindow
class Ui_MainWindow(object):
def __init__(self):
#这里可以定义一些为当前类所用的全局变量
self.filepath = ''
#注意这里要传一个参数MainWindow,所以主函数入口获取了一个MainWindow的实例
def setupUi(self, MainWindow):
# 设置窗口的对象名称
MainWindow.setObjectName("MainWindow")
# 设置窗口大小
MainWindow.resize(800, 600)
########多了这一块,
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# 定义按钮(//传的参数不同
self.startButton = QtWidgets.QPushButton(self.centralwidget)
# 设置按钮对象名称(不是按钮显示内容)
self.startButton.setObjectName("pred")
# 设置按钮位置
self.startButton.setGeometry(QtCore.QRect(10, 300, 93, 28))
# 设置按钮显示内容
self.startButton.setText("开始")
# 为按钮绑定事件(点击按钮时就触发)
self.startButton.clicked.connect(self.predict)
#####多了这一块,不知道为什么如果不加就没有按钮
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)
#####
# 定义状态栏(这里参数是MainWindow,另一个文件写的参数是self
self.statusbar = QtWidgets.QStatusBar(MainWindow)
# 将状态栏设置为当前窗口的状态栏(这里调用的对象是MainWindow,另一个文件则是self
MainWindow.setStatusBar(self.statusbar)
# 设置状态栏的对象名称
self.statusbar.setObjectName("statusbar")
# 设置状态栏样式
self.statusbar.setStyleSheet('QStatusBar::item {border: none;}')
# 定义文本标签
self.statusLabel = QLabel()
# 设置文本标签显示内容
self.statusLabel.setText(" 准备 ")
# self.statusbar.showMessage('准备')
# 定义进度条
self.progressBar = QProgressBar()
# 设置进度条的范围,参数1为最小值,参数2为最大值(可以调得更大,比如1000
self.progressBar.setRange(0, 100)
# 设置进度条的初始值
self.progressBar.setValue(0)
# 设置定时器
self.timer = QBasicTimer()
self.step = 0
# 往状态栏中添加组件(stretch应该是拉伸组件宽度)
self.statusbar.addPermanentWidget(self.startButton, stretch=0)
self.statusbar.addPermanentWidget(self.statusLabel, stretch=2)
self.statusbar.addPermanentWidget(self.progressBar, stretch=10)
# 其他界面设置
self.retranslateUi(MainWindow)#多了参数MainWindow
QtCore.QMetaObject.connectSlotsByName(MainWindow)#参数是MainWindow,不是self
#多了参数MainWindow
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
# 设置窗口标题
MainWindow.setWindowTitle(_translate("MainWindow", "testLoading"))
def timerEvent(self, event):
if self.step >= 100:
self.timer.stop()
self.startButton.setEnabled(True)
self.startButton.setText("开始")
self.statusLabel.setText(" 预测完成 ")
return
self.step = self.step + 1
self.progressBar.setValue(self.step)
def onStart(self):
self.statusLabel.setText(" 请稍后 ")
self.startButton.setEnabled(False)
self.startButton.setText("预测中...")
# 参数2本是self,报错,改为MainWindow不报错,但是不运行
self.timer.start(100, MainWindow)
#处理具体的业务逻辑,如调用深度学习模型进行预测。
def predict(self):
print('predict')
self.onStart()
if __name__ == '__main__':
app = QApplication(sys.argv)
MainWindow = QMainWindow()
ui = Ui_MainWindow()
#把QMainWindow的对象作为参数,传入ui的setupUi方法
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
运行结果(进度条根本就不走)
可以成功运行的代码(进度条可以动)
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QProgressBar, QLabel, QApplication, QMainWindow
from PyQt5.QtCore import QBasicTimer
import sys
class Ui_MainWindow(QMainWindow):
def __init__(self,parent=None):
super(Ui_MainWindow,self).__init__(parent)
self.setupUi()
#这里可以定义一些为当前类所用的全局变量
self.filepath = ''
def setupUi(self):
#设置窗口的对象名称
self.setObjectName("MainWindow")
#设置窗口大小
self.resize(800, 600)
#定义按钮
self.startButton = QtWidgets.QPushButton(self)
# 设置按钮对象名称(不是按钮显示内容)
self.startButton.setObjectName("pred")
#设置按钮位置
self.startButton.setGeometry(QtCore.QRect(10, 300, 93, 28))
#设置按钮显示内容
self.startButton.setText("开始")
#为按钮绑定事件(点击按钮时就触发)
self.startButton.clicked.connect(self.predict)
#这里我绑定的是具体的业务处理函数,如果你想点击按钮就开始走进度条,则用下面这句
# 也可以直接为按钮绑定事件,点击按钮时,就开始走进度条
# self.startButton.clicked.connect(self.onStart)
#定义状态栏
self.statusbar = QtWidgets.QStatusBar(self)
# 将状态栏设置为当前窗口的状态栏
self.setStatusBar(self.statusbar)
# 设置状态栏的对象名称
self.statusbar.setObjectName("statusbar")
#设置状态栏样式
self.statusbar.setStyleSheet('QStatusBar::item {border: none;}')
# 定义文本标签
self.statusLabel = QLabel()
# 设置文本标签显示内容
self.statusLabel.setText(" 准备 ")
#定义进度条
self.progressBar = QProgressBar()
# 设置进度条的范围,参数1为最小值,参数2为最大值(可以调得更大,比如1000
self.progressBar.setRange(0, 100)
# 设置进度条的初始值
self.progressBar.setValue(0)
#设置定时器(走进度条的时候需要使用,否则进度条不会变化,而是固定不变
self.timer = QBasicTimer()
self.step = 0
# 往状态栏中添加组件(stretch应该是拉伸组件宽度)
self.statusbar.addPermanentWidget(self.startButton, stretch=0)
self.statusbar.addPermanentWidget(self.statusLabel, stretch=2)
self.statusbar.addPermanentWidget(self.progressBar, stretch=10)
#其他界面设置
self.retranslateUi()
QtCore.QMetaObject.connectSlotsByName(self)
#====================这部分可跳过,主要是给我自己看=======================
#补充:注意这里,到底加不加self,到底是用MainWindow还是self,和'__main__':中用的代码有关
#如果在主函数入口是先new MainWindow再作为参数传入Ui_MainWindow(),则用下面这两行。
#如果没有new MainWindow就不需要
# self.retranslateUi(self)
# QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self):
_translate = QtCore.QCoreApplication.translate
#设置窗口标题
self.setWindowTitle(_translate("MainWindow", "testLoading"))
def timerEvent(self, event):
if self.step >= 100:
self.timer.stop()
self.startButton.setEnabled(True)
self.startButton.setText("开始")
self.statusLabel.setText(" 预测完成 ")
return
self.step = self.step + 1
self.progressBar.setValue(self.step)
def onStart(self):
self.statusLabel.setText(" 请稍后 ")
self.startButton.setEnabled(False)
self.startButton.setText("预测中...")
self.timer.start(100, self)
#处理具体的业务逻辑,如调用深度学习模型进行预测。
def predict(self):
self.onStart()
################用print模拟模型的调用####################
print('predict.......')
if __name__ == '__main__':
app = QApplication(sys.argv)
ui = Ui_MainWindow()
ui.show()
sys.exit(app.exec_())
运行结果
详见此文(有动图,进度条已经实现):pyqt5 嵌于主界面状态栏的进度条