如何在 pyqt pyside 中同时 运行 一个对象的多个实例
how to run many instances of an object simultaneously in pyqt pyside
下面的代码是一个示例程序,只要单击“新建”按钮,每个选项卡都包含 QWebView 浏览器(在 PyQt/PySide 中使用)和“开始”按钮,当 "Start" 按钮单击浏览器一一加载 3 个站点
问题是:
当打开多个标签和 运行 所有标签或多个标签时,所有其他标签暂停加载直到最后一个完成加载然后下一个恢复
我想运行他们同时怎么办?
import sys
from PySide.QtGui import *
from PySide.QtCore import *
from PySide.QtWebKit import *
class Main_Gui(QDialog):
def __init__(self):
QDialog.__init__(self)
layout = QVBoxLayout()
self.bt_new = QPushButton('New')
self.tabwidget = QTabWidget()
layout.addWidget(self.tabwidget)
layout.addWidget(self.bt_new)
self.setLayout(layout)
self.bt_new.clicked.connect(self.add_new)
def add_new(self):
br = browser()
self.tabwidget.addTab(br, 'browser')
class browser(QWidget):
def __init__(self):
QWidget.__init__(self)
layout = QVBoxLayout()
self.br = QWebView()
self.bt_Start = QPushButton('Start')
layout.addWidget(self.br)
layout.addWidget(self.bt_Start)
self.setLayout(layout)
self.bt_Start.clicked.connect(self.start_load)
def start_load(self):
self.th = QThread()
self.th.started.connect(self.load)
self.th.start()
def load(self):
sites = ['https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/'
, 'http://www.codecademy.com/tracks/python', 'http://www.google.com']
for i in sites:
self.br.load(QUrl(i))
self.sleep(20)
def sleep(self, seconds):
end = QTime.addSecs(QTime.currentTime(), seconds)
while end > QTime.currentTime():
QCoreApplication.processEvents()
app = QApplication(sys.argv)
win = Main_Gui()
win.resize(800, 600)
win.show()
sys.exit(app.exec_())
您没有为 QThread
分配任何工作(不要重新实现 run
方法)。 browser.load
插槽,您已使用 th.started
信号连接,在主线程中执行(因为您的浏览器是在其中创建的)。这会导致您的问题。
此外,您只能从主线程更改 GUI(例如调用 self.br.load
方法)(为了线程安全)。
class TimerThread(QThread):
nextURL = pyqtSignal(str)
def run(self):
sites = ['https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/',
'http://www.codecademy.com/tracks/python', 'http://www.google.com']
for url in sites:
print(self.thread(), url)
self.nextURL.emit(url)
self.sleep(10)
class browser(QWidget):
def __init__(self):
[...]
self.th = QThread()
def start_load(self):
self.stop_thread(self.th)
self.th = TimerThread()
self.th.nextURL.connect(self.load_url_slot)
self.th.start()
def load_url_slot(self, url):
self.br.load(QUrl(url))
def stop_thread(self, thread):
thread.terminate()
if thread.isRunning():
QCoreApplication.processEvents()
感谢 Alexander,他给了我线索和下面我在问题中提交的示例的完整代码,问题是我想告诉 QThread 等待页面加载,我找到了创建局部变量的解决方案在 QThread 中调用加载并将浏览器 loadFinished 信号连接到函数使加载完成时加载变量为真,在 Qthread 中我编写等待代码直到加载变量变为真
import sys
from PySide.QtGui import *
from PySide.QtCore import *
from PySide.QtWebKit import *
from Browser_AutoPilot import BrowserAutoPilot
class Main_Gui(QDialog):
def __init__(self):
QDialog.__init__(self)
layout = QVBoxLayout()
self.bt_new = QPushButton('New')
self.tabwidget = QTabWidget()
layout.addWidget(self.tabwidget)
layout.addWidget(self.bt_new)
self.setLayout(layout)
self.bt_new.clicked.connect(self.add_new)
def add_new(self):
br = browser()
self.tabwidget.addTab(br, 'browser')
class browser(QWidget):
load_finished = Signal()
def __init__(self):
QWidget.__init__(self)
layout = QVBoxLayout()
self.br = BrowserAutoPilot()
self.bt_Start = QPushButton('Start')
layout.addWidget(self.br)
layout.addWidget(self.bt_Start)
self.setLayout(layout)
self.th = TimerThread()
self.bt_Start.clicked.connect(self.start_load)
def start_load(self):
self.stop_thread(self.th)
self.th.nextURL.connect(self.load_url_slot)
self.br.loadFinished.connect(self.wait_loading)
self.th.start()
def load_url_slot(self, url):
self.br.load(QUrl(url))
def wait_loading(self):
self.th.loaded = True
def stop_thread(self, thread):
thread.terminate()
if thread.isRunning():
QCoreApplication.processEvents()
def sleep(self, seconds):
end = QTime.addSecs(QTime.currentTime(), seconds)
while end > QTime.currentTime():
QCoreApplication.processEvents()
class TimerThread(QThread):
nextURL = Signal(str)
def __init__(self, loaded=False):
QThread.__init__(self)
self.loaded = loaded
def run(self):
sites = ['https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/',
'http://www.codecademy.com/tracks/python', 'http://www.google.com']
for url in sites:
print(self.thread(), url)
self.nextURL.emit(url)
self.loaded = False
while not self.loaded:
self.sleep(1)
app = QApplication(sys.argv)
win = Main_Gui()
win.resize(800, 600)
win.show()
sys.exit(app.exec_())
下面的代码是一个示例程序,只要单击“新建”按钮,每个选项卡都包含 QWebView 浏览器(在 PyQt/PySide 中使用)和“开始”按钮,当 "Start" 按钮单击浏览器一一加载 3 个站点 问题是: 当打开多个标签和 运行 所有标签或多个标签时,所有其他标签暂停加载直到最后一个完成加载然后下一个恢复 我想运行他们同时怎么办?
import sys
from PySide.QtGui import *
from PySide.QtCore import *
from PySide.QtWebKit import *
class Main_Gui(QDialog):
def __init__(self):
QDialog.__init__(self)
layout = QVBoxLayout()
self.bt_new = QPushButton('New')
self.tabwidget = QTabWidget()
layout.addWidget(self.tabwidget)
layout.addWidget(self.bt_new)
self.setLayout(layout)
self.bt_new.clicked.connect(self.add_new)
def add_new(self):
br = browser()
self.tabwidget.addTab(br, 'browser')
class browser(QWidget):
def __init__(self):
QWidget.__init__(self)
layout = QVBoxLayout()
self.br = QWebView()
self.bt_Start = QPushButton('Start')
layout.addWidget(self.br)
layout.addWidget(self.bt_Start)
self.setLayout(layout)
self.bt_Start.clicked.connect(self.start_load)
def start_load(self):
self.th = QThread()
self.th.started.connect(self.load)
self.th.start()
def load(self):
sites = ['https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/'
, 'http://www.codecademy.com/tracks/python', 'http://www.google.com']
for i in sites:
self.br.load(QUrl(i))
self.sleep(20)
def sleep(self, seconds):
end = QTime.addSecs(QTime.currentTime(), seconds)
while end > QTime.currentTime():
QCoreApplication.processEvents()
app = QApplication(sys.argv)
win = Main_Gui()
win.resize(800, 600)
win.show()
sys.exit(app.exec_())
您没有为 QThread
分配任何工作(不要重新实现 run
方法)。 browser.load
插槽,您已使用 th.started
信号连接,在主线程中执行(因为您的浏览器是在其中创建的)。这会导致您的问题。
此外,您只能从主线程更改 GUI(例如调用 self.br.load
方法)(为了线程安全)。
class TimerThread(QThread):
nextURL = pyqtSignal(str)
def run(self):
sites = ['https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/',
'http://www.codecademy.com/tracks/python', 'http://www.google.com']
for url in sites:
print(self.thread(), url)
self.nextURL.emit(url)
self.sleep(10)
class browser(QWidget):
def __init__(self):
[...]
self.th = QThread()
def start_load(self):
self.stop_thread(self.th)
self.th = TimerThread()
self.th.nextURL.connect(self.load_url_slot)
self.th.start()
def load_url_slot(self, url):
self.br.load(QUrl(url))
def stop_thread(self, thread):
thread.terminate()
if thread.isRunning():
QCoreApplication.processEvents()
感谢 Alexander,他给了我线索和下面我在问题中提交的示例的完整代码,问题是我想告诉 QThread 等待页面加载,我找到了创建局部变量的解决方案在 QThread 中调用加载并将浏览器 loadFinished 信号连接到函数使加载完成时加载变量为真,在 Qthread 中我编写等待代码直到加载变量变为真
import sys
from PySide.QtGui import *
from PySide.QtCore import *
from PySide.QtWebKit import *
from Browser_AutoPilot import BrowserAutoPilot
class Main_Gui(QDialog):
def __init__(self):
QDialog.__init__(self)
layout = QVBoxLayout()
self.bt_new = QPushButton('New')
self.tabwidget = QTabWidget()
layout.addWidget(self.tabwidget)
layout.addWidget(self.bt_new)
self.setLayout(layout)
self.bt_new.clicked.connect(self.add_new)
def add_new(self):
br = browser()
self.tabwidget.addTab(br, 'browser')
class browser(QWidget):
load_finished = Signal()
def __init__(self):
QWidget.__init__(self)
layout = QVBoxLayout()
self.br = BrowserAutoPilot()
self.bt_Start = QPushButton('Start')
layout.addWidget(self.br)
layout.addWidget(self.bt_Start)
self.setLayout(layout)
self.th = TimerThread()
self.bt_Start.clicked.connect(self.start_load)
def start_load(self):
self.stop_thread(self.th)
self.th.nextURL.connect(self.load_url_slot)
self.br.loadFinished.connect(self.wait_loading)
self.th.start()
def load_url_slot(self, url):
self.br.load(QUrl(url))
def wait_loading(self):
self.th.loaded = True
def stop_thread(self, thread):
thread.terminate()
if thread.isRunning():
QCoreApplication.processEvents()
def sleep(self, seconds):
end = QTime.addSecs(QTime.currentTime(), seconds)
while end > QTime.currentTime():
QCoreApplication.processEvents()
class TimerThread(QThread):
nextURL = Signal(str)
def __init__(self, loaded=False):
QThread.__init__(self)
self.loaded = loaded
def run(self):
sites = ['https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/',
'http://www.codecademy.com/tracks/python', 'http://www.google.com']
for url in sites:
print(self.thread(), url)
self.nextURL.emit(url)
self.loaded = False
while not self.loaded:
self.sleep(1)
app = QApplication(sys.argv)
win = Main_Gui()
win.resize(800, 600)
win.show()
sys.exit(app.exec_())