可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm having issues with a custom signal in a class I made.
Relevant code:
self.parse_triggered = QtCore.pyqtSignal() def parseFile(self): self.emit(self.parse_triggered)
Both of those belong to the class: RefreshWidget. In its parent class I have:
self.refreshWidget.parse_triggered.connect(self.tabWidget.giveTabsData())
When I try to run the program, I get the error:
AttributeError: 'PyQt4.QtCore.pyqtSignal' object has no attribute 'connect'
Help? Thanks in advance.
回答1:
I had the same exact problem as you.
Try moving
self.parse_triggered = QtCore.pyqtSignal()
out of your constructor but inside your class declaration. So instead of it looking like this:
class Worker(QtCore.QThread): def __init__(self, parent = None): super(Worker, self).__init__(parent) self.parse_triggered = QtCore.pyqtSignal()
It should look like this:
class Worker(QtCore.QThread): parse_triggered = QtCore.pyqtSignal() def __init__(self, parent = None): super(Worker, self).__init__(parent)
This might not be at all what you are looking for, but it worked for me. I switched back to old-style signals anyways because I haven't found a way in new-style signals to have an undefined number or type of parameters.
回答2:
You also get that error message if you fail to call super()
or QObject.__init__()
in your custom class.
A checklist for defining custom signals in a class in Qt in Python:
- your class derives from QObject (directly or indirectly)
- your class
__init__
calls super()
(or calls QObject.__init__()
directly.) - your signal is defined as a class variable, not an instance variable
- the signature (formal arguments) of your signal matches the signature of any slot that you will connect to the signal e.g.
()
or (int)
or (str)
or ((int,), (str,))
回答3:
I have recently started working with PySide (Nokia's own version of PyQt), and saw the exact same behaviour (and solution) with custom new-style signals. My biggest concern with the solution was that using a class variable to hold the signal would mess things up when I have multiple instances of that class (QThreads in my case).
From what I could see, QtCore.QObject.__init__(self)
finds the Signal variable in the class and creates a copy of that Signal for the instance. I have no idea what QObject.__init__()
does, but the resulting Signal does proper connect()
, disconnect()
and emit()
methods (and also a __getitem__()
method), whereas the class Signal or standalone Signal variables created outside of a QObject-derived class do not have these methods and can't be used properly.
回答4:
To use the signal/slot system you need to have a QObject inherited class.
Here is a simple example:
from PySide import QtCore class LivingBeing(QtCore.QObject): bornSignal = QtCore.Signal() # initialise our signal def __init__(self,name): QtCore.QObject.__init__(self) # initialisation required for object inheritance self.bornSignal.connect(self.helloWorld) # connect the born signal to the helloworld function self.name = name # self.alive = False def summonFromClay(self): self.alive = True self.bornSignal.emit() # emit the signal def helloWorld(self): print "Hello World !, my name is %s, this place is so great !" % self.name # now try the little piece of code if __name__ == '__main__': firstHuman = LivingBeing('Adam') firstHuman.summonFromClay()
回答5:
I had the same problem. I forgot that if a class uses Signals, then it must inherit from QObject. I was doing some re-factoring and did not pay attention to this.
回答6:
Why do you connect directly to the signal, while you can do self.connect(widget, SIGNAL('parse_triggered()'), listener.listening_method)
?
where self is, for example, the form itself, and may be the same as listener