pyqt QThread 多线程实例(详细解释)

pyqt QThread 多线程实例(详细解释)_第1张图片

python 2.7  / Pyside (如果使用pyQt4,将Pyside直接替换PyQt4即可)

首先我们在Qt Designer中画好界面并自动生成design.py,注意生成后还要部分收到修改,然后创建main.py

design.py 主要负责写软件界面的文件。

main.py 主要负责写业务逻辑的文件。

design.py

# -*- coding: utf-8 -*-

from PySide import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(526, 373)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.subreddits_input_layout = QtGui.QHBoxLayout()
        self.subreddits_input_layout.setObjectName(_fromUtf8("subreddits_input_layout"))
        self.label_subreddits = QtGui.QLabel(self.centralwidget)
        self.label_subreddits.setObjectName(_fromUtf8("label_subreddits"))
        self.subreddits_input_layout.addWidget(self.label_subreddits)
        self.edit_subreddits = QtGui.QLineEdit(self.centralwidget)
        self.edit_subreddits.setObjectName(_fromUtf8("edit_subreddits"))
        self.subreddits_input_layout.addWidget(self.edit_subreddits)
        self.verticalLayout.addLayout(self.subreddits_input_layout)
        self.label_submissions_list = QtGui.QLabel(self.centralwidget)
        self.label_submissions_list.setObjectName(_fromUtf8("label_submissions_list"))
        self.verticalLayout.addWidget(self.label_submissions_list)
        self.list_submissions = QtGui.QListWidget(self.centralwidget)
        self.list_submissions.setBatchSize(1)
        self.list_submissions.setObjectName(_fromUtf8("list_submissions"))
        self.verticalLayout.addWidget(self.list_submissions)
        self.progress_bar = QtGui.QProgressBar(self.centralwidget)
        self.progress_bar.setProperty("value", 0)
        self.progress_bar.setObjectName(_fromUtf8("progress_bar"))
        self.verticalLayout.addWidget(self.progress_bar)
        self.buttons_layout = QtGui.QHBoxLayout()
        self.buttons_layout.setObjectName(_fromUtf8("buttons_layout"))
        self.btn_stop = QtGui.QPushButton(self.centralwidget)
        self.btn_stop.setEnabled(False)
        self.btn_stop.setObjectName(_fromUtf8("btn_stop"))
        self.buttons_layout.addWidget(self.btn_stop)
        self.btn_start = QtGui.QPushButton(self.centralwidget)
        self.btn_start.setObjectName(_fromUtf8("btn_start"))
        self.buttons_layout.addWidget(self.btn_start)
        self.verticalLayout.addLayout(self.buttons_layout)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "Threading Tutorial - nikolak.com", None))
        self.label_subreddits.setText(_translate("MainWindow", "Subreddits:", None))
        self.edit_subreddits.setPlaceholderText(_translate("MainWindow", "python,programming,linux,etc (comma separated)", None))
        self.label_submissions_list.setText(_translate("MainWindow", "Submissions:", None))
        self.btn_stop.setText(_translate("MainWindow", "Stop", None))
        self.btn_start.setText(_translate("MainWindow", "Start", None))

 

main.py

# -*- coding: utf-8 -*-
from PySide import QtGui
from PySide.QtCore import QThread, SIGNAL
import sys
import design
import urllib2
import json
import time


class getPostsThread(QThread):
    '''线程类'''
    def __init__(self, subreddits):
        QThread.__init__(self)
        self.subreddits = subreddits

    def __del__(self):
        self.wait()

    def _get_top_post(self, subreddit):
        """从唯一必需参数传递的subreddit返回带有顶部帖子标题,作者和subreddit名称的预格式化字符串。"""
        url = "https://www.reddit.com/r/{}.json?limit=1".format(subreddit)
        headers = {'User-Agent': '[email protected] tutorial code'}
        request = urllib2.Request(url, headers=headers)
        response = urllib2.urlopen(request)
        data = json.load(response)
        top_post = data['data']['children'][0]['data']
        return "'{title}' by {author} in {subreddit}".format(**top_post)

    def run(self):
        """用start()运行"""
        # 遍历self.subreddits列表中的每个项目(在__init__期间提供),并且对于每个项目,
        for subreddit in self.subreddits:
            # 获取有效subreddit名称的字符串,并使用reddit中的_get_top_post方法获取顶部帖子。将结果存储在名为top_post的局部变量中。
            top_post = self._get_top_post(subreddit)
            # 然后发出'SIGNAL add_post(QString)'信号,其中QString等于_get_top_post函数设置的top_post变量。
            self.emit(SIGNAL('add_post(QString)'), top_post)
            self.sleep(2)

class ThreadingTutorial(QtGui.QMainWindow, design.Ui_MainWindow):
    """主逻辑类,需要继承UI类"""
    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self)
        # 将“启动”按钮链接到start_getting_top_posts函数中
        self.btn_start.clicked.connect(self.start_getting_top_posts)

    def start_getting_top_posts(self):
        # 获取信息
        # 获取s用户输入到QLineEdit字段中
        subreddit_list = str(self.edit_subreddits.text()).split(',')
        # 如果没有输入文字,这将等于''
        if subreddit_list == ['']:
            # 是否有任何东西可以从中获取,如果没有显示消息并中止
            QtGui.QMessageBox.critical(self, "No subreddits","You didn't enter any subreddits.",QtGui.QMessageBox.Ok)
            return


        # 初始化值
        # 设置进度条的最大值,可以是任意int,它将自动转换为x/100%值
        # 例如max_value = 3,current_value = 1,进度条将显示33%
        self.progress_bar.setMaximum(len(subreddit_list))
        # 将每次运行的值初始化设置为0
        self.progress_bar.setValue(0)


        # 创建线程
        # 我们创建一个新的getPostsThread线程实例,将subreddits列表传递给线程
        self.get_thread = getPostsThread(subreddit_list)


        # 连接
        # 接下来,我们将来自getPostsThread线程的事件连接到我们希望在这些信号被触发时运行的函数,这里介绍两种信号处理

        # 连接自定义信号
        # 添加返回信息将在本类的add_post方法中进行处理,并且线程将发出的信号是‘SIGNAL(“add_post(QString)”)’,
        # 其余我们可以用相同的方法来连接任何信号
        self.get_thread.connect(SIGNAL("add_post(QString)"), self.add_post)

        # 连接内置信号
        # 无论线程是完成还是终止,我们希望向用户显示已完成的通知,无论是主动终止还是已完成
        # 完成的信号将熄灭。所以我们不需要专门捕捉已终止,但如果我们想要的话,也可以去做。
        self.get_thread.connect(SIGNAL("finished()"), self.done)


        # 启动线程的事件
        self.get_thread.start()
        # 当线程开始运行时,能允许用户停止/终止线程,所以我们启用“停止”按钮
        self.btn_stop.setEnabled(True)
        # 我们将“停止”按钮的单击连接到QThread实例所具有的内置终止方法terminate/quit
        #self.btn_stop.clicked.connect(self.get_thread.terminate)
        self.btn_stop.clicked.connect(self.get_thread.quit)
        # 我们不希望用户在此线程运行时启动另一个线程,因此我们禁用了“启动”按钮。
        self.btn_start.setEnabled(False)

    def add_post(self, post_text):
        """将给定此函数的文本添加到我们GUI中的list_submissions QListWidget中,并将进度条的当前值增加1"""
        self.list_submissions.addItem(post_text)
        self.progress_bar.setValue(self.progress_bar.value() + 1)

    def done(self):
        # 禁用“停止”按钮,
        self.btn_stop.setEnabled(False)
        # 启用“启动”按钮
        self.btn_start.setEnabled(True)
        # 将进度条重置为0
        self.progress_bar.setValue(0)
        # 弹出提示信息
        QtGui.QMessageBox.information(self, "Done!", "Done fetching posts!")


def main():
    # 创建应用
    app = QtGui.QApplication(sys.argv)
    # 创建实例表单
    form = ThreadingTutorial()
    # 显示实例
    form.show()
    # 退出程序
    app.exec_()


if __name__ == '__main__':
    main()

 

https://nikolak.com/pyqt-threading-tutorial/

你可能感兴趣的:(python,pyQt,pyside2,pyside)