Custom Qt QMenu

Есть ли способ в Qt добавить макет или виджеты в QMenu создать собственное меню?

Пример ниже (слева) - это то, что у меня есть, и я хотел бы стремиться к чему-то похожему на макет справа, добавляя виджеты не из меню. Если это не может быть сделано QMenuСуществуют ли руководства для получения аналогичных результатов (возможно, когда более стандартный виджет действует как контекстное меню) где-нибудь?

Custom 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_())
Другие вопросы по тегам