Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在多线程PyQT中更新GUI元素_Python_Multithreading_Pyqt - Fatal编程技术网

Python 在多线程PyQT中更新GUI元素

Python 在多线程PyQT中更新GUI元素,python,multithreading,pyqt,Python,Multithreading,Pyqt,我花了一段时间研究如何使用PyQT执行多线程程序,更新GUI以显示结果 我习惯于通过示例学习,但我找不到(是的,我找了好几个星期)任何使用多线程处理的简单程序示例,例如连接到www站点列表(5个线程)和仅打印带有响应代码的已处理URL 有谁能和我分享代码,或者给我发一个好的教程,在那里可以解释这样的程序吗?这里有一些非常基本的例子 您可以将GUI元素的引用传递给线程,并在线程中更新它们 import sys import urllib2 from PyQt4 import QtCore, Q

我花了一段时间研究如何使用PyQT执行多线程程序,更新GUI以显示结果

我习惯于通过示例学习,但我找不到(是的,我找了好几个星期)任何使用多线程处理的简单程序示例,例如连接到www站点列表(5个线程)和仅打印带有响应代码的已处理URL


有谁能和我分享代码,或者给我发一个好的教程,在那里可以解释这样的程序吗?

这里有一些非常基本的例子

您可以将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,谢谢编辑!我同意小部件和线程安全。我想,这段代码之所以有效,是因为在特定版本上运气好。