Qt Designer promoted widget layout
Question: I am using Qt Designer for designing my user interfaces, and I want to build
custom widgets which could be a combination of existing qt widgets such as a
QLabel and QPushButton attached screenshot

[![enter image description
here](http://i.stack.imgur.com/flgxH.png)](http://i.stack.imgur.com/flgxH.png).

Now I would like this to be independent with it's own business logic, signals
and slots in a separate python file, but would want to add this as a component
to my main screen.

I tried above by creating seprate ui file of type widget, but when I promote
that from my MainWindow, it won't show up, and the code generated by pyuic
would add it to the layout, but it is not rendered in main window.

[![enter image description
here](http://i.stack.imgur.com/jklDD.png)](http://i.stack.imgur.com/jklDD.png)

Is there a way of doing that in PyQt and QDesigner?

**EDIT** :

Here is the actual code:

_timer.py_ :

    
    
    from PyQt4 import QtGui, QtCore
    from datetime import timedelta, datetime
    
    from logbook import info
    
    
    import timer_ui
    
    
    class Timer(QtGui.QWidget, timer_ui.Ui_TimerWidget):
    
        start_time = None
        running = False
        total_time = 0
        time_spent = ''
    
        activity = None
    
        stopwatch = 0
        elapsed_time = None
        total_elapsed_time = timedelta()
    
        def __init__(self, parent=None):
            super(self.__class__, self).__init__(parent)
    
            self.setupUi(parent) #for custom widget parent is main window here which is dashboard
    
            self.lcdNumber.setDigitCount(12)
    
            self.qt_timer = QtCore.QTimer(self)
            self.qt_timer.timeout.connect(self.timer_event)
            self.qt_timer.start(1000)
    
            self.goButton.clicked.connect(self.go)
            self.breakButton.clicked.connect(self.break_timer)
    
        def go(self):
            # date text format .strftime('%a, %d %b %Y %H:%M:%S')
            self.start_time = datetime.now().replace(microsecond=0)
            self.running = True
    
    
    
    
            self.goButton.setEnabled(False)
            self.breakButton.setEnabled(True)
    
        def break_timer(self):
            ''' break finishes the activity '''
            break_time = datetime.now().replace(microsecond=0)
            self.activity.log_break(break_time.isoformat())
            self.activity = None  # activity completed
    
            self.total_elapsed_time += self.elapsed_time
            info(self.total_elapsed_time)
    
            self.running = False
    
    
            # self.lcdNumber.display(str(self.timer.get_elapsed()))
    
            self.goButton.setEnabled(True)
            self.breakButton.setEnabled(False)
    
    
        def timer_event(self):
            '''Updates the widget every second'''
    
            if self.running == True:
                current_time = datetime.now().replace(microsecond=0)
    
                # if self.elapsed_time is None:
    
                self.elapsed_time = current_time - self.start_time
                # else:
                #self.elapsed_time += current_time - self.timer.start_time.replace(microsecond=0)
                if self.total_elapsed_time is not None:
                     self.lcdNumber.display(str(self.elapsed_time + self.total_elapsed_time))
                else:
                    self.lcdNumber.display(str(self.elapsed_time))
    

_mainwindow.py_ :

    
    
    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'dashboard.ui'
    #
    # Created: Sat Mar 19 11:40:35 2016
    #      by: PyQt4 UI code generator 4.10.4
    #
    # WARNING! All changes made in this file will be lost!
    
    from PyQt4 import QtCore, QtGui
    
    try:
        _fromUtf8 = QtCore.QString.fromUtf8
    except AttributeError:
        def _fromUtf8(s):
            return s
    
    try:
        _encoding = QtGui.QApplication.UnicodeUTF8
        def _translate(context, text, disambig):
            return QtGui.QApplication.translate(context, text, disambig, _encoding)
    except AttributeError:
        def _translate(context, text, disambig):
            return QtGui.QApplication.translate(context, text, disambig)
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName(_fromUtf8("MainWindow"))
            MainWindow.resize(772, 421)
            self.centralwidget = QtGui.QWidget(MainWindow)
            self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
            self.verticalLayout = QtGui.QVBoxLayout()
            self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
            self.widget = Timer(self.centralwidget)
    
            self.verticalLayout.addWidget(self.widget)
    
            self.horizontalLayout = QtGui.QHBoxLayout()
    
            self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
            self.userNameLabel = QtGui.QLabel(self.centralwidget)
            self.userNameLabel.setObjectName(_fromUtf8("userNameLabel"))
            self.horizontalLayout.addWidget(self.userNameLabel)
            self.logoutButton = QtGui.QPushButton(self.centralwidget)
            self.logoutButton.setEnabled(True)
            self.logoutButton.setObjectName(_fromUtf8("logoutButton"))
            self.horizontalLayout.addWidget(self.logoutButton)
    
            self.verticalLayout.addLayout(self.horizontalLayout)
    
            self.listView = QtGui.QListView(self.centralwidget)
            self.listView.setObjectName(_fromUtf8("listView"))
            self.verticalLayout.addWidget(self.listView)
            MainWindow.setCentralWidget(self.centralwidget)
            self.statusbar = QtGui.QStatusBar(MainWindow)
            self.statusbar.setObjectName(_fromUtf8("statusbar"))
            MainWindow.setStatusBar(self.statusbar)
            self.menuBar = QtGui.QMenuBar(MainWindow)
            self.menuBar.setGeometry(QtCore.QRect(0, 0, 772, 23))
            self.menuBar.setObjectName(_fromUtf8("menuBar"))
            MainWindow.setMenuBar(self.menuBar)
    
            self.retranslateUi(MainWindow)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
        def retranslateUi(self, MainWindow):
            MainWindow.setWindowTitle(_translate("MainWindow", "Title", None))
            self.userNameLabel.setText(_translate("MainWindow", "You are now logged in as", None))
            self.logoutButton.setText(_translate("MainWindow", "Logout", None))
    
    from timer import Timer
    

_timer_ui.py_ :

    
    
    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'timer.ui'
    #
    # Created: Sat Mar 19 11:41:40 2016
    #      by: PyQt4 UI code generator 4.10.4
    #
    # WARNING! All changes made in this file will be lost!
    
    from PyQt4 import QtCore, QtGui
    
    try:
        _fromUtf8 = QtCore.QString.fromUtf8
    except AttributeError:
        def _fromUtf8(s):
            return s
    
    try:
        _encoding = QtGui.QApplication.UnicodeUTF8
        def _translate(context, text, disambig):
            return QtGui.QApplication.translate(context, text, disambig, _encoding)
    except AttributeError:
        def _translate(context, text, disambig):
            return QtGui.QApplication.translate(context, text, disambig)
    
    class Ui_TimerWidget(object):
        def setupUi(self, TimerWidget):
            TimerWidget.setObjectName(_fromUtf8("TimerWidget"))
            TimerWidget.resize(412, 52)
            self.horizontalLayout = QtGui.QHBoxLayout(TimerWidget)
            self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
            self.label = QtGui.QLabel(TimerWidget)
            self.label.setObjectName(_fromUtf8("label"))
            self.horizontalLayout.addWidget(self.label)
            self.lcdNumber = QtGui.QLCDNumber(TimerWidget)
            self.lcdNumber.setAutoFillBackground(False)
            self.lcdNumber.setNumDigits(12)
            self.lcdNumber.setSegmentStyle(QtGui.QLCDNumber.Flat)
            self.lcdNumber.setObjectName(_fromUtf8("lcdNumber"))
            self.horizontalLayout.addWidget(self.lcdNumber)
            self.goButton = QtGui.QPushButton(TimerWidget)
            self.goButton.setObjectName(_fromUtf8("goButton"))
            self.horizontalLayout.addWidget(self.goButton)
            self.breakButton = QtGui.QPushButton(TimerWidget)
            self.breakButton.setObjectName(_fromUtf8("breakButton"))
            self.horizontalLayout.addWidget(self.breakButton)
    
            self.retranslateUi(TimerWidget)
            #QtCore.QMetaObject.connectSlotsByName(TimerWidget)
    
        def retranslateUi(self, TimerWidget):
            #TimerWidget.setWindowTitle(_translate("TimerWidget", "Form", None))
            self.label.setText(_translate("TimerWidget", "Total hours spent", None))
            self.goButton.setText(_translate("TimerWidget", "Go!", None))
            self.breakButton.setText(_translate("TimerWidget", "Break", None))
    


Answer: Promoted widgets are just placeholders for standard Qt widgets. You cannot
create a custom widget for Qt Designer that way.

It can be done, but the process is much more complicated than simple widget
promotion. See [Writing Qt Designer
Plugins](http://pyqt.sourceforge.net/Docs/PyQt4/designer.html#writing-qt-
designer-plugins) in the PyQt docs, and for a detailed tutorial, see [Using
Python Custom Widgets In Qt
Designer](http://wiki.python.org/moin/PyQt/Using_Python_Custom_Widgets_in_Qt_Designer)
on the Python Wiki. The [PyQt source
code](http://www.riverbankcomputing.com/software/pyqt/download) also has many
more examples (look in _examples/designer/plugins_).

**EDIT** :

There are two problems with your code. Firstly, you are passing the wrong
argument to `setupUi` in the `Timer` class. You should fix it like this:

    
    
    class Timer(QtGui.QWidget, timer_ui.Ui_TimerWidget):
        ...
        def __init__(self, parent=None):
            super(Timer, self).__init__(parent)
            self.setupUi(self) # pass in self, not parent
    

Secondly, you edited the _mainwindow.py_ file and broke one of the layouts.
Never, **_ever_** edit the modules generated by `pyuic`! The line you broke is
this one:

    
    
            # self.verticalLayout = QtGui.QVBoxLayout()
            self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
    

But don't try to fix this by editing - instead, make sure you _regenerate_ all
the ui modules with `pyuic` so you get back to clean, unedited files again.

