Note: If you’re new to using PyQt but are interested in great cross-platform GUI application development please read the PyQt Introduction article.
I actually think of this more as an FSQ than an FAQ. Frequently Searched Questions on my blog.
These are the contents of this article:
- Writing Custom Signals in PyQt
- Saving an Image as JPEG using a QImage in PyQt
- Tracking Mouse Hover events with PyQt
- Bonus Tips
Lets start with the most searched item.
Writing Custom Signals in PyQt
Writing custom signals that you want to ‘emit’ or trigger during certain events is an easy task. You need to create your signal object first. This is done using the PyQt.QtCore provided pyqtSignal() function. Its signature is given as:
QtCore.pyqtSignal([optional argument types], [optional name])
We need to create a signal object using this signal as a property in our class, then call its connect and emit methods to actually use it. If I were to explain diagrammatically:

Creating Custom Signals using PyQt
The following code sample explains three types of signals:
- Signals with no arguments (simpleSig)
- Signals with some arguments (2, argumentSig)
- Signals with multiple-type (overloaded) arguments (int and QString, doubleSig)
# -*- coding: utf-8 -*-
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
class MyWidget(QWidget):
# Defining signals below:
# No arguments, its a simple signal that can
# be emitted.
simpleSig = pyqtSignal()
# A signal that requires two parameters.
# (One is an integer, other is a Python list type)
# You can have one or more than two as well.
argumentSig = pyqtSignal(int, list)
# A signal that allows two different sets of params.
# One is if you send an int, the other is for QString.
# This signal is also optionally named using 'name'
# for use in more dynamic purposes.
doubleSig = pyqtSignal((int,), (QString,), name='doubles')
def __init__(self, parent=None):
# Construct the parent, never forget this!
super(MyWidget, self).__init__(parent)
# Connect our signals to their slots
self.simpleSig.connect(self.simpleSlot)
self.argumentSig.connect(self.argumentSlot)
# We have same slot for the double signals
# (aka) overloaded signals.
# Cause we can check the argument from within too!
self.doubleSig['int'].connect(self.doubleSlot)
self.doubleSig['QString'].connect(self.doubleSlot)
# Connect our button to a slot which
# will call the signals.
self.button = QPushButton('Press me', self)
self.button.clicked.connect(self.buttonClicked)
def buttonClicked(self, checked=False):
# Emit the various signals to use them.
self.simpleSig.emit()
self.argumentSig.emit(2, [1,2,3])
# Overloaded signals have the following format
# for emitting specifically.
self.doubleSig['int'].emit(42)
self.doubleSig['QString'].emit('Hitchhiking a ride.')
# Defining custom-signal slots below:
def simpleSlot(self):
# Takes no arguments
print "Simple custom signal:",
print "No arguments in this type of signal."
def argumentSlot(self, *args):
# ( Can also be 'argumentSlot(self, intArg, listArg)' )
# Has two arguments anyway, which is collected into one
# using '*' (A Python feature)
print "Multi-argument signal:",
print "Two arguments were passed: value: '%d' of %s and value: '%s' of %s." % (args[0], type(args[0]), args[1], type(args[1]))
def doubleSlot(self, someArgument):
# This slot handles both doubleSig(int)
# and doubleSig(QString)
print "Overloaded signal:",
print "An argument was passed and it was of '%s' and value: '%s'." % (type(someArgument), someArgument)
if __name__=='__main__':
app = QApplication(sys.argv)
widget = MyWidget()
widget.show()
app.exec_()
The output upon running this example code would be (printed in stdout):
Simple custom signal: No arguments in this type of signal. Multi-argument signal: Two arguments were passed: value: '2' of <type 'int'> and value: '[1, 2, 3]' of <type 'list'>. Overloaded signal: An argument was passed and it was of '<type 'int'>' and value: '42' Overloaded signal: An argument was passed and it was of '<class 'PyQt4.QtCore.QString'>' and value: 'Hitchhiking a ride.'
I hope this makes it clear on how to create your own/custom signals and to piggyback data on it via arguments (using their class/type to create them).
References: PyQt Documentation
Saving an Image as JPEG using QImage
JPEG is a wonderful, lossy image format. PyQt supports JPEG saving if a plugin called libjpeg exists. Anyhow to save a QImage as a JPEG image, do the following:
# Create a 50 pixel square image
# (or load your own using a filename).
img = QImage(50, 50, QImage.Format_RGB32)
# Lets draw a red square on this.
painter = QPainter(img)
painter.setBrush(QBrush(QColor('#ff0000')))
painter.drawRect(0,0,50,50)
painter.end()
# Save it as JPEG. Extension mention does
# all internal magic. 'jpg' also allowed.
img.save("sample.jpeg")
The above code snippet creates an image ‘sample.jpeg’ that looks like below:

A QImage saved JPEG - With a shape drawn using QPainter
There it is, as simple as that! Can be done via QPixmap too.
References: QImage, QPainter (Lots of other shape/figure drawing help here)
Tracking Mouse Hover Events with PyQt
Mouse hover events (known as the mouseMoveEvent(event) in PyQt) are tracked by default if the mouse is pressed and dragged. However if you’d like to also track mouse move events upon simple hover also (without a press requirement) you will need to enable the mouseTracking property of the QWidget (also available in all its derivatives, naturally).
So, to enable mouse tracking / mouse hover tracking for your widget you will need to call widget.setMouseTracking(True). The following code snippet is again a simple program that prints co-ordinates of the mouse pointer upon hover (without requiring a press held).
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
class MyWidget(QWidget):
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent)
# Enable mouse hover event tracking
self.setMouseTracking(True)
def mouseMoveEvent(self, event):
# This is a QWidget provided event
# that fires for every mouse move event
# (In our case the move is also the hover)
print "Mouse Pointer is currently hovering at: ", event.pos()
if __name__=='__main__':
app = QApplication(sys.argv)
widget = MyWidget()
widget.show()
app.exec_()
It should spew out some output like:
Mouse Pointer is currently hovering at: PyQt4.QtCore.QPoint(415, 66) Mouse Pointer is currently hovering at: PyQt4.QtCore.QPoint(420, 60) Mouse Pointer is currently hovering at: PyQt4.QtCore.QPoint(424, 56) Mouse Pointer is currently hovering at: PyQt4.QtCore.QPoint(427, 51) Mouse Pointer is currently hovering at: PyQt4.QtCore.QPoint(433, 41) Mouse Pointer is currently hovering at: PyQt4.QtCore.QPoint(438, 36)
An additional way, apart from QWidget.setMouseTracking(True) is to set a Qt.Hover attribute via QWidget.setAttribute(attribute) and then filtering this event out. If you’d like me to give an example for this method too, post a comment. I think the mouse tracking solution does it for detecting mouse hover events over your widgets as the other way might look ugly.
References: QMouseEvent
Bonus Tips
Screen Size
Getting the screen size of the desktop (the display resolution in other words) is simple. You need to access the desktop widget using QApplication.desktop() [Its static so you don't need your QApplication object] and then pulling out the size() from it. That is, do:
QApplication.desktop().size()
References: QApplication
Setting the Window Size
Um, am not sure what’s so ambiguous about setting the size/geometry of a widget in PyQt but to generally set any widget’s size, be it your QMainWindow object or a simple inner QWidget derivative, all you have to do is to set its geometry property like so:
# x and y are co-ordinates where the widget/window has to appear # and width and height are the sizes you're looking to set # (You can keep position same by using widgetObj.x()/y() to get current # values of x/y and passing them back in). widgetObj.setGeometry(x, y, width, height)
References: QWidget
End
That’s all for now folks, keep the searches or comment-queries coming if you still have some! (And oh, please do refer Qt Assistant too, it’s the right thing to do).