QMenu
正确显示包含具有自己尺寸的QWidgetAction
的QWidget
,但是当菜单被撕下(并成为独立窗口)时,事情就会出错。窗口大小可正确显示使用 addAction(str)
添加的任何操作,但 QWidgetAction
的 QWidget
几乎完全隐藏。
此代码重现了问题:
#!/usr/bin/env python
from PySide2 import QtCore, QtWidgets
def main():
app = QtWidgets.QApplication()
window = QtWidgets.QWidget()
layout = QtWidgets.QHBoxLayout()
window.setLayout(layout)
button = QtWidgets.QPushButton("Push Me")
menu = QtWidgets.QMenu()
menu.setTearOffEnabled(True)
menu.addAction("Ok")
qwa = QtWidgets.QWidgetAction(menu)
big_button = QtWidgets.QPushButton("Big Button")
big_button.setMinimumWidth(400)
big_button.setMinimumHeight(400)
qwa.setDefaultWidget(big_button)
menu.addAction(qwa)
button.setMenu(menu)
layout.addWidget(button)
window.show()
app.exec_()
main()
这是因为当 QMenu 被撕下时,您实际上看不到相同 QMenu 对象,而是基于它的new QMenu。
QMenu 文档实际上解释了这一点,但我承认可以更加强调这个重要方面:
QMenu 还可以提供可撕式菜单。撕式菜单是一个顶级窗口,其中包含菜单的副本。
然后,请注意QWidgetAction 描述中的这一部分:
如果您只有一个自定义小部件,那么您可以使用 setDefaultWidget() 将其设置为默认小部件。如果该操作被添加到 QToolBar,或者通常添加到支持 QWidgetAction 的操作容器,则将使用该小部件。如果仅具有默认小部件的 QWidgetAction 同时添加到两个工具栏,则默认小部件将显示仅在第一个工具栏中添加了操作。
上述内容不仅对工具栏有效,而且对菜单(“支持 QWidgetAction 的操作容器”)有效,包括 tear off 菜单:如果您将相同的 QWidgetAction 添加到多个菜单,并且该操作仅实现
setDefaultWidget()
,小部件仅在第一个菜单中可见,这正是使用撕下时发生的情况。
解决方案是继承 QWidgetAction 并使用
createWidget()
代替:
class ButtonAction(QtWidgets.QWidgetAction):
def createWidget(self, parent):
big_button = QtWidgets.QPushButton("Big Button", parent)
big_button.setMinimumWidth(400)
big_button.setMinimumHeight(400)
return big_button
...
menu = QtWidgets.QMenu()
qwa = ButtonAction(menu)
menu.addAction(qwa)
请注意,您可能应该将按钮的
clicked
信号连接到操作的 triggered
信号。