在多线程PyQT中更新GUI元素 [英] Updating GUI elements in MultiThreaded PyQT

查看:156
本文介绍了在多线程PyQT中更新GUI元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一段时间以查找信息如何使用PyQT做多线程程序,更新GUI以显示结果.

I was researching for some time to find information how to do multithreaded program using PyQT, updating GUI to show the results.

我习惯于通过示例进行学习,但我找不到(是的,我一直在找几个星期)使用多线程执行此简单任务的程序的任何简单示例,例如连接到www网站列表(5个线程)和只需打印带有响应代码的处理过的网址即可.

I'm used to learning by example and i can't find (yes i was looking for weeks) any simple example of program using multithreading doing such simple task as for example connecting to list of www sites (5 threads) and just printing processed urls with response code.

任何人都可以共享代码或将我发送到解释此类程序的很好的教程中吗?

Could anyone share code or send me to good tutorial where such program is explained ?

推荐答案

下面是一些非常基本的示例.

Here some very basic examples.

<罢工> 您可以将对GUI元素的引用传递给线程,然后在线程中更新它们.

You can pass references to GUI elements to threads, and update them in thread.

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小部件不是线程安全的,并且不应从除主线程之外的任何线程访问(请参阅

Editors Note: Qt widgets are not thread safe and should not be accessed from any thread but the main thread (see the Qt documentation for more details). The correct way to use threads is via signals/slots as the second part of this answer shows.

此外,您可以使用信号和插槽来分隔GUI和网络逻辑.

Also, you can use signals and slots, to separate gui and network logic.

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中更新GUI元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆