Pyqt - 有时没有收到Qthread上发出的信号

时间:2018-04-25 21:09:16

标签: python-3.x pyqt5 qt-signals

所以我有一个GUI,它使用大量的方法来登录程序并检索信息。所以我开始将该代码集成到Qthread中;一切都工作正常,直到我记得测试错误消息,似乎Qthread内的发出信号有时不会被我的主代码捕获。

以下是我正在讨论的代码:

(python 3,pyqt5)

代码修订版1 - 更改日志: testf - 所有值现在都使用信号和插槽加载到Qthread中 - 未经测试,将很快更新 - Qthread - 添加"信号接收功能" (tt信号添加到loginb)

std::tuple

线程代码:

def testf(self):
    self.movie.start()
    self.gif.show()
    self.myThread = thread()
    self.loginb.tt.connect(self.myThread.valueset)
    self.loginb.tt.emit(self.userfield.text(), self.pwfield.text(), self.checkBox.text(), self.checkBox.isChecked())
    self.myThread.start()
    self.myThread.done.connect(self.threadrelay)

def threadrelay(self, code, text): #decides what to do given the thread's emited signal arguments
    print('enter relay',code)
    self.movie.stop()
    self.gif.hide()
    self.myThread.exit()
    if code == 3:
        print(text)
        print('trying to open main diag')
        self.Omaindialog(text)
    elif code == 4:
        self.wrongpass.setText(text)
        self.wrongpass.show()            
    else:
        self.errordiag(text,code)

这只显示受影响的部分(可能更多我的代码受此影响,idk但我真的不知道这里发生了什么) - 所以" testf"函数被调用(按钮),它启动qthread,然后qthread发出带有参数的完成信号,这些参数将由" threadrelay"功能

这是一些输出(每个按钮点击之间约5-10秒):

class thread(QtCore.QThread):
    done=pyqtSignal(int, str)

    def valueset(self,u,p,c,ci):
        print('received values')
        self.user=u
        self.paw=p
        self.check=c
        self.checkis=ci

    def run (self):
        print(self.check == "Save password", self.check)
        if (self.paw=='' or self.user=='') and self.check == "Save password":
            print('if 1')
            txt=("loads of html code here")
            self.done.emit(4,txt)
            print('emited')
        elif ('@' not in self.user or '.' not in self.user) and self.check == "Save password":
            print('if 2')
            txt=("loads of html code here")
            self.done.emit(4,txt)
            print('emited')
        else:

EDIT1:大声笑我出去喝了一杯咖啡回来了,现在它的工作频率比没有...我感到困惑......它仍然无法正常工作有时虽然

EDIT2:我意识到我可以在 Qthread之前检查,但是这个问题可能也会发生在Qthread中的其余 emits (我刚刚和#39; t抓住它了,我想避开它并知道错误...

关于运行中的代码:复选框是多用途的,用于保存和加载密码(其中的文本会相应更改:如果有可用的密码,则自动勾选使用保存;如果用户取消,则为更改为"保存密码"选项); @或。不在usr.txt()中是因为用户必须是电子邮件。 wp(wrongpass)是一个标签,显示'请填写两个字段'或者'插入有效的电子邮件'。

更新:使用信号/插槽传递变量并没有解决我的问题。但是我修复了它,我发现可能Qthread正在快速发出信号,所以我在发出信号之前在if和elif中加了一个time.sleep(1),它完美无缺! - 这真的是原因吗?

1 个答案:

答案 0 :(得分:0)

我认为问题出在self.check.text () ==" Save password " 注意:

    self.checkBox = QtWidgets.QCheckBox('Save password', self)
    self.checkBox.toggle()
    self.checkBox.stateChanged.connect(self.changeTitle)
    self.stateCheckBox = 2

def changeTitle(self, state):
    self.stateCheckBox = state

试试我:

from PyQt5        import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import pyqtSignal, Qt

class Thread1(QtCore.QThread):
    done = pyqtSignal(int, str)
    def __init__(self, usr, paw, wp, check, parent=None):
        QtCore.QThread.__init__(self)
        self.user  = usr
        self.paw   = paw
        self.wp    = wp
        self.check = check

    def run (self):
        if (self.paw=='' or self.user=='' or self.wp=='') :
            txt=("Error: enter user or password or wrongpass")
            self.done.emit(4, txt)
        elif (self.paw != self.wp):
            txt=("Error:  password ")
            self.done.emit(4, txt)    
        elif self.check:
            txt=("Save data")
            self.done.emit(4, txt)             
        #elif ('@' not in self.user.text() or '.' not in self.user.text()) and self.check.text() == "Save password":
        # I do not know what it is
        elif ('@' not in self.user or '.' not in self.user) and self.check:
            print('\nif 2')
            txt=("loads of html code here")
            self.done.emit(4, txt)
            print('emited')
        else:
            txt=("do not save data")
            self.done.emit(4, txt)

class App(QtWidgets.QWidget):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)

        self.userfield = QtWidgets.QLineEdit(self)
        self.userfield.setPlaceholderText("userfield")
        self.pwfield = QtWidgets.QLineEdit(self)
        self.pwfield.setPlaceholderText("pwfield")
        self.wrongpass = QtWidgets.QLineEdit(self)
        self.wrongpass.setPlaceholderText("wrongpass")        

        self.checkBox = QtWidgets.QCheckBox('Save password', self)
        self.checkBox.toggle()
        self.checkBox.stateChanged.connect(self.changeTitle)
        self.stateCheckBox = 2

        self.but1 = QtWidgets.QPushButton("testf", self)
        self.but1.clicked.connect(self.testf)

        self.label = QtWidgets.QLabel("", self)

        self.grid1 = QtWidgets.QGridLayout()
        self.grid1.addWidget(self.userfield, 0,  0, 1, 20)
        self.grid1.addWidget(self.pwfield,   1,  0, 1, 20)
        self.grid1.addWidget(self.wrongpass, 2,  0, 1, 20)
        self.grid1.addWidget(self.checkBox,  3,  0, 1, 20)
        self.grid1.addWidget(self.but1,      4,  0, 1, 20)
        self.grid1.addWidget(self.label,     6,  0, 1, 20)
        self.grid1.setContentsMargins(10, 10, 10, 10)
        self.setLayout(self.grid1)


    def testf(self):                   # starter function - called by pushbutton
        #self.myThread = thread(self.userfield,self.pwfield, self.wrongpass, self.checkBox)

        #self.myThread = Thread1(self.userfield, self.pwfield, self.wrongpass, self.stateCheckBox)
        self.myThread = Thread1(str(self.userfield.text()), 
                                str(self.pwfield.text()), 
                                str(self.wrongpass.text()), 
                                int(self.stateCheckBox))

        self.myThread.start()
        self.myThread.done.connect(self.threadrelay)

    def threadrelay(self, code, text): #decides what to do given the thread's emited signal arguments
        # I do not know what it is
        #self.movie.stop()
        #self.gif.hide()
        self.myThread.exit()
        if code == 3:
            print(text)
            print('trying to open main diag')
            self.Omaindialog(text)            # I do not know what it is
        elif code == 4:
            self.label.setText(text)
        else:
            self.errordiag(text, code)

    def changeTitle(self, state):
        self.stateCheckBox = state

if __name__ == "__main__":
    import sys
    app        = QtWidgets.QApplication(sys.argv)
    myapp      = App()
    myapp.show()
    sys.exit(app.exec_())               

enter image description here