Qt add a widget inside another widget?

Viewed 11182

I'd like to make a single widget that combines the behavior of two existing widgets. For example a widget that is a button that also contains a checkbox. The user can click the larger button but also the checkbox within.

E.g. gmail introduced a "select-all" button that displays a menu on click, but it also integrates a checkbox that selects all email. See this screenshot for an example:
enter image description here


How would one go about combining behaviors of existing widgets to this effect? I'm hoping for a solution where widget behaviors can be combined and I only need to override where they conflict.

This question is similar to the Combine multiple widgets into one in qt question but differs in that I want the two widgets to be placed on top of each other and appear as one widget.

In response to cbamber85's reply I've added the code below to show how far I've managed to integrate the replies. As with cbamber85's reply this contains no real functionality, it's just the PyQT version of his code.

from PyQt4 import QtCore, QtGui

class CheckBoxButton(QtGui.QWidget):
    checked = QtCore.pyqtSignal(bool)

    def __init__(self, *args):
        QtGui.QWidget.__init__(self, *args)
        self._isdown = False
        self._ischecked = False

    def isChecked(self):
        return self._ischecked

    def setChecked(self, checked):
        if self._ischecked != checked:
            self._ischecked = checked
            self.checked.emit(checked)

    def sizeHint(self, *args, **kwargs):
        QtGui.QWidget.sizeHint(self, *args, **kwargs)
        return QtCore.QSize(128,128)

    def paintEvent(self, event):
        p = QtGui.QPainter(self)
        butOpt = QtGui.QStyleOptionButton()
        butOpt.initFrom(self)
        butOpt.state = QtGui.QStyle.State_Enabled
        butOpt.state |= QtGui.QStyle.State_Sunken if self._isdown else QtGui.QStyle.State_Raised

        self.style().drawControl(QtGui.QStyle.CE_PushButton, butOpt, p, self)

        chkBoxWidth = self.style().pixelMetric(QtGui.QStyle.PM_CheckListButtonSize,
                                               butOpt, self) / 2
        butOpt.rect.moveTo((self.rect().width() / 2) - chkBoxWidth, 0)

        butOpt.state |= QtGui.QStyle.State_On if self._ischecked else QtGui.QStyle.State_Off
        self.style().drawControl(QtGui.QStyle.CE_CheckBox, butOpt, p, self)

    def mousePressEvent(self, event):
        self._isdown = True
        self.update()

    def mouseReleaseEvent(self, event):
        self.setChecked(not self.isChecked())
        self._isdown = False
        self.update()


class Dialog(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        widg = CheckBoxButton(self)
        self.setCentralWidget(widg)


if __name__ == '__main__':
    app = QtGui.QApplication([])
    window = Dialog()
    window.show()
    app.exec_()
2 Answers
Related