Custom Qt QMenu
Есть ли способ в Qt добавить макет или виджеты в QMenu
создать собственное меню?
Пример ниже (слева) - это то, что у меня есть, и я хотел бы стремиться к чему-то похожему на макет справа, добавляя виджеты не из меню. Если это не может быть сделано QMenu
Существуют ли руководства для получения аналогичных результатов (возможно, когда более стандартный виджет действует как контекстное меню) где-нибудь?
3 ответа
Конечно, есть! В Qt, если есть желание, есть способ.
Вы, вероятно, должны будете сделать свой собственный класс, который использует QMenu
и использует член QListWidget
,
Затем вам нужно будет сгенерировать макет и перегрузить все правильные QLayout
функции для пересчета размеров.
И тогда вам нужно будет использовать этот макет (думаю, QHBoxLayout
) отображать как QMenu
и QListWidget
бок о бок.
Этого должно быть достаточно, чтобы указать вам правильное направление.
РЕДАКТИРОВАТЬ:
Как отметил комментатор, вы не можете наследовать два QObject
вещи, поэтому я обновил ответ соответственно.
Для настройки пунктов меню вы можете использовать QWidgetAction
учебный класс. Но вы хотите настроить меню, чтобы выглядеть как всплывающий виджет. Таким образом, вы можете подкласс QMenu
и попробуйте улучшить макет меню для ваших нужд (QMenu
является QWidget
). Тебе квестин не понятен.
Я написал сценарий, вы можете попробовать его.
но я не подкласс 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_())