Archive for the 'Qt4' Category

Checking what PyQt4 version you’re running

Friday, February 1st, 2008

This is one of those things I tend to forget


>>> PyQt4.Qt.qVersion()
'4.3.3'

PyQt4: Using QMutex vs QMutexLocker.

Sunday, November 25th, 2007

Here’s some code for my future reference on how to use QMutex or QMutexLocker.

Lessons Learned:
* Use QMutex to protect data, not code. Try not to lock hughe amounts of code within a function with mutex.lock(), mutex.unlock(), if for any reason you forget to release the lock you’ll be in trouble. Use the mutex directly only when you know what it is that you want to protect concurrent access from.
* When you have a complex function and you don’t want to worry about what to protect and when to release the lock (on exceptions thrown, before returns,etc), you can create an instance of QMutexLocker and it should release the mutex lock upon destruction… this takes us to the next lesson
* When using a QMutexLocker, DO NOT make the QMutexLocker an attribute of your class, otherwise, the reference will live after the method finishes and the lock won’t be released.

Here’s some code.

from PyQt4.Qt import QObject, QMutex, QApplication, QThread, QMutexLocker
import sys

class MutexTestSubject(QObject):
	'''
	Class that uses a QMutex to synchronize
        access to its add(),substract() methods.

        This works perfectly fine.
	'''
	def __init__(self):
		QObject.__init__(self)
		self.MAX_LIMIT = 100
		self.MIN_LIMIT = 0
		self.counter = 50
		self.mutex = QMutex()

	def add(self):
		self.mutex.lock()
		if self.counter < self.MAX_LIMIT:
			self.counter = self.counter + 1
		self.mutex.unlock()

	def substract(self):
		self.mutex.lock()
		if self.counter > self.MIN_LIMIT:
			self.counter = self.counter - 1
		self.mutex.unlock()

	def printStatus(self,thread):
		print "Counter:",self.counter," - Thread:",id(thread)

		if self.counter > self.MAX_LIMIT+1 or self.counter < self.MIN_LIMIT:
			print "Stopping Threads, Max Surpassed, Not Thread Safe. Last Thread:",id(thread)
			sys.exit()
	

class MutexLockerTestSubject(QObject):
	'''
	Class that attemps to synchronize thread
 	access to its add(),substract() methods with
	the QMutexLocker object.
	'''
	def __init__(self):
		QObject.__init__(self)
		self.MAX_LIMIT = 100
		self.MIN_LIMIT = 0
		self.counter = 50
		self.mutex = QMutex()

	def add(self):
		#VIP: DO NOT MAKE mutexLocker an attribute of your class.
		#other wise it won't be destroyed and the lock will never be released.
		mutexLocker = QMutexLocker(self.mutex)
		if self.counter < self.MAX_LIMIT:
			self.counter = self.counter + 1

	def substract(self):
		mutexLocker = QMutexLocker(self.mutex)
		if self.counter > self.MIN_LIMIT:
			self.counter = self.counter - 1

	def printStatus(self,thread):
		print "Counter:",self.counter," - Thread:",id(thread)

		if self.counter > self.MAX_LIMIT+1 or self.counter < self.MIN_LIMIT:
			print "Stopping Threads, Max Surpassed, Not Thread Safe. Last Thread:",id(thread)
			sys.exit()


class AdderWorker(QThread):
	def __init__(self, mutexTestObject):
		self.mutexTestObject = mutexTestObject
		QThread.__init__(self)

	def run(self):
		while(True):
			self.mutexTestObject.add()
			self.mutexTestObject.printStatus(self)

class SubstractorWorker(QThread):
	def __init__(self, mutexTestObject):
		self.mutexTestObject = mutexTestObject
		QThread.__init__(self,mutexTestObject)

	def run(self):
		while(True):
			self.mutexTestObject.substract()
			self.mutexTestObject.printStatus(self)

if __name__ == "__main__":
	USE_MUTEX_LOCKER = True #switch this to use regular mutexes vd QMutexLocker
	app = QApplication(sys.argv)
	mutexTestObject = MutexTestSubject() if not USE_MUTEX_LOCKER else MutexLockerTestSubject()

	adderThread  = AdderWorker(mutexTestObject)
	substracterThread = SubstractorWorker(mutexTestObject)

	adderThread.start()
	substracterThread.start()

	sys.exit(app.exec_())

Note about Signals and PyQt4.

Monday, July 9th, 2007

I keep making the mistake of sending PyQt_PyObjects instead of sending actual Qt4 objects on signals that are defined by Qt like that.

Bottom line:

If a signal has been defined by Qt, to send Qt objects, just copy and paste it, do not try to override it by exchanging the Qt objects for PyQt_PyObject.

This is because PyQt_PyObject is used to represent regular Python objects, therefore, original Qt4 classes will never emit signals under those weird signatures, Qt4 seems to be very strict on how it matches signals.

So when you see something like this on the documentation:

Qt Signals
void currentItemChanged (QTreeWidgetItem *,QTreeWidgetItem *)

Define your signal for example like this, and it will work:

SIGNAL_ITEM_CHANGED = SIGNAL('currentItemChanged (QTreeWidgetItem *,QTreeWidgetItem *)')

Do not do this, cause it won’t work:

SIGNAL_ITEM_CHANGED = SIGNAL('currentItemChanged (PyQt_PyObject, PyQt_PyObject)')

(Keep in mind PyQt_PyObject is used to represent Python objects only, and its useful only when YOU define and emit your own signals)

then connect it from a QTreeWidget item (or derived object) to a listener object’s method like this:

QObject.connect(myQTree,SIGNAL_ITEM_CHANGED,myListener.onItemChanged)

Your object’s listener method should look like this:

def onItemChanged(self, current, previous):
  #do what you gotta do, current and previous will be QTreeWidgetItems

How to build PyQt4 for Windows

Friday, February 23rd, 2007

- Make sure you don’t have cygwin or C:devkitPromsysbin in your path,
or else your make files can end up trying to run the Makefile using ‘sh’ and all
the makefile we’re about to use are meant to run from the windows command line.

If for some odd reason you type ‘sh’ on your windows command line and you see something like:

sh-2.04$

You’re likely to find this later on:

/bin/sh: -c: line 2: syntax error: unexpected end of file

- Install Qt open source, with the exe installer, this will attempt to install
ming if you don’t have it installed, say yes, mingw rocks.

- Make sure you have the following Windows environment variables set:

QTDIR = c:Qt4.2.2
QTMAKESPEC = win32-g++

- Make sure you have Python2.5, Qt bin and Mingw bin folders on your path

PATH = %PATH%;c:Mingwbin;c:Mingwlibexecgccmingw323.4.2;c:python25bin;c:Qt4.2.2bin

- Get pexports just in case the Qt doesn’t have libQtCore4.a on its lib/
folder.

You can download pexports at:

http://www.emmestech.com/software/cygwin/pexports-043/download_pexports.html

If you don’t have that libQtCore4.a you won’t be able to build PyQt.

So you’ll need to do this, go to your Qt bin folder, say:
c:Qt4.2.2bin

And run this:

pexports QtCore4.dll > Qt4Core4.def
dlltool -dllname QtCore4.dll –def QtCore4.def –output-lib libQtCore4.a

Move the resulting file, libQtCore4.a, to c:Qt4.2.2lib

COMPILING SIP:
- PyQt needs “sip” to be able to bind the Qt libraries, sip will generate the necessary C++ code.
To install sip, get its source code, extract it to a folder say:

c:sip-4.5.2

Once inside run it’s configure.py like this:

python configure.py -p win32-g++

That will create the Makefiles, then you will make it using

mingw32-make

and

mingw32-make install

Now, I’m not sure what’s the environment variable of Mingw library path,
and I was having errors from the compilation of PyQt, telling me it couldn’t
find the sip libraries, so this is what I did:

– Copy all the .o files from c:sip-4.5.2siplib to c:mingwlib
– Copy all the .h files from c:sip-4.5.2siplib to c:mingwincludes

- Now it’s finally time to compile PyQt.
Uncompress the PyQt zip with the source (not the binary, if not we wouldn’t be doing this),
do it at the root of your hardrive (C:), you’ll end up with a folder named similar to this:

c:PyQt-win-gpl-4.1.1

Go in there and do this:
python configure.py
mingw32-make (this will take a long time, it will wrap every Qt C++ library on a new .cpp file which will be then compiled to exist as a python binding)
mingw32-make install

If you have any errors write me a comment on this post




  • Categories

  • June 2013
  • May 2013
  • April 2013
  • March 2013
  • February 2013
  • January 2013
  • December 2012
  • November 2012
  • October 2012
  • September 2012
  • July 2012
  • June 2012
  • May 2012
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • December 2011
  • November 2011
  • October 2011
  • September 2011
  • August 2011
  • June 2011
  • May 2011
  • April 2011
  • March 2011
  • February 2011
  • December 2010
  • November 2010
  • October 2010
  • September 2010
  • August 2010
  • July 2010
  • June 2010
  • May 2010
  • April 2010
  • March 2010
  • February 2010
  • January 2010
  • December 2009
  • October 2009
  • September 2009
  • July 2009
  • May 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • September 2008
  • August 2008
  • July 2008
  • June 2008
  • May 2008
  • April 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • June 2007
  • May 2007
  • April 2007
  • March 2007
  • February 2007
  • January 2007
  • December 2006
  • November 2006
  • October 2006
  • September 2006
  • August 2006
  • July 2006
  • June 2006
  • May 2006
  • April 2006
  • March 2006
  • February 2006
  • January 2006
  • December 2005
  • November 2005
  • October 2005
  • September 2005
  • August 2005
  • July 2005
  • June 2005
  • May 2005
  • April 2005
  • March 2005
  • February 2005
  • January 2005
  • December 2004
  • November 2004
  • October 2004