Python 在多线程PyQT中更新GUI元素
我花了一段时间研究如何使用PyQT执行多线程程序,更新GUI以显示结果 我习惯于通过示例学习,但我找不到(是的,我找了好几个星期)任何使用多线程处理的简单程序示例,例如连接到www站点列表(5个线程)和仅打印带有响应代码的已处理URLPython 在多线程PyQT中更新GUI元素,python,multithreading,pyqt,Python,Multithreading,Pyqt,我花了一段时间研究如何使用PyQT执行多线程程序,更新GUI以显示结果 我习惯于通过示例学习,但我找不到(是的,我找了好几个星期)任何使用多线程处理的简单程序示例,例如连接到www站点列表(5个线程)和仅打印带有响应代码的已处理URL 有谁能和我分享代码,或者给我发一个好的教程,在那里可以解释这样的程序吗?这里有一些非常基本的例子 您可以将GUI元素的引用传递给线程,并在线程中更新它们 import sys import urllib2 from PyQt4 import QtCore, Q
有谁能和我分享代码,或者给我发一个好的教程,在那里可以解释这样的程序吗?这里有一些非常基本的例子 您可以将GUI元素的引用传递给线程,并在线程中更新它们
import sys
import urllib2
from PyQt4 import QtCore, QtGui
class DownloadThread(QtCore.QThread):
def __init__(self, url, list_widget):
QtCore.QThread.__init__(self)
self.url = url
self.list_widget = list_widget
def run(self):
info = urllib2.urlopen(self.url).info()
self.list_widget.addItem('%s\n%s' % (self.url, info))
class MainWindow(QtGui.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.list_widget = QtGui.QListWidget()
self.button = QtGui.QPushButton("Start")
self.button.clicked.connect(self.start_download)
layout = QtGui.QVBoxLayout()
layout.addWidget(self.button)
layout.addWidget(self.list_widget)
self.setLayout(layout)
def start_download(self):
urls = ['http://google.com', 'http://twitter.com', 'http://yandex.ru',
'http://stackoverflow.com/', 'http://www.youtube.com/']
self.threads = []
for url in urls:
downloader = DownloadThread(url, self.list_widget)
self.threads.append(downloader)
downloader.start()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.resize(640, 480)
window.show()
sys.exit(app.exec_())
编辑器注意:Qt小部件不是线程安全的,除了主线程外,不应从任何线程访问(有关详细信息,请参阅)。正确使用线程的方法是通过信号/插槽,如回答的第二部分所示
此外,您还可以使用信号和插槽来分离gui和网络逻辑
import sys
import urllib2
from PyQt4 import QtCore, QtGui
class DownloadThread(QtCore.QThread):
data_downloaded = QtCore.pyqtSignal(object)
def __init__(self, url):
QtCore.QThread.__init__(self)
self.url = url
def run(self):
info = urllib2.urlopen(self.url).info()
self.data_downloaded.emit('%s\n%s' % (self.url, info))
class MainWindow(QtGui.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.list_widget = QtGui.QListWidget()
self.button = QtGui.QPushButton("Start")
self.button.clicked.connect(self.start_download)
layout = QtGui.QVBoxLayout()
layout.addWidget(self.button)
layout.addWidget(self.list_widget)
self.setLayout(layout)
def start_download(self):
urls = ['http://google.com', 'http://twitter.com', 'http://yandex.ru',
'http://stackoverflow.com/', 'http://www.youtube.com/']
self.threads = []
for url in urls:
downloader = DownloadThread(url)
downloader.data_downloaded.connect(self.on_data_ready)
self.threads.append(downloader)
downloader.start()
def on_data_ready(self, data):
print data
self.list_widget.addItem(unicode(data))
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.resize(640, 480)
window.show()
sys.exit(app.exec_())
嘿,我没有试过pyQt,但我在pygtk中使用了多线程。在pygtk中,gobject通常用于执行此操作。您应该为pyQt搜索类似的内容。另请参见,或为建议使用信号将线程与显示逻辑分离而搜索+1。但是禁止直接从非gui(主)线程与gui交互,不是吗?注意:第一个示例是错误的。不允许从线程调用
QListWidget.addItem()
。你必须使用信号。是的,这是一个糟糕的回答(对不起)。如果您这样做,您的程序将随机崩溃。Qt小部件不是线程安全的…@three_Pinepples,谢谢编辑!我同意小部件和线程安全。我想,这段代码之所以有效,是因为在特定版本上运气好。