Python PyQt5 进度条没有进展

3

基本上,我的程序旨在在后台逐行显示读取Excel文件的进度。到目前为止,我有以下代码:

excelresult.py:

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtCore import Qt, QBasicTimer
import os, sys, xlrd, threading, time, pythoncom
import win32com.client
from time import sleep
from test import MyGlobals


class ExcelCheck(threading.Thread):
progPercent = 0

def __init__(self):
    threading.Thread.__init__(self)
    self.event = threading.Event()

def run(self):
    pythoncom.CoInitialize()
    try:
        while not self.event.is_set():
            excel = win32com.client.Dispatch("Excel.Application")
            wb = excel.ActiveWorkbook
            ws = wb.Worksheets("TC")
            va_title = ws.Range(ws.Range('I7'), ws.Range('I700'))
            i = 0
            for r in va_title.Cells:
                if r.Text != '':
                    i = i + 1
                    # print(r.Text)
            # print(i)
            # print(round(i / 178.0 * 100,0))
            # rounding off
            progPercent = round(i / 178.0 * 100.0)
            MyGlobals.x=progPercent

            print(progPercent)
        return progPercent
    except:
        print('Excel is not executed')



        # sleep(1)
        # self.event.wait()

def stop(self):
    self.event.set()

scm.py

# -*- coding: utf-8 -*-

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtCore import Qt, QBasicTimer
import os, sys, xlrd, win32com.client, xlwt, threading, time
from time import sleep
from ExcelResult import *
from test import MyGlobals
import threading

class Ui_MainWindow(object):
def __init__(self):
    super().__init__()
    self.btn_active = False
    print('init_false')


def startBtnClicked(self):
    self.btnStart.setText('start!')
    self.btn_active = True

    print(self.btn_active)
    tmr = ExcelCheck()
    tmr.start()

    while(MyGlobals.x<=100):

        #print (MyGlobals.x)
        self.progressBar.setValue(MyGlobals.x)

    # self.progressBar.minimum = 1
    # self.progressBar.maximum = 100
    # for progPercent in range(1, 101):
    #     self.progressBar.setValue(progPercent)
    #     time.sleep(1)
def exitBtnClicked(self):
    # self.ExcelCheck()
    self.btn_active = False
    print(self.btn_active)
    # os.system("taskkill /f /im Scm21.Client.exe")
    # self.close()
    # Stop the progress of python
    self.sys.exit()
    tmr = ExcelCheck()
    tmr.stop()

def setupUi(self, MainWindow):
    MainWindow.setObjectName("MainWindow")
    MainWindow.resize(446, 207)

    self.centralwidget = QtWidgets.QWidget(MainWindow)
    self.centralwidget.setObjectName("centralwidget")

    self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
    self.progressBar.setGeometry(QtCore.QRect(40, 70, 381, 23))
    self.progressBar.setProperty("value", 0)
    self.progressBar.setObjectName("progressBar")

    self.btnStart = QtWidgets.QPushButton(self.centralwidget)
    self.btnStart.setGeometry(QtCore.QRect(110, 110, 75, 23))
    self.btnStart.setObjectName("btnStart")
    self.btnStart.clicked.connect(self.startBtnClicked)

    self.btnExit = QtWidgets.QPushButton(self.centralwidget)
    self.btnExit.setGeometry(QtCore.QRect(260, 110, 75, 23))
    self.btnExit.setObjectName("btnExit")
    self.btnExit.clicked.connect(self.exitBtnClicked)

    MainWindow.setCentralWidget(self.centralwidget)
    self.menubar = QtWidgets.QMenuBar(MainWindow)
    self.menubar.setGeometry(QtCore.QRect(0, 0, 446, 21))
    self.menubar.setObjectName("menubar")
    MainWindow.setMenuBar(self.menubar)
    self.statusbar = QtWidgets.QStatusBar(MainWindow)
    self.statusbar.setObjectName("statusbar")
    MainWindow.setStatusBar(self.statusbar)
    self.retranslateUi(MainWindow)
    QtCore.QMetaObject.connectSlotsByName(MainWindow)

def retranslateUi(self, MainWindow):
    _translate = QtCore.QCoreApplication.translate
    MainWindow.setWindowTitle(_translate("MainWindow", "SCM21"))
    self.btnStart.setText(_translate("MainWindow", "Start"))
    self.btnExit.setText(_translate("MainWindow", "Exit"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

并且,test.py

class MyGlobals(object):
    x = 0

所以,我能够使用test.py将ExcelResult.py中的ProgPercent值传递到scm.py中,但是我完全不知道如何更新进度条的值。
我尝试使用循环,但它会导致GUI挂起。
谢谢。

将返回的progPercent更改为返回self.progPercent - eyllanesc
我建议您使用QThread而不是threading.Thread。 - eyllanesc
@eyllanesc 我已经能够获取进度百分比值了,这会有什么区别吗? - Karmesh Maheshwari
此外,我完全不知道如何使用QThread方法。 - Karmesh Maheshwari
1个回答

2

使用Qthread:

import time
from PyQt5 import QtCore
from PyQt5 import QtWidgets


class ExcelCheck(QtCore.QThread):
    updated = QtCore.pyqtSignal(int)
    running = False

    def __init__(self, parent=None):
        super(ExcelCheck, self).__init__(parent)
        self.progPercent = 0
        self.running = True

    def run(self):
        while self.running:
            self.progPercent += 1
            self.progPercent %= 100
            self.updated.emit(int(self.progPercent))
            time.sleep(0.1)

    def stop(self):
        self.running = False


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent=parent)
        self.setupUi(self)
        self.btn_active = False

    def startBtnClicked(self):
        self.btnStart.setText('start!')
        self.btn_active = True
        self.tmr = ExcelCheck(self)
        self.tmr.updated.connect(self.updateValue)
        self.tmr.start()

    def updateValue(self, data):
        self.progressBar.setValue(data)

    def exitBtnClicked(self):
        # self.ExcelCheck()
        self.btn_active = False
        self.tmr.stop()
        self.sys.exit()

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(446, 207)

        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar.setGeometry(QtCore.QRect(40, 70, 381, 23))
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")

        self.btnStart = QtWidgets.QPushButton(self.centralwidget)
        self.btnStart.setGeometry(QtCore.QRect(110, 110, 75, 23))
        self.btnStart.setObjectName("btnStart")
        self.btnStart.clicked.connect(self.startBtnClicked)

        self.btnExit = QtWidgets.QPushButton(self.centralwidget)
        self.btnExit.setGeometry(QtCore.QRect(260, 110, 75, 23))
        self.btnExit.setObjectName("btnExit")
        self.btnExit.clicked.connect(self.exitBtnClicked)

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 446, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "SCM21"))
        self.btnStart.setText(_translate("MainWindow", "Start"))
        self.btnExit.setText(_translate("MainWindow", "Exit"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

嘿,谢谢。但是,当我在替换进度更新逻辑时,QT窗口立即关闭,没有显示任何进度。 - Karmesh Maheshwari
嘿,我已经让它工作了,但是退出只在一开始的几秒钟内有效,在进度完成后,如果我们按退出键,窗口以及退出键都会变得无响应并且窗口挂起。有什么建议吗? - Karmesh Maheshwari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接