how to emit signal from a non PyQt class?
pyqt, pyqt4, python, python-2.7, twisted
Solution
This is what I use in my one code for sending signals from QGraphicsItems (because they are not derived from QObject and cannot send/receive signals by default). It's basically a simplified version of Radio-'s answer.
from PyQt4 import QtGui as QG
from PyQt4 import QtCore as QC
class SenderObject(QC.QObject):
something_happened = QC.pyqtSignal()
`SenderObject` is a tiny class derived from QObject where you can put all the signals you need to emit. In this case only one is defined.
class SnapROIItem(QG.QGraphicsRectItem):
def __init__(self, parent = None):
super(SnapROIItem, self).__init__(parent)
self.sender = SenderObject()
def do_something_and_emit(self):
...
self.sender.something_happened.emit()
In the non-QObject class you add a `SenderObject` as a `sender` variable. Anywhere where the non-QObject class is used you can connect the signal from the `sender` to anything you need.
class ROIManager(QC.QObject):
def add_snaproi(self, snaproi):
snaproi.sender.something_happened.connect(...)
UPDATE
The full code is this and should print out "Something happened...":
from PyQt4 import QtGui as QG
from PyQt4 import QtCore as QC
class SenderObject(QC.QObject):
something_happened = QC.pyqtSignal()
class SnapROIItem(QG.QGraphicsItem):
def __init__(self, parent = None):
super(SnapROIItem, self).__init__(parent)
self.sender = SenderObject()
def do_something_and_emit(self):
self.sender.something_happened.emit()
class ROIManager(QC.QObject):
def __init__(self, parent=None):
super(ROIManager,self).__init__(parent)
def add_snaproi(self, snaproi):
snaproi.sender.something_happened.connect(self.new_roi)
def new_roi(self):
print 'Something happened in ROI!'
if __name__=="__main__":)
roimanager = ROIManager()
snaproi = SnapROIItem()
roimanager.add_snaproi(snaproi)
snaproi.do_something_and_emit()
UPDATE 2
Instead of
QtCore.QObject.connect(self,QtCore.SIGNAL('registered()'),self.registered)
you should have:
protocol.sender.registered.connect(self.registered)
This means you also need to get hold of the `protocol` instance in `self.pf` (by the way, do you import `Protocol` and then define it yourself as well?)
In the Protocol class instead of
QtCore.QObject.emit( QtCore.SIGNAL('registered')
you need to, first, instantiate a SenderObject in the Protocol.
class Protocol(amp.AMP):
def __init__( self, *args, **kw ):
super(Protocol, self).__init__(*args, **kw)
self.sender = SenderObject()
and then, in `register_procedure` emit the signal through `sender`: self.sender.registered.emit()
For all of this to work you'll have to have defined SenderObject as:
class SenderObject(QC.QObject):
registered = QC.pyqtSignal()
Problem
i'm programming an application in python using twisted and PyQt . the problem that i'm facing is that when a function in my twisted code is executed i have to print a line in the GUI, i'm trying to achieve this by emiting a signal (Non PyQt class). This does not seem to work, i have a doubt that the twisted event loop is screwing things for PyQt. Because the closeEvent signal is not being trapped by the program. Here's the code snippet: ``` from PyQt4 import QtGui, QtCore import sys from twisted.internet.protocol import Factory, Protocol from twisted.protocols import amp import qt4reactor class register_procedure(amp.Command): arguments = [('MAC',amp.String()), ('IP',amp.String()), ('Computer_Name',amp.String()), ('OS',amp.String()) ] response = [('req_status', amp.String()), ('ALIGN_FUNCTION', amp.String()), ('ALIGN_Confirmation', amp.Integer()), ('Callback_offset',amp.Integer()) ] class Ui_MainWindow(QtGui.QMainWindow): def __init__(self,reactor, parent=None): super(Ui_MainWindow,self).__init__(parent) self.reactor=reactor self.pf = Factory() self.pf.protocol = Protocol self.reactor.listenTCP(3610, self.pf) # listen on port 1234 def setupUi(self,MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) MainWindow.resize(903, 677) self.centralwidget = QtGui.QWidget(MainWindow) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth()) self.centralwidget.setSizePolicy(sizePolicy) self.create_item() self.retranslateUi(MainWindow) self.connect(self, QtCore.SIGNAL('triggered()'), self.closeEvent) QtCore.QObject.connect(self,QtCore.SIGNAL('registered()'),self.registered) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) self.pushButton_4.setText(_translate("MainWindow", "Delete System ", None)) self.pushButton.setText(_translate("MainWindow", "Add System", None)) self.label_2.setText(_translate("MainWindow", "SYSTEM STATUS", None)) self.label.setText(_translate("MainWindow", "Monitoring Output", None)) def registered(self):# this function is not being triggered print "check" self.textbrowser.append() def closeEvent(self, event):#neither is this being triggered print "asdf" self.rector.stop() MainWindow.close() event.accept() class Protocol(amp.AMP): @register_procedure.responder def register_procedure(self,MAC,IP,Computer_Name,OS): self.bridge_conn=bridge() cursor_device.execute("""select * FROM devices where MAC = ?;""",[(MAC)]) exists_val=cursor_device.fetchone() cursor_device.fetchone() print "register" if not exists_val== "": cursor_device.execute("""update devices set IP= ? , Computer_name= ? , OS = ? where MAC= ?;""",[IP,Computer_Name,OS,MAC]) QtCore.QObject.emit( QtCore.SIGNAL('registered')) # <--emits signal return {'req_status': "done" ,'ALIGN_FUNCTION':'none','ALIGN_Confirmation':0,'Callback_offset':call_offset(1)} else: cursor_device.execute("""INSERT INTO devices(Mac,Ip,Computer_name,Os) values (?,?,?,?);""",[MAC,IP,Computer_Name,OS]) QtCore.QObject.emit( QtCore.SIGNAL('registered'))#<--emits signal return {'req_status': "done" ,'ALIGN_FUNCTION':'main_loop()','ALIGN_Confirmation':0,'Callback_offset':0} if __name__ == "__main__": app = QtGui.QApplication(sys.argv) try: import qt4reactor except ImportError: from twisted.internet import qt4reactor qt4reactor.install() from twisted.internet import reactor MainWindow = QtGui.QMainWindow() # <-- Instantiate QMainWindow object. ui = Ui_MainWindow(reactor) ui.setupUi(MainWindow) MainWindow.show() reactor.run() ```