/// @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);
}
}