From 4e9e75817fb0d2b5f6880278857621af30d7d0f1 Mon Sep 17 00:00:00 2001 From: Luke Campagnola Date: Tue, 17 Dec 2013 21:23:37 -0500 Subject: [PATCH] Added Qt.loadUiType function for PySide Added example of simple Designer usage. --- examples/designerExample.py | 46 ++++++++++++++++++++++++++++++++ examples/designerExample.ui | 38 +++++++++++++++++++++++++++ pyqtgraph/Qt.py | 52 ++++++++++++++++++++++++++++++++++--- 3 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 examples/designerExample.py create mode 100644 examples/designerExample.ui diff --git a/examples/designerExample.py b/examples/designerExample.py new file mode 100644 index 00000000..812eff6b --- /dev/null +++ b/examples/designerExample.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +""" +Simple example of loading UI template created with Qt Designer. + +This example uses uic.loadUiType to parse and load the ui at runtime. It is also +possible to pre-compile the .ui file using pyuic (see VideoSpeedTest and +ScatterPlotSpeedTest examples; these .ui files have been compiled with the +tools/rebuildUi.py script). +""" +import initExample ## Add path to library (just for examples; you do not need this) + +import pyqtgraph as pg +from pyqtgraph.Qt import QtCore, QtGui +import numpy as np +import os + +pg.mkQApp() + +## Define main window class from template +path = os.path.dirname(os.path.abspath(__file__)) +uiFile = os.path.join(path, 'designerExample.ui') +WindowTemplate, TemplateBaseClass = pg.Qt.loadUiType(uiFile) + +class MainWindow(TemplateBaseClass): + def __init__(self): + TemplateBaseClass.__init__(self) + self.setWindowTitle('pyqtgraph example: Qt Designer') + + # Create the main window + self.ui = WindowTemplate() + self.ui.setupUi(self) + self.ui.plotBtn.clicked.connect(self.plot) + + self.show() + + def plot(self): + self.ui.plot.plot(np.random.normal(size=100), clear=True) + +win = MainWindow() + + +## Start Qt event loop unless running in interactive mode or using pyside. +if __name__ == '__main__': + import sys + if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): + QtGui.QApplication.instance().exec_() diff --git a/examples/designerExample.ui b/examples/designerExample.ui new file mode 100644 index 00000000..41d06089 --- /dev/null +++ b/examples/designerExample.ui @@ -0,0 +1,38 @@ + + + Form + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + Plot! + + + + + + + + + + + PlotWidget + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/pyqtgraph/Qt.py b/pyqtgraph/Qt.py index e584a381..410bfd83 100644 --- a/pyqtgraph/Qt.py +++ b/pyqtgraph/Qt.py @@ -1,4 +1,14 @@ -## Do all Qt imports from here to allow easier PyQt / PySide compatibility +""" +This module exists to smooth out some of the differences between PySide and PyQt4: + +* Automatically import either PyQt4 or PySide depending on availability +* Allow to import QtCore/QtGui pyqtgraph.Qt without specifying which Qt wrapper + you want to use. +* Declare QtCore.Signal, .Slot in PyQt4 +* Declare loadUiType function for Pyside + +""" + import sys, re ## Automatically determine whether to use PyQt or PySide. @@ -23,8 +33,41 @@ if USE_PYSIDE: from PySide import QtGui, QtCore, QtOpenGL, QtSvg import PySide VERSION_INFO = 'PySide ' + PySide.__version__ + + # Make a loadUiType function like PyQt has + + # Credit: + # http://stackoverflow.com/questions/4442286/python-code-genration-with-pyside-uic/14195313#14195313 + + def loadUiType(uiFile): + """ + Pyside "loadUiType" command like PyQt4 has one, so we have to convert the ui file to py code in-memory first and then execute it in a special frame to retrieve the form_class. + """ + import pysideuic + import xml.etree.ElementTree as xml + from io import StringIO + + parsed = xml.parse(uiFile) + widget_class = parsed.find('widget').get('class') + form_class = parsed.find('class').text + + with open(uiFile, 'r') as f: + o = StringIO() + frame = {} + + pysideuic.compileUi(f, o, indent=0) + pyc = compile(o.getvalue(), '', 'exec') + exec(pyc, frame) + + #Fetch the base_class and form class based on their type in the xml from designer + form_class = frame['Ui_%s'%form_class] + base_class = eval('QtGui.%s'%widget_class) + + return form_class, base_class + + else: - from PyQt4 import QtGui, QtCore + from PyQt4 import QtGui, QtCore, uic try: from PyQt4 import QtSvg except ImportError: @@ -34,6 +77,9 @@ else: except ImportError: pass + + loadUiType = uic.loadUiType + QtCore.Signal = QtCore.pyqtSignal VERSION_INFO = 'PyQt4 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR @@ -43,6 +89,6 @@ versionReq = [4, 7] QtVersion = PySide.QtCore.__version__ if USE_PYSIDE else QtCore.QT_VERSION_STR m = re.match(r'(\d+)\.(\d+).*', QtVersion) if m is not None and list(map(int, m.groups())) < versionReq: - print(map(int, m.groups())) + print(list(map(int, m.groups()))) raise Exception('pyqtgraph requires Qt version >= %d.%d (your version is %s)' % (versionReq[0], versionReq[1], QtVersion))