Qt is a C++ cross-platform application and user-interface framework. It is developed by Nokia and contains a comprehensive library of GUI classes.
Using the visual editor “Qt Designer” GUIs are easily created and maintained.
This notebook describes a simple method to integrate Qt GUIs in Python programs using PyQt and the Python module QtGuiLoader
.
In Example 1 a simple but flexible widget is created. It can be used as Widget, Dialog or MainWindow.
In Exercise 1 the widget is extended with more stuff to control a plot
Install a distribution, e.g. Pythonxy, winpython or Anaconda
or
Install Python 2.7, Qt4 (including QtDesigner), and PyQt4 (alternatively PySide)
In this example a simple but flexible widget is created. It can be used as Widget, Dialog or MainWindow (Menubar, toolbar and statusbar cannot be added to this widget).
"Horizontal Layout"
from the "Widget Box" and drop it on the Form"LineEdit"
to layout"PushButton"
to layout next to the "LineEdit"
pushButton
clicked()
actionPrintText
trigger()
MyUI/MyWidgetUI.ui
" in the same folder as this notebookMyUI/MyWidgetUI.py
" file in the same folder (This is required in order to import the widget. Its content will be autogenerated if the file is completely empty or older than "MyUI/MyWidgetUI.ui
")The widget can be integrated as QMainWindow
, QDialog
or QWidget
.
QMainWindow
is a separate window, i.e. two main windows can be closed independently. QDialog
is a sub window, i.e. if its parent window is closed the dialog is closed too. A dialog may be modal, such that other windows cannot be operated before the dialog is closed. QWidget
can be inserted into an existing widget or layout.In order to use it, subclass QtMainWindowLoader
, QtDialogLoader
or QtWidgetLoader
from QtGuiLoader
and instantiate with MyUI.MyWidgetUI
as ui_module argument.
When using QtGuiLoader
, actions are by default connected to methods with the same name.
All PyQt elements are found in the self.ui
-object, e.g. self.ui.lineEdit
and documentation of the PyQt elements is found at http://pyqt.sourceforge.net/Docs/PyQt4/classes.html
In the following script, MYWidgetUI
is used as a QMainWindow
. Run it using Shift-Enter.
A new window will open and the text in the QLineEdit
will be printet when clicking the QPushButton
In [ ]:
import MyUI.MyWidgetUI
from QtGuiLoader import QtMainWindowLoader
class MyMainWindow(QtMainWindowLoader):
def __init__(self):
QtMainWindowLoader.__init__(self, ui_module=MyUI.MyWidgetUI)
def actionPrintText(self):
print "Mainwindow text: %s"%str(self.ui.lineEdit.text())
print #required to print at first click (only when running as IPython Notebook)
MyMainWindow().start()
In the following example MyWidgetUI
is reused as both QMainWindow
, QDialog
and QWidget
.
On some platforms you need to close the window opened in the previous script before running the next script
In [ ]:
from QtGuiLoader import QtMainWindowLoader, QtDialogLoader, QtWidgetLoader
import MyUI.MyWidgetUI
from PyQt4 import QtGui
class MyMainWindow(QtMainWindowLoader):
def __init__(self):
QtMainWindowLoader.__init__(self, ui_module=MyUI.MyWidgetUI)
self.setWindowTitle("Mainwindow")
#Add as QWidget
self.ui.horizontalLayout.addWidget(MyWidget(self))
#Add button that opens as QDialog
self.ui.horizontalLayout.addWidget(QtGui.QPushButton("Open dialog", self, clicked=self.open_dialog))
def open_dialog(self):
#open as QDialog
MyDialog(parent=self,modal=True).start()
def actionPrintText(self):
print "Mainwindow text: %s"%self.ui.lineEdit.text()
class MyDialog(QtDialogLoader):
def __init__(self,parent,modal):
QtDialogLoader.__init__(self, MyUI.MyWidgetUI, parent, modal)
self.setWindowTitle("Dialog")
def actionPrintText(self):
print "Dialog text: %s"%self.ui.lineEdit.text()
class MyWidget(QtWidgetLoader):
def __init__(self, parent):
QtWidgetLoader.__init__(self, ui_module=MyUI.MyWidgetUI, parent=parent)
self.show()
def actionPrintText(self):
print "Widget text: %s"%str(self.ui.lineEdit.text())
print #required to print at first click (only when running as IPython Notebook)
MyMainWindow().start()
Add "Form Layout"
to "Form"
x:
formLayout
and add an entry for x:QLineEdit
(default)xLineEdit
and set properties in Property editor:y:
QLineEdit
(default) yxLineEdit
and set properties in Property editor:Color:
formLayout
again and add entry for color:QComboBox
colorComboBox
and add three items:Width:
formLayout
again and add entry for width:QLineEdit
(default) widthLineEdit
(The one you just added)"Horizontal Layout"
"Horizontal Slider"
to horizontal layouthorizontalSlider
and set properties in Property editor:"Label"
next to horizontalSlider
formLayout
again and add entry for yLim:QLineEdit
(default) yLimLineEdit
(The one you just added)"Horizontal Layout"
"Spin Box"
to horizontal layoutspinBox
and set properties in Property editor:Label
next to spinBox
alignHCenter
"Double Spin Box"
next to labeldoubleSpinBox
and set properties in Property editor:Sender | Signal | Receiver | Slot |
`xLineEdit` | editingFinished() | acitonUpdatePlot | trigger() |
`yLineEdit` | editingFinished() | acitonUpdatePlot | trigger() |
`colorComboBox` | currentIndexChanged(int) | acitonUpdatePlot | trigger() |
`horizontalSlider` | sliderReleased() | acitonUpdatePlot | trigger() |
`spinBox` | valueChanged(int) | acitonUpdatePlot | trigger() |
`doubleSpinBox` | valueChanged(double) | acitonUpdatePlot | trigger() |
MyUI/MyPlotControlUI.ui
" in the same folder as this notebookMyUI/MyPlotcontrolUI.py
" file in the same folder (This is required in order to import the widget. Its content will be autogenerated if the file is completely empty or older than "MyUI/MyPlotControlUI.ui
")Hints:
self.ui.yLineEdit
. The text must be converted to a string using str(x)QAbstractSlider
(super class of QSlider
). See link in top of the QSlider
documentationspinBox
and the upper bound from doubleSpinBox
Run again
In [ ]:
import MyUI.MyPlotControlUI
from QtGuiLoader import QtMainWindowLoader
import numpy as np
import matplotlib.pyplot as plt
class MyPlotControlMainWindow(QtMainWindowLoader):
def __init__(self):
try: self.ui = MyUI.MyPlotControlUI.Ui_Form() # Enables autocompletion (maybe...)
except: pass
QtMainWindowLoader.__init__(self, ui_module=MyUI.MyPlotControlUI)
#Connect widget signals to actionUpdatePlot
self.ui.xLineEdit.editingFinished.connect(self.actionUpdatePlot)
self.ui.yLineEdit.editingFinished.connect(self.actionUpdatePlot)
self.ui.colorComboBox.currentIndexChanged.connect(self.actionUpdatePlot)
self.ui.horizontalSlider.valueChanged.connect(self.actionUpdatePlot)
self.ui.spinBox.valueChanged.connect(self.actionUpdatePlot)
self.ui.doubleSpinBox.valueChanged.connect(self.actionUpdatePlot)
self.actionUpdatePlot()
x_str = property(lambda self : str(self.ui.xLineEdit.text()))
y_str = property(lambda self : "x")
color = property(lambda self : 'Red')
width = property(lambda self : 1)
ylim = property(lambda self : (0,10))
def actionUpdatePlot(self):
print (self.x_str, self.y_str, self.color, self.width, self.ylim)
MyPlotControlMainWindow().start()
In [ ]: