Custom Qt QMenu

烈酒焚心 提交于 2019-12-22 04:16:13

问题


Is there a way in Qt to add a layout or widgets to a QMenu to create a custom menu?

The example below (left) is what I have, and I'd like to aim for something similar to the mock-up on the right, by adding non-menu widgets. If it can't be done by QMenu, are there guides to produce similar results (perhaps by having a more standard widget act as a context menu) anywhere?


回答1:


Sure there is! In Qt, if there is a a will there is a way.

You will probably need to make your own class that uses QMenu and uses a member QListWidget.

You will then need to generate the layout and overload all the correct QLayout functions for size recalculation.

And then you'll need to use this layout (think QHBoxLayout) to display both a QMenu and a QListWidget side by side.

That should be enough to point you in the right direction.

EDIT:

As a commenter pointed out, you can't inherit two QObject things so I updated the answer accordingly.




回答2:


To customize menu items you can use QWidgetAction class. But you want to customize menu to look like popup widget. So you may subclass QMenu and try to improve layout of menu for your needs (QMenu is QWidget). You questoin is not clear.




回答3:


I wrote a script, you can try it.

but I am not subclass 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_())


来源:https://stackoverflow.com/questions/18787426/custom-qt-qmenu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!