当我在doWork
方法中运行时,通过单击button1
,进度条将按预期工作。
然而,当我通过列表中的doWork
其他方法的方法(即btn2
,btn3
),进度条刚跳到100%它启动后。
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
from selenium import webdriver
class SeleniumWorker(QtCore.QObject):
progressChanged = QtCore.pyqtSignal(int)
def doWork(self, lst=['http://www.somesite.com/',
'http://www.somesite.com/page2',
'http://www.somesite.com/page3']):
progress = 0
browser = webdriver.Firefox()
links = lst
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)
button1 = QtWidgets.QPushButton("Start1")
button2 = QtWidgets.QPushButton("Start2")
button3 = QtWidgets.QPushButton("Start3")
lay.addWidget(progressBar)
lay.addWidget(button1)
lay.addWidget(button2)
lay.addWidget(button3)
self.thread = QtCore.QThread()
self.worker = SeleniumWorker()
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.doWork)
button1.clicked.connect(self.thread.start)
button2.clicked.connect(self.btn2)
button3.clicked.connect(self.btn3)
self.worker.progressChanged.connect(progressBar.setValue)
def btn2(self):
self.lst2 = ['http://www.somesite.com/page4',
'http://www.somesite.com/page5',
'http://www.somesite.com/page6']
self.worker.doWork(self.lst2)
def btn3(self):
self.lst3 = ['http://www.somesite.com/page7',
'http://www.somesite.com/page8',
'http://www.somesite.com/page9']
self.worker.doWork(self.lst3)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
看来您不了解我先前解决方案的逻辑,我将详细说明该过程:
[1] self.thread = QtCore.QThread()
[2] self.worker = SeleniumWorker()
[3] self.worker.moveToThread(self.thread)
[4] self.worker.progressChanged.connect(progressBar.setValue, QtCore.Qt.QueuedConnection)
[5] self.thread.started.connect(self.worker.doWork)
QThread
是线程处理程序,因此该类的对象使我们可以在除主线程(称为GUI线程)之外的其他线程上执行任务。
您正在创建一个具有doWork方法的SeleniumWorker对象,该对象是不应在GUI线程中执行的阻塞任务,并且将使用先前的QThread来实现。
由于该函数必须在另一个线程中执行,因此具有该方法的对象必须移至该另一个线程。
另一个线程中的对象的信号连接到QProgressBar
GUI线程中的对象,该连接必须使用flag进行QtCore.Qt.QueuedConnection
。
当线程启动时,它将调用doWork函数,并且由于self.worker对象在另一个线程中,因此该函数也将在另一个线程中执行。
对于您在下一部分显示的代码中,您doWork
在线程尚未启动时正在调用该函数,因此它将在主线程中执行。
def btn2(self):
...
# main thread
self.worker.doWork(self.lst2)
传递url的一种方法是通过setter方法,然后启动线程。线程启动时,将调用doWork
,doWork
执行时,将progressChanged
发出信号。
通过以上所有操作,我们获得了以下内容:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from selenium import webdriver
class SeleniumWorker(QtCore.QObject):
progressChanged = QtCore.pyqtSignal(int)
started = QtCore.pyqtSignal()
finished = QtCore.pyqtSignal()
def setUrls(self, urls=['http://www.somesite.com/',
'http://www.somesite.com/page2',
'http://www.somesite.com/page3']):
self.urls = urls
def doWork(self):
self.started.emit()
progress = 0
self.progressChanged.emit(progress)
browser = webdriver.Firefox()
links = self.urls
for link in links:
browser.get(link)
progress += 100 / len(links)
self.progressChanged.emit(progress)
browser.close()
self.finished.emit()
class Widget(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
QtWidgets.QWidget.__init__(self, *args, **kwargs)
lay = QtWidgets.QHBoxLayout(self)
self.progressBar = QtWidgets.QProgressBar()
self.progressBar.setRange(0, 100)
button1 = QtWidgets.QPushButton("Start1")
button2 = QtWidgets.QPushButton("Start2")
button3 = QtWidgets.QPushButton("Start3")
lay.addWidget(self.progressBar)
lay.addWidget(button1)
lay.addWidget(button2)
lay.addWidget(button3)
self.thread = QtCore.QThread()
self.worker = SeleniumWorker()
self.worker.moveToThread(self.thread)
self.worker.progressChanged.connect(self.progressBar.setValue, QtCore.Qt.QueuedConnection)
self.thread.started.connect(self.worker.doWork)
button1.clicked.connect(self.btn1)
button2.clicked.connect(self.btn2)
button3.clicked.connect(self.btn3)
self.worker.finished.connect(self.on_finished)
self.worker.started.connect(lambda: self.buttons_setEnable(False))
def on_finished(self):
self.buttons_setEnable(True)
if self.thread.isRunning():
self.thread.quit()
self.thread.wait()
def buttons_setEnable(self, enable):
for btn in self.findChildren(QtWidgets.QPushButton):
btn.setEnabled(enable)
def btn1(self):
self.worker.setUrls()
self.thread.start()
def btn2(self):
lst2 = ['http://www.somesite.com/page4',
'http://www.somesite.com/page5',
'http://www.somesite.com/page6']
self.worker.setUrls(lst2)
self.thread.start()
def btn3(self):
lst3 = ['http://www.somesite.com/page7',
'http://www.somesite.com/page8',
'http://www.somesite.com/page9']
self.worker.setUrls(lst3)
self.thread.start()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
注意 :我添加了在按钮运行时禁用按钮的功能,因为适当的是,线程在运行时不要再次启动。
问题内容: 当我在方法中运行代码时,通过点击,进度条将按预期工作。 然而,当我通过列表中的其他方法的方法(即,),进度条刚跳到100%它启动后。 问题答案: 看来您不了解我先前解决方案的逻辑,我将详细说明该过程: 是线程处理程序,因此该类的对象使我们可以在除主线程(称为GUI线程)之外的其他线程上执行任务。 您正在创建一个具有doWork方法的SeleniumWorker对象,该对象是不应在GUI
PS Vita的系统软件可通过升级,追加各式各样的功能或强化安全性。使用时请随时升级为最新版本。 若要进行系统升级,需事先将连接的电脑设为以下状态。 连接互联网 安装/下载PlayStation®内容管理助手 可在以下网站进行下载。 http://cma.dl.playstation.net/cma/ 1. 在电脑确认内容管理助手是否已启动。 可从电脑的工作列确认。 2. 使用USB连接线连接PS
PS Vita的系统软件可通过升级,追加各式各样的功能或强化安全性。使用时请随时升级为最新版本。 若要进行升级,需事先将连接的PS3™设为以下状态。 连接互联网 系统软件升级为版本4.00以上 关闭所有使用中的应用程序,显示(用户) 1. 使用USB连接线连接PS Vita和PS3™。 2. 操作PS Vita,轻触[系统升级]>[连接至PS3™进行升级]。 可通过PS3™的网络功能,经由互联网下
问题内容: 我有一个奇怪的场景,其中SQL Server 2012数据库中的自动标识int列未正确递增。 假设我有一个使用int自动标识作为主键的表,它偶尔会跳过增量,例如: 1,2,3,4,5,1004,1005 这是在非常随机的时间在随机数量的表上发生的,无法复制以找到任何趋势。 这是怎么回事?有没有办法使它停止? 问题答案: 这完全是正常的。微软在SQL Server 2012中添加了,最后
问题内容: 这是在PyQt4,Linux和Python 2.5上 我可以将PyQt的窗口设置为“始终位于其他应用程序之上”吗? 例如,在GTK中,我使用属性:Modal。 现在,在PyQt中,我正在使用QWidget,但是,我找不到一种方法来实现。 有任何想法吗?? 问题答案: 向QMainWindow传递 窗口标志(或使用setWindowFlags)。 顾名思义,这是对窗口管理器的提示(不是硬
问题内容: 我正在尝试编写一个脚本,该脚本在执行任务时将显示忙碌指示。任务结束后,进度条将填满,表明任务已完成100%。我只是希望进度条显示任务正在进行中,但是当我启动任务时,忙碌的指示停止了。在我看来,指示和任务无法一起继续进行。请帮我。这是mycode: 问题答案: 首先,直接编辑使用QtDesigner创建的代码是一个坏主意。您可能已经在文档顶部看到该行。对于这样一个简单的小部件,最好使用手