QT 自定义QPushButton,可以定制左右键弹出菜单

///  @file NPushButtonExtend.h
///  @brief QPushButton扩展
///  @author project4gogo@163.com
///  @date 2018


#ifndef NPUSHBUTTONEXTEND_H
#define NPUSHBUTTONEXTEND_H

#include <QObject>
#include <QPushButton>
#include <QAction>
#include <QList>

///
/// \brief The NPushButtonExtend class
/// 在原有基础上增加了菜单功能,通过左键点击指定区域,弹出菜单选项。
/// 菜单可固定,也可动态生成
///
///
class NPushButtonExtend : public QPushButton
{    
public:
    enum
    {
        MENU_STATIC = 0,
        MENU_DYNAMIC,
    };

    enum
    {
        MENU_BUTTON_LEFT = 0,
        MENU_BUTTON_RIGHT,
    };
    Q_OBJECT
public:
    NPushButtonExtend(QWidget *parent);
    ~NPushButtonExtend();

    ///菜单动态生成,通过发送信号signalRequestMenuy请求菜单
    void SetDynamicMenu();

    ///菜单固定
    void SetStaticMenu();

    ///点击弹出菜单的区域大小
    void SetExtendSize(QRect rc);

    ///设置弹出菜单使用的按键
    /// @param leftOrRight 按键标识 0:左键 1:右键
    void SetMenuButton(int leftOrRight);

    ///增加菜单项
    /// @param icon 图标
    /// @param text 菜单项名称
    /// @param checked 初始状态是否为选中,当checkable=true时有效
    /// @param checkable 菜单项是否为checkable模式
    /// @return 返回值为菜单项的索引
    int AddMenuItem(QIcon &icon, QString text, bool checked = false, bool checkable = false);
    int AddMenuItem(QString text, bool checked = false, bool checkable = false);
    void AddSeparator();

    ///设置菜单项显示的文字
    void SetMenuItemText(int index, QString text);

    QAction *GetMenuItem(int index);
    QAction *GetMenuItem(QString text);


signals:
    ///需要弹出菜单时,发出的请求设置菜单信息
    void signalRequestMenu();

    ///选中了菜单项时发出
    /// @param index 选中的菜单项索引,按加入顺序排列
    /// @param text  菜单项显示的文字
    void signalMenuClicked(int index, QString text, bool checked);

protected slots:
    void OnMenuClicked(bool checked);

    void OnShowMenu();
protected:
    void ReleaseMenuItem();

    // QWidget interface
protected:
    virtual void mousePressEvent(QMouseEvent *e) override;

private:
    QList<QAction*> m_menuItemList;
    QRect m_menuPopRc;

    bool m_bUsingSataicMenu = MENU_STATIC;
    int m_menuButton = MENU_BUTTON_RIGHT;


};

#endif // NPUSHBUTTONEXTEND_H
#include "npushbuttonextend.h"

#include <QDebug>
#include <QMouseEvent>
#include <QTimer>
#include <QPoint>
#include <QMenu>

#define N_PUSH_BUTTON_EXTEND_NAME "n_push_button_extend_meu_obj_name"
NPushButtonExtend::NPushButtonExtend(QWidget *parent)
    :QPushButton(parent)
{
    m_menuPopRc = QRect(0, 0, width(), height());
}

NPushButtonExtend::~NPushButtonExtend()
{
    ReleaseMenuItem();
}

void NPushButtonExtend::SetDynamicMenu()
{
    m_bUsingSataicMenu = MENU_DYNAMIC;
}

void NPushButtonExtend::SetStaticMenu()
{
    m_bUsingSataicMenu = MENU_STATIC;
}

int NPushButtonExtend::AddMenuItem(QIcon &icon, QString text, bool checked, bool checkable)
{
    QAction *pAction = new QAction(icon, text, this);
    connect(pAction, &QAction::triggered, this, &NPushButtonExtend::OnMenuClicked);
    if(true == checkable)
    {
        pAction->setCheckable(true);
        pAction->setChecked(checked);
    }
    m_menuItemList.push_back(pAction);

    return m_menuItemList.size()-1;
}

int NPushButtonExtend::AddMenuItem(QString text, bool checked, bool checkable)
{
    QIcon icon;
    return AddMenuItem(icon, text, checked, checkable);
}

void NPushButtonExtend::AddSeparator()
{
    m_menuItemList.push_back(nullptr);
}

void NPushButtonExtend::SetMenuItemText(int index, QString text)
{
    if(index >= 0 && index < m_menuItemList.size())
    {
        QAction *pAction = m_menuItemList[index];
        if(nullptr != pAction)
        {
            pAction->setText(text);
        }
    }
}

QAction *NPushButtonExtend::GetMenuItem(int index)
{
    QAction *p = nullptr;
    if((index >= 0) && (index < m_menuItemList.size()))
    {
        p = m_menuItemList[index];
    }
    return p;
}

QAction *NPushButtonExtend::GetMenuItem(QString text)
{
    QAction *p = nullptr;
    for(int i = 0; i < m_menuItemList.size(); i++)
    {
        if(0 == text.compare(m_menuItemList[i]->text()))
        {
            p = m_menuItemList[i];
            break;
        }
    }
    return p;
}

void NPushButtonExtend::SetExtendSize(QRect rc)
{
    m_menuPopRc = rc;
}

void NPushButtonExtend::SetMenuButton(int leftOrRight)
{
    m_menuButton = leftOrRight;
}

void NPushButtonExtend::OnMenuClicked(bool checked)
{
    QAction *p = reinterpret_cast<QAction*>(sender());
    for(int i = 0; i < m_menuItemList.size(); i++)
    {
        if(p == m_menuItemList[i])
        {
            emit signalMenuClicked(i, p->text(), checked);
            break;
        }
    }
}

void NPushButtonExtend::OnShowMenu()
{
    ///动态生成时,释放上一次生成的菜单
    if(MENU_DYNAMIC == m_bUsingSataicMenu)
    {
        ReleaseMenuItem();
    }

    /// 请求菜单
    emit signalRequestMenu();

    ///生成菜单
    if(m_menuItemList.size() > 0)
    {
        QMenu *menu = new QMenu(this);
        menu->setObjectName(N_PUSH_BUTTON_EXTEND_NAME);
        for(int i = 0; i < m_menuItemList.size(); i++)
        {
            if(nullptr != m_menuItemList[i])
            {
                menu->addAction(m_menuItemList[i]);
            }
            else
            {
                menu->addSeparator();
            }
        }
        menu->exec(QCursor::pos());

        delete menu;
    }
}

void NPushButtonExtend::ReleaseMenuItem()
{
    for(int i = 0; i < m_menuItemList.size(); i++)
    {
        QAction *p = m_menuItemList[i];
        if(nullptr != p)
        {
            p->deleteLater();
        }
    }
    m_menuItemList.clear();
}




void NPushButtonExtend::mousePressEvent(QMouseEvent *e)
{
    bool bUsed = false;
    do
    {
        if((MENU_BUTTON_LEFT == m_menuButton) && (Qt::LeftButton != e->button()))
        {
            break;
        }

        if((MENU_BUTTON_RIGHT == m_menuButton) && (Qt::RightButton != e->button()))
        {
            break;
        }

        if(m_menuPopRc.contains(e->pos().x(), e->pos().y()))
        {
            QTimer::singleShot(1, this, SLOT(OnShowMenu()));
            bUsed = true;
        }

    }while(false);

    if(false == bUsed)
    {
        QPushButton::mousePressEvent(e);
    }
}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值