我构建了一个PyQt5 GUI来进行一些selenium测试。除PyQt进度条外,其他所有操作均按预期进行。
在下面的第一个示例中,当我使用Selenium浏览器时,最后,当浏览器关闭时,进度条只会跳到100%。但是,selenium工作正常。
def test(self): self.completed = 0 browser = webdriver.Firefox() links = ['http://www.somesite.com/', 'http://www.somesite.com/page2', 'http://www.somesite.com/page3'] for link in links: browser.get(link) self.completed += 100 / len(links) time.sleep(2) print(link) self.progressBar.setValue(self.completed) browser.close()
但是,在下面的此版本中,在Selenium浏览器被注释掉的情况下,进度条可以按预期工作。
def test(self): self.completed = 0 #browser = webdriver.Firefox() links = ['http://www.somesite.com/', 'http://www.somesite.com/page2', 'http://www.somesite.com/page3'] for link in links: #browser.get(link) self.completed += 100 / len(links) time.sleep(2) print(link) self.progressBar.setValue(self.completed) #browser.close()
阻塞任务与在其中执行GUI的事件循环不友好,因为它们阻止了GUI执行的常规任务,例如票证检查,重画等。
在这些情况下,解决方案是使用线程执行阻止任务并使用信号发送信息。
import sys from PyQt5 import QtCore, QtWidgets from selenium import webdriver class SeleniumWorker(QtCore.QObject): progressChanged = QtCore.pyqtSignal(int) def doWork(self): progress = 0 browser = webdriver.Firefox() links = ['http://www.somesite.com/', 'http://www.somesite.com/page2', 'http://www.somesite.com/page3'] for link in links: browser.get(link) progress += 100 / len(links) self.progressChanged.emit(progress) browser.close() class Widget(QtWidgets.QWidget): def __init__(self, *args, **kwargs): QtWidgets.QWidget.__init__(self, *args, **kwargs) lay = QtWidgets.QHBoxLayout(self) progressBar = QtWidgets.QProgressBar() progressBar.setRange(0, 100) button = QtWidgets.QPushButton("Start") lay.addWidget(progressBar) lay.addWidget(button) self.thread = QtCore.QThread() self.worker = SeleniumWorker() self.worker.moveToThread(self.thread) self.thread.started.connect(self.worker.doWork) button.clicked.connect(self.thread.start) self.worker.progressChanged.connect(progressBar.setValue, QtCore.Qt.QueuedConnection) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) w = Widget() w.show() sys.exit(app.exec_())