QPushButton的QMenu滑动弹出及隐藏

        功能描述:需要在QOpenGLWidget窗口内动态创建一个QPushButton,当鼠标滑过QPushButton时,弹出QPushButton下面的QMenu,选择QMenu内的QAction执行相应的功能。

        问题分析:QPushButton 默认操作是点击按钮弹出QMenu;如果要通过鼠标滑过按钮触发弹出QMenu,则要在QPushButton的基础上派生出自己的PushButton来处理滑动事件。

#pragma once

#include <QPushButton>

class CustomPushButton : public QPushButton
{
    Q_OBJECT

public:
    CustomPushButton(QWidget *parent = Q_NULLPTR);
    ~CustomPushButton();

private:
    void mouseMoveEvent(QMouseEvent *event);         // 鼠标移动事件
};
 

#include "CustomPushButton.h"

#include <QMenu>
#include <QAction>
#include <QMouseEvent>

CustomPushButton::CustomPushButton(QWidget *parent)
    : QPushButton(parent)
{
}

CustomPushButton::~CustomPushButton()
{
}

void CustomPushButton::mouseMoveEvent(QMouseEvent *event)
{
    const QRect customBtnRect = this->geometry();
    const QPoint mousePos = event->pos() + customBtnRect.topLeft();

    if (customBtnRect.contains(mousePos))
    {
        if (this->menu())
        {
            this->menu()->popup(this->mapToGlobal(QPoint(0, 0)));
        }
    }
}
 

        自己的PushButton派生类写好了之后,在QOpenGLWidget类头文件中定义该PushButton派生类和QMenu。

    CustomPushButton *m_btnMenu;
    QMenu *m_menu;

        在QOpenGLWidget类cpp文件中实现m_btnMenu和m_menu的初始化。

void OpenglWidget::initializeGL()

   QAction *act1 = new QAction(this);
    QAction *act2 = new QAction(this);

    m_menu = new QMenu(this);
    //m_menu->installEventFilter(this);
    m_menu->setMouseTracking(true);
    m_menu->addAction(act1);
    m_menu->addAction(act2);

    m_btnMenu = new CustomPushButton(this);
    m_btnMenu->setFixedSize(QSize(30, 30));
    m_btnMenu->setIconSize(QSize(30, 30));
    m_btnMenu->setIcon(QIcon(QString("*.png")));
    m_btnMenu->move(QPoint(10, 10));

    m_btnMenu->setMenu(m_menu);
    m_btnMenu->setMouseTracking(true);
}

        实现了上述步骤运行后正常就能看到窗口中有一个按钮,鼠标滑过按钮时会弹出定义好的菜单,但是鼠标滑出菜单,菜单不会消失。下面通过Qt eventFilter来解决该问题。Qt eventFilter的使用有2个函数:一个是 installEventFilter负责在相应部件上安装事件过滤器;另一个函数是 eventFilter 函数,我们在此函数中实现事件过滤器。

        在QMenu定义中安装eventFilter。

    m_menu = new QMenu(this);
    m_menu->installEventFilter(this);
    m_menu->setMouseTracking(true);
    m_menu->addAction(act1);
    m_menu->addAction(act2);

bool OpenglWidget::eventFilter(QObject *watched, QEvent * event)
{
    if (watched == m_menu)
    {
        if (event->type() == QEvent::MouseMove)
        {
            QPointF lp = ((QMouseEvent*)event)->localPos();
            const auto& actionSize = m_menu->actions().size();

            bool flag = false;
            for (size_t i = 0; i < actionSize; ++i)
            {
                QRect rc = m_menu->actionGeometry(m_menu->actions()[i]);
                if (rc.contains(lp.toPoint()))
                {
                    // 鼠标滑动选中action时,更改该action的icon...
                    flag = true;
                }
                else
                {
                    // 鼠标滑出action时,更改该action的icon...
                }
            }

            if (!flag)
                m_menu->hide();

        }
    }
    return false;
}

 

        这个问题困扰了我几天,写下该博客是为记录,并分享给需要的人。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值