I followed this explanation by Nathan Horne and built an inheritable class for loading .ui files and compiling them at runtime quite a while ago.
Also I found this neat way of writing singletons.
So here’s a class that takes a UI file, compiles it and shows its contents.
''' @Author: Trevor van Hoof UIC compiler at runtime Inherit uicWindow and give it a ui file to open Reloading the import of uicr will also recompile the UI file, showing new changes. ''' import os.path from PyQt4 import uic, QtGui ''' Generic PyQt window class which can be inherited from for quick window creation ''' class UicWindow(object): ''' Uses the uic compiler at runtime, so any QtDesigner file gets updated immediately The created QtWindow object is named after the file given (without extension) When creating multiple instances of the same .ui file it may be wise to manually rename by using the
.window.setWindowTitle() function @param in_parent The window this widget is parented to -> widgets get embedded in main -> dockwidgets can dock to main -> mainWindows get closed when main gets closed @param in_uifile The QtDesigner ui file to load, best is to use an absolute path to avoid problems with import and inheritance @param in_customtitle QtDesigner permits windows and widgets to be named, but it is also possible to set or change the name using script, this is supported so multiple copies of the same input can be differently named ''' def __init__(self,in_parent,in_uifile,in_customtitle=None): window_class = uic.loadUiType(in_uifile) ''' The uic returns both a form class with other functionality and a QWidget with the designer file objects Both functionalities are required and are therefore packed together through inheritance in this embedded class which serves no other purpose than combining data ''' class QtWindow(window_class,window_class): def __init(self): pass self.window = QtWindow() super(QtWindow, self.window).__init__(in_parent) self.window.setupUi(self.window) self.window.setObjectName(os.path.splitext(os.path.basename(in_uifile))) if in_customtitle is not None: self.window.setWindowTitle(in_customtitle) self.window.show() def snapToCenter(self): if self.window.parent() != None: core = self.window.parent().geometry().center() else: core = QtGui.QDesktopWidget().screen().geometry().center() geo = self.window.geometry() self.window.setGeometry( core.x()-geo.width()*0.5, core.y()-geo.height()*0.5, geo.width(), geo.height() ) def resizeAndCenter(self, in_size): self.window.resize(in_size) self.snapToCenter() def __del__(self): try: self.window.close() except: pass
And here’s a usage example; note that the ui file must exist.
import Qtutils.uicr from Qtutils.LaunchAsStandalone import * from PyQt4 import QtCore, QtGui class MainWindow(Qtutils.uicr.UicWindow): def __init__(self): #act like a singleton, any future function call will return this instance globals()[self.__class__.__name__] = self #get a file next to this file self.filepath = __file__.replace('\\','/').rsplit('/',1) filename = ('%s/main.ui'%self.filepath) #and load it as a UI file, parent defaults to None Qtutils.uicr.UicWindow.__init__(self, None, filename) ''' Makes sure the singleton instance is callable ''' def __call__(self): return self #main function to launch as standalone app for unit-tests def main(): w = MainWindow() w.resizeAndCenter( QtCore.QSize(180,220) ) return w QtStandalone(main)
By removing the first line in __init__:
globals()[self.__class__.__name__] = self
The class is no longer a singleton, this may be desirable while frequently updating the ui file as it won’t be reimported unless the class is reinitialized.