在Qt中是否有办法将布局或窗口小部件添加到QMenu
以创建自定义菜单?
下面的示例(左)是我所拥有的,我想通过添加非菜单小部件来瞄准类似于右侧模型的东西。如果QMenu
无法完成,是否有指南可以在任何地方产生类似的结果(可能通过将更标准的小部件作为上下文菜单)?
答案 0 :(得分:8)
当然有!在Qt中,如果有遗嘱就有办法。
您可能需要创建自己的使用QMenu
的类并使用成员QListWidget
。
然后,您需要生成布局并重载所有正确的QLayout
函数以进行大小重新计算。
然后您需要使用此布局(请QHBoxLayout
)并排显示QMenu
和QListWidget
。
这应该足以指出你正确的方向。
修改强>
作为一名评论者指出,你不能继承两个QObject
的东西,所以我更新了
相应地回答。
答案 1 :(得分:0)
要自定义菜单项,您可以使用QWidgetAction
课程。但是你想要自定义菜单看起来像弹出窗口小部件。因此,您可以继承QMenu
并尝试根据需要改进菜单布局(QMenu
为QWidget
)。你的questoin不清楚。
答案 2 :(得分:0)
我写了一个脚本,可以尝试一下。
但我不是QMenu的子类。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from PySide.QtGui import *
from PySide.QtCore import *
class MenuItem(QWidget):
"""docstring for MenuItem"""
def __init__(self, text='test', icon=None, parent=None):
super(MenuItem, self).__init__(parent)
hbox = QHBoxLayout(self)
# hbox.setContentsMargins(0, 0, 0, 0)
label = QLabel(text)
btn = QPushButton()
if icon:
btn.setIcon(icon)
hbox.addWidget(label)
hbox.addStretch()
hbox.addWidget(btn)
self.setMinimumWidth(parent.width())
class MyMenu(QWidget):
"""docstring for MyMenu"""
def __init__(self, parent=None):
super(MyMenu, self).__init__(parent)
self.main_width = 200
self.main_height = 150
self.close_menu = False
self.parent = parent
self.setGeometry(0, 0, 200, 150)
self.initUI()
self.setWindowFlags(Qt.Popup)
# self.setWindowModality(Qt.WindowModal)
def initUI(self):
main_frame = QWidget(self)
main_v_layout = QVBoxLayout(main_frame)
main_v_layout.setContentsMargins(0, 0, 0, 0)
item_1 = MenuItem('item 1', parent=self)
item_2 = MenuItem('item 2', parent=self)
item_3 = MenuItem('item 3', parent=self)
main_v_layout.addWidget(item_1)
main_v_layout.addWidget(item_2)
main_v_layout.addWidget(item_3)
def animationShow(self):
self.close_menu = False
self.start_close_menu = True
self.show()
# PyQt4.QtCore.QRect(0, 0, 400, 23)
rect = self.parent.rect()
# PyQt4.QtCore.QPoint(199, 11)
center_pos = rect.center()
# PyQt4.QtCore.QPoint(654, 465)
global_center_pos = self.parent.mapToGlobal(center_pos)
height = rect.height()
show_pos = QPoint(
global_center_pos.x() - (self.width() / 2),
global_center_pos.y() + height)
# print show_pos
self.move(show_pos)
self.inAnimation(show_pos)
def inAnimation(self, show_pos=None):
start_height = QSize(self.main_width, 0)
end_height = QSize(self.main_width, self.main_height)
size_anim = QPropertyAnimation(self, 'size')
size_anim.setStartValue(start_height)
size_anim.setEndValue(end_height)
size_anim.setDuration(160)
size_anim.setEasingCurve(QEasingCurve.OutQuad)
opacity_anim = QPropertyAnimation(self, 'windowOpacity')
opacity_anim.setStartValue(0.0)
opacity_anim.setEndValue(1.0)
opacity_anim.setDuration(260)
opacity_anim.setEasingCurve(QEasingCurve.OutQuad)
self.in_anim_group = QParallelAnimationGroup()
self.in_anim_group.addAnimation(size_anim)
self.in_anim_group.addAnimation(opacity_anim)
self.in_anim_group.start()
def outAnimation(self):
try:
end_size = QSize(self.size().width(), 0)
pos_anim = QPropertyAnimation(self, 'size')
pos_anim.setEndValue(end_size)
pos_anim.setDuration(200)
pos_anim.setEasingCurve(QEasingCurve.InQuad)
opacity_anim = QPropertyAnimation(self, 'windowOpacity')
opacity_anim.setStartValue(1.0)
opacity_anim.setEndValue(0.0)
opacity_anim.setDuration(200)
opacity_anim.setEasingCurve(QEasingCurve.InQuad)
self.out_anim_group = QParallelAnimationGroup()
self.out_anim_group.addAnimation(pos_anim)
self.out_anim_group.addAnimation(opacity_anim)
self.out_anim_group.finished.connect(self.closeMenu)
self.out_anim_group.start()
except RuntimeError as e:
pass
except Exception as e:
print e
def closeMenu(self):
self.close_menu = True
self.setVisible(False)
def closeEvent(self, event):
# super(MyMenu, self).closeEvent(event)
if self.start_close_menu:
self.outAnimation()
self.start_close_menu = False
def hideEvent(self, event):
# print 'hideEvent', event
super(MyMenu, self).hideEvent(event)
def setVisible(self, visible):
if self.close_menu:
visible = False
elif not visible:
visible = True
super(MyMenu, self).setVisible(visible)
class Win(QWidget):
"""docstring for Win"""
def __init__(self):
super(Win, self).__init__()
vbox = QVBoxLayout(self)
btn = QPushButton('call menu')
vbox.addWidget(btn)
self.menu = MyMenu(btn)
btn.clicked.connect(self.menu.animationShow)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = Win()
win.show()
sys.exit(app.exec_())