PyQt — изменение размера виджета меню вручную не приводит к изменению размера его содержимого

#qt #user-interface #pyqt #pyqt4

#qt #пользовательский интерфейс #pyqt #pyqt4

Вопрос:

Я использую QToolButton для открытия меню, которое представляет собой простой QWidget. Внутри этого виджета находятся QTextEdit и кнопка. В правом нижнем углу есть QSizeGrip, который я хочу использовать, чтобы позволить пользователю изменять размер виджета и, следовательно, QTextEdit.

Если я использую этот виджет самостоятельно внутри MainWindow (опция 1), все работает так, как ожидалось. Однако, если я помещу этот виджет в меню (опция 2), я больше не смогу изменять его размер. Перетаскивание QSizeGrip изменяет размер меню, но не виджета. Я уже экспериментировал с setWindowFlags(QtCore.Qt.SubWindow) и setSizePolicy(..) без какого-либо заметного эффекта.

Мой вопрос: как мне изменить размер виджета (вместе с TextEdit)?

Вот код и изображение под ним.

 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_())
  

введите описание изображения здесь

Ответ №1:

Проблема в том, что Button.menu не сообщает вашему виджету об изменении размера.

На панели инструментов вы можете назначить собственную функцию, resizeEvent которая изменит размер вашего виджета.

Вам нужен доступ к вашему виджету

     self.MyW = MyWidget()
  

и вы можете назначить собственную функцию

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

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

Полный код:

 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_())
  

Возможно, это можно сделать с помощью SizeGrip и MyWidget , но я не пробовал