Проблема с QThread и декоратором Python

#python #multithreading #pyqt5

#python #многопоточность #pyqt5

Вопрос:

У меня проблема с моим кодом о Qthread с PyQt на Python 3.6 Ошибка в файле

 F:PROGRAMMESQtProjetcYrAnalyzerworker2.py", line 14, in run
self._target(*self._args, **self._kwargs)
TypeError: execute_this_function() takes 1 positional argument but 2 were given
[Finished in 3.1s with exit code 3221226505]
 

Это класс worker2.py :

 from PyQt5.QtCore import *
from PyQt5 import QtCore
from functools import wraps

class Runner(QtCore.QThread):
    def __init__(self, target, *args, **kwargs):
        super().__init__()
        self._target = target
        self._args = args
        self._kwargs = kwargs

    def run(self):
        self._target(*self._args, **self._kwargs)


def run(func):
    @wraps(func)
    def async_func(*args, **kwargs):
         runner = Runner(func, *args, **kwargs)
         func.__runner = runner
         runner.start()
    return async_func
 

это основной класс :

 from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import gui, os, time
from worker2 import *

class MyWindow(QMainWindow):

    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.ui = gui.Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.compteur.clicked.connect(self.execute_this_function)

    @run
    def execute_this_function(self):
        self.ui.edit_compteur.setText("1")
        time.sleep(0.5)
        self.ui.edit_compteur.setText("2")
        time.sleep(0.5)
        self.ui.edit_compteur.setText("3")
        time.sleep(0.5)
        self.ui.edit_compteur.setText("4")
        time.sleep(0.5)
        self.ui.edit_compteur.setText("5")
        time.sleep(0.5)
 

ОШИБКА :

 self._target(*self._args, **self._kwargs)
TypeError: execute_this_function() takes 1 positional argument but 2 were given
 

Комментарии:

1. есть отзывы??

Ответ №1:

Ошибка, которую вы указываете, вызвана тем, что clicked является перегруженным сигналом, то есть на самом деле это 2 сигнала, один с логической подписью, а другой без подписи: clicked = pyqtSignal([], [bool]) и по умолчанию он попытается передать логическое значение. Итак, решение состоит в том, чтобы установить подпись слота с помощью @pyqtSlot

Другая ошибка, которая все еще не отображается из-за предыдущей ошибки, заключается в том, что вы не должны обновлять графический интерфейс напрямую. Простая стратегия заключается в использовании QTimer.singleShot(0, ...) next для functools.partial, если вам нужно передать дополнительные аргументы.

 import time
from PyQt5 import QtCore, QtWidgets
from functools import partial

from worker2 import run
import gui


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.ui = gui.Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.compteur.clicked.connect(self.execute_this_function)

    @run
    @QtCore.pyqtSlot()
    def execute_this_function(self):
        wrapper = partial(self.ui.edit_compteur.setText, "1")
        QtCore.QTimer.singleShot(0, wrapper)
        time.sleep(0.5)
        wrapper = partial(self.ui.edit_compteur.setText, "2")
        QtCore.QTimer.singleShot(0, wrapper)
        time.sleep(0.5)
        wrapper = partial(self.ui.edit_compteur.setText, "3")
        QtCore.QTimer.singleShot(0, wrapper)
        time.sleep(0.5)
        wrapper = partial(self.ui.edit_compteur.setText, "4")
        QtCore.QTimer.singleShot(0, wrapper)
        time.sleep(0.5)
        wrapper = partial(self.ui.edit_compteur.setText, "5")
        QtCore.QTimer.singleShot(0, wrapper)
        time.sleep(0.5)