PDA

View Full Version : Sending signals from one module to another



Dubbie
5th July 2010, 11:25
Hi,

I have an application I am writing that has a fairly complicated set of functions that take a while to run.

I have put them inside a separate module file (and in their own class) to keep things simple.

the end of my main GUI file looks like this:



if __name__ == "__main__":
import sys

app = QtGui.QApplication(sys.argv)

if len(sys.argv) == 1:
filePath = serverRoot + ''
else:
filePath = sys.argv[1]

chunks = os.path.split(filePath)
fpath = chunks[0]
fname = chunks[1]

panel = StartQT4(fpath, fname)
panel.show()

sys.exit(app.exec_())


I'm guessing this is a very newb question, but I can't seem to figure out how to send a signal (so I can update the UI) from a class in a separate file.

Imagine the other file looks something like this:




#myLib.py

class Stuff:
def doComplicatedStuff():
# Somehow send a signal here back to the main app that called this function



I am planning on running the "complicated function" in a separate thread so that the GUI updating will work.

Am I way off here?
This is only my 3rd day of Python, so please be gentle :)

Thanks in advance.

tbscope
5th July 2010, 11:47
This is only my 3rd day of Python, so please be gentle :)

I have exactly zero seconds of experience with Python, so I'm not able to help you with the language syntax.
However, I can tell you how signals and slots work.

You have two classes

class MyClass1
...

class MyClass2
...

You then create objects based on these classes (I don't know how this is done in Python, so the rest is pseudo code)
MyClass1 myClass1Object
MyClass2 myClass2Object

You can then link them together:
connect(myClass1Object, SIGNAL(finishedTask1()), myClass2Object, SLOT(printResults()))
connect(myClass2Object, SIGNAL(somethingElse()), myClass1Object, SLOT(doAnotherThing()))

When using connect, you link one or two objects.

Be careful when using signals and slots in threads, the documentation is not clear on how it works.

Dubbie
5th July 2010, 12:16
Thankyou for the hint!

I *think* I get what you mean. I'll give it a try in the morning.

Thanks very much for your help!

R

Dubbie
6th July 2010, 01:11
Ok, I'm still not getting this working.

I have written a bare-bones app to illustrate what I want to do:

This is my main file: (test2_ui.py)



from test2 import *
from PyQt4 import QtCore, QtGui

class StartQT4(QtGui.QMainWindow,):

def __init__(self, parent=None):

QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)

QtCore.QObject.connect(self.ui.pushButton,QtCore.S IGNAL("clicked()"), self.ok)

def closeApp(self):
self.close()

def ok(self):
import testlib
tl = testlib.lazyworker()
QtCore.QObject.connect(tl,QtCore.SIGNAL("update(int)"), self.updateUI)
tl.doWork()

def updateUI(self, prog):
self.ui.label.setText(str(prog))

if __name__ == "__main__":
import sys

app = QtGui.QApplication(sys.argv)

panel = StartQT4()
panel.show()

sys.exit(app.exec_())


This is my UI include: (test2.py)



from PyQt4 import QtCore, QtGui

class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 300)
self.label = QtGui.QLabel(Dialog)
self.label.setGeometry(QtCore.QRect(70, 120, 221, 16))
self.label.setObjectName("label")
self.pushButton = QtGui.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(70, 180, 231, 91))
self.pushButton.setObjectName("pushButton")

self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)

def retranslateUi(self, Dialog):
Dialog.setWindowTitle(QtGui.QApplication.translate ("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("Dialog", "TextLabel", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton.setText(QtGui.QApplication.transla te("Dialog", "PushButton", None, QtGui.QApplication.UnicodeUTF8))



This is my module with class inside: (testlib.py)



import time
from PyQt4 import QtCore, QtGui

class lazyworker:
def doWork(self):
for self.i in range(0,100):
time.sleep(0.1)
self.emit(SIGNAL("update(int)"), self.i)


When I try to run this I get the following error:



TypeError: arguments did not match any overloaded call:
QObject.connect(QObject, SIGNAL(), QObject, SLOT(), Qt.ConnectionType=Qt.AutoConnection): argument 1 has unexpected type 'lazyworker'
QObject.connect(QObject, SIGNAL(), callable, Qt.ConnectionType=Qt.AutoConnection): argument 1 has unexpected type 'lazyworker'
QObject.connect(QObject, SIGNAL(), SLOT(), Qt.ConnectionType=Qt.AutoConnection): first argument of unbound method must have type 'QObject'


I gather this is because it wants a class of type Qobject, not my "lazyworker" type.

I'm not really sure what do to from here.

Thanks in advance!

R

ChrisW67
6th July 2010, 02:30
Lazyworker needs to inherit from QObject to gain the needed functionality. Not a snake handler either but something like;


class lazyworker(QtCore.QObject):
...

Dubbie
6th July 2010, 02:52
Ah, that was the missing link!

Thanks so much.

It's all working great now, of course the UI doesn't update, but I figure that is because the thread is locking it.

Now to get the multithreading working.

Thanks very much for the fast and accurate help.