Introduction To GUI Programming in Python: Alice Invernizzi A.invernizzi@cineca - It
Introduction To GUI Programming in Python: Alice Invernizzi A.invernizzi@cineca - It
Python
Alice Invernizzi
[email protected]
Index
What is Qt?
Qt is a cross platform development framework written in C++.
languages, through language bindings available for Ruby, Java, Perl, and
also Python with PyQt.
The Qt toolkit is a collection of classes to simplify the creation of
Mac OS
Introduction to Qt
QtCore
QtGUI
Widgets:
Memory Management
Introspection (runtime identification of object types)
Event handling
Qt Object Model
All PyQt classes that derive from QObject can have a “parent”.
A widget that has no parent is a top-level window, and a widget that has a
parent (always another widget) is contained (displayed) within its parent.
Object Ownership
PyQt Simple Example
- an application object
- a main window (which has a central widget), or
- a main widget
Finally, we enter the mainloop of the application. The event handling starts
from this point. The mainloop receives events from the window system and
dispatches them to the application widgets. The mainloop ends, if we call
the exit() method or the main widget is destroyed
GUI Components
The programmer specifies the position and the size of each widget
in pixels.
NOTES:
The size and the position of a widget do not change, if you resize
a window
Applications might look different on various platforms
Box Layout
Layout management with layout classes is much more flexible and practical. It is
the preferred way to place widgets on a window. The basic layout classes are
QHBoxLayout and QVBoxLayout.
class BoxLayout(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle('box layout')
ok = QtGui.QPushButton("OK")
cancel = QtGui.QPushButton("Cancel")
hbox = QtGui.QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(ok)
hbox.addWidget(cancel)
vbox = QtGui.QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)
self.resize(300, 150)
app = QtGui.QApplication(sys.argv)
qb = BoxLayout()
qb.show()
sys.exit(app.exec_())
Grid Layout
The most universal layout class is the grid layout. This layout divides the
space into rows and columns.
import sys
from PyQt4 import QtGUi
class GridLayout(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle('grid layout')
names = [ '7', '8', '9', '4', '5', '6']
grid = QtGui.QGridLayout()
j=0
pos = [(0, 0), (0, 1), (0, 2), (1, 0), (1,1),(1,2)]
for i in names:
button = QtGui.QPushButton(i)
grid.addWidget(button, pos[j][0], pos[j][1])
j=j+1
self.setLayout(grid)
app = QtGui.QApplication(sys.argv)
qb = GridLayout()
qb.show()
sys.exit(app.exec_())
Main Window
The QMainWindow class provides a main application window. This enables to
create the classic application skeleton with a statusbar, toolbars and a
menubar.
The statusbar is a widget that is used for displaying status information.
import sys
from PyQt4 import QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.resize(250, 150)
self.setWindowTitle('statusbar')
self.statusBar().showMessage('Ready')
app = QtGui.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
Main Window
• A menubar is one of the most visible parts of the GUI application.
It is a group of commands located in various menus.
• Toolbars provide a quick access to the most frequently used
commands.
• GUI applications are controlled with commands. These commands
can be launched from a menu, a context menu, a toolbar or with
a shortcut. PyQt simplifies development with the introduction of
actions.
• User actions are represented by the QAction class
• The action system synchronizes menus, toolbars, and keyboard
shortcuts, it also stores information about tooltips and interactive
help
Main Window
MenuBar
QAction
To create an action, you can:
•Instantiate a QAction object directly ToolBar
•Call addAction() on existing QMenu and QToolBar
objects
•Then you can share it with other objects.
Events are an important part in any GUI program. Events are generated
by users or by the system. When we call the application's exec_()
method, the application enters the main loop. The main loop fetches
events and sends them to the objects. Trolltech has introduced a unique
signal and slot mechanism.
Signals are emitted, when users click on the button, drag a slider etc.
Signals can be emitted also by the environment.
Qobject::connect(src,SIGNAL(signature),dest,SLOT(signature))
app = QApplication(sys.argv)
form = MyForm()
form.show()
app.exec_()
Signal and Slot
Apart from being verbose and un-Pythonic, this syntax has a serious problem.
You must type the C++ signature of the signal exactly. Otherwise, the signal
just won’t fire, without an exception or any warning. This is a very
common mistake.
The "new-style" signal-slot connection mechanism is much better. Here’s how
the connection is done
sender.signalName.connect(receiver.slotName)
app = QApplication(sys.argv)
form = MyForm()
form.show()
app.exec_()
Signal and Slot
• A signal can be connected to any number of slots. In this case, the slots
are activated in arbitrary order.
• A slot may not have more arguments than the signal that is connected to
it. But may have less; the additional parameters are then discarted
import sys
from PyQt4 import QtGui
class MessageBox(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('message box')
self.button=QtGui.QPushButton('Close')
self.setCentralWidget(self.button)
self.button.clicked.connect(self.close)
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(self, 'Message',"Are you sure to quit?",
QtGui.QMessageBox.Yes,QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
app = QtGui.QApplication(sys.argv)
qb = MessageBox()
qb.show()
sys.exit(app.exec_())
Building GUI using QtDesigner
Qt Designer is the Qt tool for designing and building graphical user interfaces.
It allows you to design widgets, dialogs or complete main windows using
on-screen forms and a simple drag-and-drop interface.
It has the ability to preview your designs to ensure they work as you intended.
Building GUI using QtDesigner
Qt Designer uses XML .ui files to store designs and does not generate
any code itself.
PyQt4 includes the uic Python module.
to Python code.
The Python code is structured as a single class that is derived from the
This takes a single argument which is the widget in which the user
interface is created.
Building GUI using QtDesigner
NOTE:
To generate .py code from .ui file:
– pyuic4 filename.ui -o Ui_filename.py
To generate .py code from .qrc resource file :
– pyrcc4 -o resources_rc.py resources.qrc
To use ui interaface:
from uiMainWindow import Ui_MainWindow
class MyMainWindow(QtGui.QMainWindow):
def __init__(self,parent):
QtGui.QMainWindow.__init__(self, parent=None)
self.ui=Ui_MainWindow()
self.ui.setupUi(self)
self.ui.actionOpen.triggered.connect(self.OpenFile
Embedding Matplolib in Qt
We will see:
How to embed a Matplotlib Figure into a Qt window
NOTES:
Note that FigureCanvasQTAgg, other than being a Matplotlib class,
is also a QWidget—the base class of all user interface objects.
So this means we can treat FigureCanvasQTAgg like a pure Qt widget
Object. NavigationToolbar2QTAgg also inherits from QWidget, so it
can be used as Qt objects in a QApplication.
Example
import sys
from PyQt4 import QtGui
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main = Window()
main.show()
sys.exit(app.exec_())
Example
class Window(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog__init__(parent)
self.figure = plt.figure()
# this is the Canvas Widget that displays the `figure`
self.canvas = FigureCanvas(self.figure)
# this is the Navigation widget
self.toolbar = NavigationToolbar(self.canvas, self)
# Just some button connected to `plot` method
self.button = QtGui.QPushButton('Plot')
self.button.clicked.connect(self.plot)
# set the layout
layout = QtGui.QVBoxLayout()
layout.addWidget(self.toolbar)
layout.addWidget(self.canvas)
layout.addWidget(self.button)
self.setLayout(layout)
Example
def plot(self):
# random data
data = [random.random() for i in range(10)]
# create an axis
ax = self.figure.add_subplot(111)
# discards the old graph
ax.hold(False)
# plot data
ax.plot(data, '*-')
# refresh canvas
self.canvas.draw()
Embedding Matplolib with
QtDesigner
Embedding VTK in Qt
QVTKRenderWindowInteractor uses a
vtkGenericRenderWindowInteractor to handle the
interactions and it uses GetRenderWindow() to get the
vtkRenderWindow.
Embedding VTK in Qt: Example
from PyQt4 import QtGui
from vtk.qt4.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
import vtk
import sys
from Ui_MainWindowVtk import Ui_MainWindow
if __name__=='__main__':
app = QtGui.QApplication(['QVTKRenderWindowInteractor'])
window=MyMainWindow()
window.show()
sys.exit(app.exec_())
30/05/13
Embedding VTK in Qt: Example
class MyMainWindow(QtGui.QMainWindow):
def __init__(self,parent=None):
QtGui.QMainWindow.__init__(self)
self.ui=Ui_MainWindow()
self.ui.setupUi(self)
self.widget=QVTKRenderWindowInteractor(self)
self.widget.Initialize()
self.widget.Start()
self.widget.show()
self.setCentralWidget(self.widget)
self.ui.actionCone.triggered.connect(self.addCone)
self.ui.actionCube.triggered.connect(self.addCube)
self.ui.actionOpen.triggered.connect(self.addFig)
30/05/13
Embedding VTK in Qt: Example
def addFig(self):
filename=QtGui.QFileDialog.getOpenFileName(self,'Open vtp','.',"Document files (*.vtp);;All
files (*.*)")
reader = vtk.vtkXMLPolyDataReader()
reader.SetFileName(str(filename))
reader.Update()
ren = vtk.vtkRenderer()
self.widget.GetRenderWindow().AddRenderer(ren)
mapper = vtk.vtkPolyDataMapper()
mapper.SetInput(reader.GetOutput())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
ren.AddActor(actor)
def addCone(self):
ren = vtk.vtkRenderer()
self.widget.GetRenderWindow().AddRenderer(ren)
cone = vtk.vtkConeSource()
cone.SetResolution(8)
coneMapper = vtk.vtkPolyDataMapper()
coneMapper.SetInputConnection(cone.GetOutputPort())
coneActor = vtk.vtkActor()
coneActor.SetMapper(coneMapper)
ren.AddActor(coneActor)
30/05/13
Embedding VTK in Qt: Example
def addCube(self):
ren = vtk.vtkRenderer()
self.widget.GetRenderWindow().AddRenderer(ren)
cube = vtk.vtkCubeSource()
cube = vtk.vtkCubeSource()
cube.SetXLength(200)
cube.SetYLength(200)
cube.SetZLength(200)
cube.Update()
cubeMapper = vtk.vtkPolyDataMapper()
cubeMapper.SetInputConnection(cube.GetOutputPort())
cubeActor = vtk.vtkActor()
cubeActor.SetMapper(cubeMapper)
ren.AddActor(cubeActor)
ren.ResetCamera()
30/05/13