0
votes

I am using a QToolButton to open up a menu, which is a simple QWidget. Inside this widget live a QTextEdit and a Button. At the lower right corner there is a QSizeGrip which I want to use to let the user resize the widget and thus the QTextEdit.

If I use this widget on its own inside a MainWindow (Option1) everything works as expected. If however I put this widget into the menu (Option2), I cannot resize it anymore. Dragging the QSizeGrip changes the size of the Menu but not the Widget. I have already experimented with setWindowFlags(QtCore.Qt.SubWindow) and setSizePolicy(..) without any notable effect.

My Question is: How do I make the widget (together with the TextEdit) resizable?

Here is the code and below a picture.

import sys
from PyQt4 import QtGui, QtCore

class MyWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        super(MyWidget, self).__init__(parent)

        self.setLayout(QtGui.QVBoxLayout())
        self.TextEdit = QtGui.QTextEdit()

        self.Button = QtGui.QPushButton("Push")

        self.UpdateWidget = QtGui.QWidget()
        self.UpdateWidget.setLayout(QtGui.QHBoxLayout())
        self.UpdateWidget.layout().addWidget(self.Button, 1)
        self.UpdateWidget.layout().addWidget(QtGui.QSizeGrip(self), 0)

        self.layout().addWidget(self.TextEdit)
        self.layout().addWidget(self.UpdateWidget)

        self.layout().setSpacing(0)
        self.layout().setContentsMargins(0,0,0,0)
        self.UpdateWidget.layout().setSpacing(4)
        self.UpdateWidget.layout().setContentsMargins(0,0,0,0)

        # This is what I already tried to make the menu resizable:
        #self.setWindowFlags(QtCore.Qt.SubWindow)
        #self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        #self.TextEdit.setWindowFlags(QtCore.Qt.SubWindow)
        #self.TextEdit.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)


class ToolBar(QtGui.QWidget):
    def __init__(self, parent=None):
        super(ToolBar, self).__init__(parent)
        self.setLayout(QtGui.QHBoxLayout())
        self.Button = QtGui.QToolButton()
        self.Button.setText("Open Text Editor")
        self.Button.setPopupMode(QtGui.QToolButton.InstantPopup)
        self.Button.setMenu(QtGui.QMenu(self.Button))
        action = QtGui.QWidgetAction(self.Button)
        action.setDefaultWidget(MyWidget())
        self.Button.menu().addAction(action)
        self.layout().addWidget(self.Button)


class App(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(App, self).__init__(parent)

        #Option 1: 
        #Use MyWidget in MainWindow. This works as expected.
        #self.central = MyWidget()

        #Option 2:
        #Use MyWidget as default widgt for a menu action. 
        #In this case MyWidget cannot be resized.
        self.central = ToolBar()

        self.setCentralWidget(self.central)


if __name__=='__main__':
    app = QtGui.QApplication(sys.argv)
    thisapp = App()
    thisapp.show()
    sys.exit(app.exec_())

enter image description here

1

1 Answers

2
votes

Problem is because Button.menu doesn't inform your widget about size change.

In ToolBar you can assign own function to resizeEvent which will resize your widget.

You need access to your widget

    self.MyW = MyWidget()

and you can assign own function

    self.Button.menu().resizeEvent = self.onResize

def onResize(self, event):        
    self.MyW.resize(event.size())

Full code:

import sys
from PyQt4 import QtGui, QtCore

class MyWidget(QtGui.QWidget):

    def __init__(self, parent=None):
        super(MyWidget, self).__init__(parent)    
        self.setLayout(QtGui.QVBoxLayout())

        self.TextEdit = QtGui.QTextEdit()

        self.Button = QtGui.QPushButton("Push")

        self.UpdateWidget = QtGui.QWidget()
        self.UpdateWidget.setLayout(QtGui.QHBoxLayout())
        self.UpdateWidget.layout().addWidget(self.Button, 1)
        self.UpdateWidget.layout().addWidget(QtGui.QSizeGrip(self), 0)

        self.layout().addWidget(self.TextEdit)
        self.layout().addWidget(self.UpdateWidget)

        self.layout().setSpacing(0)
        self.layout().setContentsMargins(0,0,0,0)
        self.UpdateWidget.layout().setSpacing(4)
        self.UpdateWidget.layout().setContentsMargins(0,0,0,0)


class ToolBar(QtGui.QWidget):

    def __init__(self, parent=None):
        super(ToolBar, self).__init__(parent)
        self.setLayout(QtGui.QHBoxLayout())

        self.Button = QtGui.QToolButton()
        self.Button.setText("Open Text Editor")
        self.Button.setPopupMode(QtGui.QToolButton.InstantPopup)
        self.Button.setMenu(QtGui.QMenu(self.Button))

        self.MyW = MyWidget() # <-- here
        action = QtGui.QWidgetAction(self.Button) 
        action.setDefaultWidget(self.MyW) # <-- here

        self.Button.menu().addAction(action)
        self.layout().addWidget(self.Button)

        self.Button.menu().resizeEvent = self.onResize # <-- here

    def onResize(self, event):        # <-- here
        self.MyW.resize(event.size()) # <-- here

class App(QtGui.QMainWindow):

    def __init__(self, parent=None):
        super(App, self).__init__(parent)

        #Option 1: 
        #Use MyWidget in MainWindow. This works as expected.
        #self.central = MyWidget()

        #Option 2:
        #Use MyWidget as default widgt for a menu action. 
        #In this case MyWidget cannot be resized.
        self.central = ToolBar()

        self.setCentralWidget(self.central)


if __name__=='__main__':
    app = QtGui.QApplication(sys.argv)
    thisapp = App()
    thisapp.show()
    sys.exit(app.exec_())

Maybe it can be done olny with SizeGrip and MyWidget but I didn't try