Solved 'PySide2.QtCore.Signal' object has no attribute 'emit'
-
When I call emit, the interpreter keep telling me emit do not exist
OS : win10 64bits
python : 3.7.3(anaconda)
install by pip : pip install PySide2
llvm: libclang-release_70-based-windows-mingw_64\libclangSource codes to reproduce
import sys from PySide2.QtCore import QObject, Signal from PySide2.QtGui import QFont from PySide2.QtWidgets import QApplication, QPushButton class someClass(QObject): def __init__(self): super(someClass, self).__init__() self.someSignal = Signal() try: self.someSignal.emit() except Exception as e: print("__init__:") print(e) if __name__ == "__main__": app = QApplication(sys.argv) sc = someClass() button = QPushButton(text="Press me if you want to close the server") button.resize(640, 480) button.setFont(QFont("Arial", 20, QFont.Bold)) button.clicked.connect(button.close) button.show() sys.exit(app.exec_())
packages installed by pip
certifi 2019.3.9 mkl-fft 1.0.10 mkl-random 1.0.2 numpy 1.16.2 pip 19.0.3 PySide2 5.12.2 scikit-learn 0.20.3 scipy 1.2.1 setuptools 40.8.0 shiboken2 5.12.2 wheel 0.33.1 wincertstore 0.2
packages installed by anaconda
# Name Version Build Channel blas 1.0 mkl anaconda ca-certificates 2019.1.23 0 anaconda certifi 2019.3.9 py37_0 anaconda icc_rt 2019.0.0 h0cc432a_1 anaconda intel-openmp 2019.3 203 anaconda mkl 2019.3 203 anaconda mkl_fft 1.0.10 py37h14836fe_0 anaconda mkl_random 1.0.2 py37h343c172_0 anaconda numpy 1.16.2 py37h19fb1c0_0 anaconda numpy-base 1.16.2 py37hc3f5095_0 anaconda openssl 1.1.1 he774522_0 anaconda pip 19.0.3 py37_0 anaconda pyside2 5.12.2 pypi_0 pypi python 3.7.3 h8c8aaf0_0 anaconda scikit-learn 0.20.3 py37h343c172_0 anaconda scipy 1.2.1 py37h29ff71c_0 anaconda setuptools 40.8.0 py37_0 anaconda shiboken2 5.12.2 pypi_0 pypi sqlite 3.27.2 he774522_0 anaconda vc 14.1 h21ff451_3 anaconda vs2015_runtime 15.5.2 3 anaconda wheel 0.33.1 py37_0 anaconda wincertstore 0.2 py37_0 anaconda
Edit : Install by Python 3.5.4 got the same issues
-
Workaround found
import sys from PySide2.QtCore import QObject, Signal from PySide2.QtGui import QFont from PySide2.QtWidgets import QApplication, QPushButton class someClass(QObject): class commu(QObject): someSignal = Signal() def __init__(self): super(someClass, self).__init__() cm = self.commu() self.someSignal = cm.someSignal cm.someSignal.connect(self.print_msg) try: cm.someSignal.emit() except Exception as e: print("__init__:") print(e) def print_msg(self): print("lalalu") if __name__ == "__main__": app = QApplication(sys.argv) sc = someClass() button = QPushButton(text="Press me if you want to close the server") button.resize(640, 480) button.setFont(QFont("Arial", 20, QFont.Bold)) button.clicked.connect(button.close) button.show() sys.exit(app.exec_())
Awkward, but unless it work.
My feel about Qt for python, if you want to use Qt, good with c++ and not forced to used python, pick c++ first. Qt written by c++ has better tool chains and easier to use, more natural compare with Qt for python.
-
Your work-around is the long-winded approach. Simply define your signal as a class variable, but connect/reference it as an instance variable. I believe for the signal/slot mechanism to work worrectly the signals and slots MUST be bound to object instances, not static class methods/variables.
The following works flawlessly in pyqt.
class something(QObject): # class variable mySignal = pyqtSignal() def Connections(self): # used as an instance variable here self.mySignal.connect(self.someslot) def DoSomething(self): # used as an instance variable here self.mySignal.emit()
-
pyqt do not equal to pyside2, they are different beast, with different gotcha
-
I suggest reading this wiki <https://wiki.qt.io/Qt_for_Python_Signals_and_Slots>.
What I wrote above is valid in pyside2 as well: declare signal as class variable in a class derived from QObject, and call it as an instance variable using emit()...with the correction to my initial comment, that apparently slots can be static or global methods.
cheers
-
@Kent-Dorfman Tried, do not work, the interpreter keep telling me emit do not exist
-
Try this:
import sys from PySide2.QtCore import QObject, Signal, Slot from PySide2.QtGui import QFont from PySide2.QtWidgets import QApplication, QPushButton class someClass(QObject): someSignal = Signal() def __init__(self): super(someClass, self).__init__() self.someSignal.connect(self.print_msg) try: self.someSignal.emit() except Exception as e: print("__init__:") print(e) @Slot() def print_msg(self): print("lalalu") if __name__ == "__main__": app = QApplication(sys.argv) sc = someClass() button = QPushButton(text="Press me if you want to close the server") button.resize(640, 480) button.setFont(QFont("Arial", 20, QFont.Bold)) button.clicked.connect(button.close) button.show() sys.exit(app.exec_())
- Signals have to be class variables to work.
- You also need to make sure that the
__init__
of the QObject is called. This is where pyside does the setup of the signals, trying to use the signal before setup wont work properly. - Lastly, make sure you use a Slot decorator on methods you want to connect into the signal system. It will appear to work without the decorator, but you will run into issues with the python class and c++ object lifetimes getting out of sync.
-
@KeirRice If i copy that code and execute it, it immedeatly prints "lalalu". and not on click.
-
@Iceflower said in 'PySide2.QtCore.Signal' object has no attribute 'emit':
it immedeatly prints "lalalu". and not on click
Yes, because the signal is emited in someClass.init
The buitton is only there to close the app.
If you want to print on button click then connect a slot like it is done now for button.close:button.clicked.connect(sc.print_msg)
-
Im posting this because the replies above are a bit odd to me... This should work >
from PySide2.QtCore import Signal, QObject class myTestObject(QObject): someSignal = Signal(str) def __init__(self): QObject.__init__(self) # call to initialize properly self.someSignal.connect(self.testSignal) # test link self.someSignal.emit("Wowz") # test def testSignal(self, arg): print("my signal test from init fire", arg)