QMenu设置弹出位置,支持16个方向。

弹出位置分别可以为:
当前16个位置

enum MenuBtnDirection
{
    LeftTop_LeftBottom = 0,           //左上角的左下方向弹出
    LeftTop_LeftTop,                  //左上角的左上方向弹出
    LeftTop_rightBottom ,             //左上角的右下方向弹出
    LeftTop_rightTop,                 //左上角的右上方向弹出
    LeftBottom_LeftBottom,            //左下角的左下方向弹出
    LeftBottom_LeftTop,               //左下角的左上方向弹出
    LeftBottom_rightBottom ,          //左下角的右下方向弹出
    LeftBottom_rightTop,              //左下角的右上方向弹出
    RightTop_LeftBottom,              //右上角的左下方向弹出
    RightTop_LeftTop,                 //右上角的左上方向弹出
    RightTop_rightBottom ,            //右上角的右下方向弹出
    RightTop_rightTop,                //右上角的右上方向弹出
    RightBottom_LeftBottom,           //右下角的左下方向弹出
    RightBottom_LeftTop,              //右下角的左上方向弹出
    RightBottom_rightBottom ,         //右下角的右下方向弹出
    RightBottom_rightTop,             //右下角的右上方向弹出
};

本内容中QMenu被重写了,是为了点击menu内部不让自动回收,如果没有这个需求的可以用原生的QMenu即可。且本文已经直接写了一个能够添加QMenu的自定义按钮了,有需要的兄弟直接用。
直接上代码:
.h

#ifndef MENUBTN_H
#define MENUBTN_H

#include <QToolButton>
#include "ubase.h"
#include <QMenu>
#include <QMouseEvent>

class UMenu;
class MenuBtn : public QToolButton
{
    Q_OBJECT
public:
    MenuBtn(QWidget* parent = nullptr);
    void setInfo(int direction = 0,QWidget* childWidget = nullptr);
private slots:
    void slotShowMenu();
private:
    UMenu* m_menu;
    QWidget* m_childWidget;
    int m_direction;
};


class UMenu : public QMenu
{
public:
    UMenu(QWidget* parent = nullptr);
protected:
    void mouseReleaseEvent(QMouseEvent *e);
};
#endif // MENUBTN_H

.cpp

#include "menubtn.h"
#include <QHBoxLayout>

MenuBtn::MenuBtn(QWidget *parent)
{
    connect(this,&MenuBtn::clicked,this,&MenuBtn::slotShowMenu);
}

void MenuBtn::setInfo(int direction, QWidget *childWidget)
{
    m_direction = direction;
    m_childWidget = childWidget;
    if (childWidget)
    {
        DEBUGLOG<<childWidget->rect();
        m_menu = new UMenu(this); Q_CHECK_PTR(m_menu);
        QHBoxLayout* hboxlay = new QHBoxLayout(m_menu);
        hboxlay->addWidget(childWidget);
        m_menu->setLayout(hboxlay);
        this->setMenu(m_menu);
//        this->setPopupMode(QToolButton::InstantPopup);
    }
}

void MenuBtn::slotShowMenu()
{
    if (m_direction == LeftTop_LeftBottom)
    {
        QPoint pos;
        pos.setX(-m_childWidget->sizeHint().width() - width()/2);
        pos.setY(0);
        m_menu->exec(mapToGlobal(pos));
    }
    else if(m_direction == LeftTop_LeftTop)
    {
        QPoint pos;
        pos.setX(-m_childWidget->sizeHint().width() - width()/2);
        pos.setY(-m_childWidget->sizeHint().height() - height());
        m_menu->exec(mapToGlobal(pos));
    }
    else if(m_direction == LeftTop_rightBottom)
    {
        QPoint pos;
        pos.setX(0);
        pos.setY(0);
        m_menu->exec(mapToGlobal(pos));
    }
    else if(m_direction == LeftTop_rightTop)
    {
        QPoint pos;
        pos.setX(0);
        pos.setY(-m_childWidget->sizeHint().height() - height());
        m_menu->exec(mapToGlobal(pos));
    }
    else if (m_direction == LeftBottom_LeftBottom)
    {
        QPoint pos;
        pos.setX(-m_childWidget->sizeHint().width() - width()/2);
        pos.setY(height());
        m_menu->exec(mapToGlobal(pos));
    }
    else if(m_direction == LeftBottom_LeftTop)
    {
        QPoint pos;
        pos.setX(-m_childWidget->sizeHint().width() - width()/2);
        pos.setY(-m_childWidget->sizeHint().height());
        m_menu->exec(mapToGlobal(pos));
    }
    else if(m_direction == LeftBottom_rightBottom)
    {
        QPoint pos;
        pos.setX(0);
        pos.setY(height());
        m_menu->exec(mapToGlobal(pos));
    }
    else if(m_direction == LeftBottom_rightTop)
    {
        QPoint pos;
        pos.setX(0);
        pos.setY(-m_childWidget->sizeHint().height());
        m_menu->exec(mapToGlobal(pos));
    }
    else if (m_direction == RightTop_LeftBottom)
    {
        QPoint pos;
        pos.setX(-m_childWidget->sizeHint().width() + width()/2);
        pos.setY(0);
        m_menu->exec(mapToGlobal(pos));
    }
    else if(m_direction == RightTop_LeftTop)
    {
        QPoint pos;
        pos.setX(-m_childWidget->sizeHint().width() + width()/2);
        pos.setY(-m_childWidget->sizeHint().height() - height());
        m_menu->exec(mapToGlobal(pos));
    }
    else if(m_direction == RightTop_rightBottom)
    {
        QPoint pos;
        pos.setX(width());
        pos.setY(0);
        m_menu->exec(mapToGlobal(pos));
    }
    else if(m_direction == RightTop_rightTop)
    {
        QPoint pos;
        pos.setX(width());
        pos.setY(-m_childWidget->sizeHint().height() - height());
        m_menu->exec(mapToGlobal(pos));
    }
    else if (m_direction == RightBottom_LeftBottom)
    {
        QPoint pos;
        pos.setX(-m_childWidget->sizeHint().width() + width()/2);
        pos.setY(height());
        m_menu->exec(mapToGlobal(pos));
    }
    else if(m_direction == RightBottom_LeftTop)
    {
        QPoint pos;
        pos.setX(-m_childWidget->sizeHint().width() + width()/2);
        pos.setY(-m_childWidget->sizeHint().height());
        m_menu->exec(mapToGlobal(pos));
    }
    else if(m_direction == RightBottom_rightBottom)
    {
        QPoint pos;
        pos.setX(width());
        pos.setY(height());
        m_menu->exec(mapToGlobal(pos));
    }
    else if(m_direction == RightBottom_rightTop)
    {
        QPoint pos;
        pos.setX(width());
        pos.setY(-m_childWidget->sizeHint().height());
        m_menu->exec(mapToGlobal(pos));
    }
    else
        m_menu->exec(mapToGlobal(QPoint(0,0)));
}


UMenu::UMenu(QWidget *parent):QMenu(parent)
{

}

void UMenu::mouseReleaseEvent(QMouseEvent *e)
{
    //屏蔽QMenu::mouseReleaseEvent(e),达到拦截点击的目的,使其点击menu里面任何位置都无效。
//    QAction *action = this->actionAt(e->pos());
//    if (action)
//    {
//        action->activate(QAction::Trigger);
//    }
//    else
//    {
//        QMenu::mouseReleaseEvent(e);
//    }
}

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东方忘忧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值