pycharm+pyqt5在应用中遇到的一些问题总结

目录

1、UI与逻辑分离

2、线程的创建

3、动态创建多线程

4、停止指定线程



1、UI与逻辑分离

两者分离,一个是代码结构更清晰;另外,将复杂的逻辑放到线程中,不会造成UI的卡顿

2、线程的创建

网上很多方法和教程都是直接继承QThread,重写run方法,这样用起来的确简单方便,但是再翻下网上的资料,据说这是原设计者一直在骂的,不提倡的用法,正确的使用方法是继承QObject,复杂的工作放在work(名字自定义)方法中,如下:

class Parser(QObject):
    signal = pyqtSignal(int, str)  # 括号里填写信号传递的参数

    def __init__(self, id: int):
        super(Parser, self).__init__()
        self.__id = id

    @pyqtSlot()
    def work(self):
        # do something

然后在需要创建线程的地方:

    parserObj = Parser()
    parserThd = QThread()
    parserObj.moveToThread(parserThd)
    parserObj.signal.connect(self.msgBrowserCb)
    # connect只能连接一次,否则会出现多个slot函数工作
    # connect可以放在线程启动之后无影响
    parserThd.started.connect(parserObj.work)
    parserThd.start()

 这样就完成了线程的创建和使用。

3、动态创建多线程

参考了别人的示例:https://www.zchen.info/archives/multithreading-with-pyqt5-and-qthread.html

4、停止指定线程

3的示例中也包含了线程的停止,是通过发信号的方式来实现,但在测试中发现的,主线程中发出信号后,线程的槽函数并没有收到,不知为何,这里也遇到了相同的问题,并从中找到了解决方法:https://stackoverflow.com/questions/39976322/pyqt-how-to-send-a-stop-signal-into-a-thread-where-an-object-is-running-a-condi

在主线程中直接调用创建的QObject对象的方法,使其工作任务正常结束,再调用线程的quit();恢复时反之。


class Parser(QObject):
    signal = pyqtSignal(int, str)  # 括号里填写信号传递的参数

    def __init__(self, id: int):
        super(Parser, self).__init__()
        self.__id = id

        self.__abort = False

    @pyqtSlot()
    def work(self):
        # do something
        thread_name = QThread.currentThread().objectName()
        thread_id = int(QThread.currentThreadId())
        msgid = None
        self.__abort = False
        while 1:
            if self.__abort:
                break
            print('  running worker #{} from {}(#{})'.format(self.__id,
                                                             thread_name,
                                                             thread_id))
            self.signal.emit(thread_id, thread_name)
            time.sleep(2)
            # break

    def abort(self, finish_id=0):
            print('  worker #{} notified to abort'.format(self.__id))
            self.__abort = True

多线程创建时:

    self.__threads = []
    for i in range(self.model.rowCount()):
        print(self.model.data(self.model.index(i, 1)))
        parserObj = Parser(int(self.model.data(self.model.index(i, 0))))
        parserThd = QThread()
        parserThd.setObjectName('thread_' + str(i))
        self.__threads.append((parserThd, parserObj)) # 放到list列表中,便于管理
        parserObj.moveToThread(parserThd)
        parserObj.signal.connect(self.msgBrowserCb)
        # self.notice_signal.connect(parserObj.abort) # 此方法没效果
        parserThd.started.connect(parserObj.work)
        parserThd.start()

停止时点击按钮方法:

    def stopBtnCb(self):        
        # 获取tableView的当前行号
        worker_id = self.tableView.currentIndex().row()
        parserThd, parserObj = self.__threads[worker_id]
        # self.notice_signal.emit(worker_id) # 此方法没效果
        parserObj.abort(worker_id) #直接调用对象的abort
        parserThd.quit()
        # parserThd.wait()

猜你喜欢

转载自blog.csdn.net/hawk98/article/details/83107904