#简述
重新最近开始了QQ最新版 9.0 界面的模仿,前几天搞了一个QQ登陆界面的动画效果详情见 QQ 9.0 新版登录窗口登录特效 ,今晚Qt技术学习班分享了QQ 9.0版本的自定义菜单控件,通过QListWidget 来承载 每个菜单项,通过简单的组合完成菜单项控件,主要如下:
1、自动设置菜单高度,根据当前添加的菜单项自增菜单高度;
2、菜单宽度可根据菜单文字自行设置;
3、菜单的透明度、菜单边框阴影宽度、菜单四角圆角弧度均可设置;
4、其他菜单等样式,菜单项文字颜色,图标等均可自行设置;
/**
* @author : 前行中的小猪;
* @date : 2018年05月18日
* @version: 1.0
* @note : 模仿QQ菜单样式,实现自定义菜单,通过ListWidget加载菜单项;
1、自动设置菜单高度,根据当前添加的菜单项自增菜单高度;
2、菜单宽度可根据菜单文字自行设置;
3、菜单的透明度、菜单边框阴影宽度、菜单四角圆角弧度均可设置;
4、其他菜单等样式,菜单项文字颜色,图标等均可自行设置,
这里只给出一个模板,大家可自行发挥拓展;
*@ 博客地址: https://blog.csdn.net/GoForwardToStep ;
**/
#include
#include
#include
#include
#include
#include
#define MENU_ITEM_HEIGHT 30 // 菜单项的高度;
class QQMenuItemWidget : public QWidget
{
Q_OBJECT
public:
QQMenuItemWidget()
: m_isEnter(false)
, m_itemIndex(0)
{
m_iconLabel = new QLabel;
m_iconLabel->setFixedSize(QSize(20, 20));
m_textLabel = new QLabel;
m_textLabel->setStyleSheet("font-family:Microsoft YaHei;font-size:14px;");
QHBoxLayout* hLayout = new QHBoxLayout(this);
hLayout->addWidget(m_iconLabel);
hLayout->addWidget(m_textLabel);
hLayout->addStretch();
hLayout->setSpacing(10);
hLayout->setContentsMargins(10, 0, 0, 0);
this->setFixedHeight(MENU_ITEM_HEIGHT);
this->setAttribute(Qt::WA_TranslucentBackground);
}
// 设置菜单项文字;
void setMenuItemText(const QString& text)
{
m_textLabel->setText(text);
m_textLabel->setScaledContents(true);
}
// 设置菜单项图标;
void setMenuItemIcon(const QIcon& icon)
{
m_iconLabel->setPixmap(icon.pixmap(QSize(20, 20)));
}
// 设置菜单项Index;
void SetMenuItemIndex(const int& index)
{
m_itemIndex = index;
}
private:
void mouseReleaseEvent(QMouseEvent *event)
{
emit signalMenuClicked(m_itemIndex);
}
void enterEvent(QEvent *event)
{
m_isEnter = true;
update();
}
void leaveEvent(QEvent *event)
{
m_isEnter = false;
update();
}
void paintEvent(QPaintEvent *event)
{
if (m_isEnter)
{
QPainter painter(this);
painter.fillRect(this->rect(), QColor(215, 215, 215, 150));
}
}
signals:
// 通知菜单项被点击;
void signalMenuClicked(int);
private:
QLabel* m_iconLabel;
QLabel* m_textLabel;
int m_itemIndex;
bool m_isEnter;
};
class QQCustomMenu : public QWidget
{
Q_OBJECT
public:
QQCustomMenu(QWidget *parent = Q_NULLPTR);
// 添加菜单项;
void addMenuItem(const QIcon &icon, const QString &text);
// 添加分隔项;
void addSeparator();
private:
void initWidget();
void paintEvent(QPaintEvent *event);
private slots:
// 根据Index判断当前点击了那个菜单项;
void onMenuItemClicked(int menuItemIndex);
private:
QListWidget* m_menuItemListWidget;
// 根据当前添加的菜单项和分隔项自动计算菜单高度;
int m_currentMenuHeight;
// 记录菜单项Index;
int m_menuItemIndex;
};
#include "QQCustomMenu.h"
#include
#include
#define SHADOW_WIDTH 15 // 窗口阴影宽度;
#define WINDOW_WIDTH 180 // 菜单宽度;
#define SEPARATOR_HEIGHT 12 // 分割线高度;
#define VMARGIN 10 // QListWidget纵向的边距;
#define BORDER_RADIUS 5 // 菜单四角圆角的弧度;
#define WINDPW_OPACITY 0.9 // 菜单背景透明度;
QQCustomMenu::QQCustomMenu(QWidget *parent)
: QWidget(parent)
, m_menuItemIndex(0)
{
initWidget();
// 设置窗户属性;
setWindowFlags(Qt::FramelessWindowHint/* | Qt::Tool*/); // 正式应用时要加上 Qt::Tool;
setAttribute(Qt::WA_TranslucentBackground);
setWindowOpacity(WINDPW_OPACITY);
setFixedWidth(WINDOW_WIDTH);
setStyleSheet("QListView{border:none} QListView::item{background:transparent;}");
// 设置阴影边框;
auto shadowEffect = new QGraphicsDropShadowEffect(this);
shadowEffect->setOffset(0, 0);
shadowEffect->setColor(Qt::gray);
shadowEffect->setBlurRadius(SHADOW_WIDTH);
this->setGraphicsEffect(shadowEffect);
// 计算默认高度;
m_currentMenuHeight = SHADOW_WIDTH * 2 + VMARGIN * 2;
this->setFixedHeight(m_currentMenuHeight);
}
void QQCustomMenu::initWidget()
{
m_menuItemListWidget = new QListWidget;
m_menuItemListWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_menuItemListWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QHBoxLayout* hMainLayout = new QHBoxLayout(this);
hMainLayout->addWidget(m_menuItemListWidget);
hMainLayout->setContentsMargins(SHADOW_WIDTH, SHADOW_WIDTH + VMARGIN, SHADOW_WIDTH, SHADOW_WIDTH + VMARGIN);
}
void QQCustomMenu::addMenuItem(const QIcon &icon, const QString &text)
{
QQMenuItemWidget* menuItem = new QQMenuItemWidget;
menuItem->setMenuItemIcon(icon);
menuItem->setMenuItemText(text);
connect(menuItem, &QQMenuItemWidget::signalMenuClicked, this, &QQCustomMenu::onMenuItemClicked);
QListWidgetItem* item = new QListWidgetItem;
item->setSizeHint(QSize(WINDOW_WIDTH - 2 * SHADOW_WIDTH, MENU_ITEM_HEIGHT));
m_menuItemListWidget->addItem(item);
m_menuItemListWidget->setItemWidget(item, menuItem);
m_menuItemIndex++;
m_currentMenuHeight += MENU_ITEM_HEIGHT;
this->setFixedHeight(m_currentMenuHeight);
}
void QQCustomMenu::addSeparator()
{
QFrame* separatorLabel = new QFrame;
separatorLabel->setFrameShape(QFrame::HLine);
separatorLabel->setLineWidth(1);
separatorLabel->setFrameShadow(QFrame::Sunken);
// 设置分隔线颜色;
QPalette palette = separatorLabel->palette();
palette.setColor(QPalette::Dark, QColor(219, 219, 219, 150));
separatorLabel->setPalette(palette);
QListWidgetItem* item = new QListWidgetItem;
item->setSizeHint(QSize(WINDOW_WIDTH - 2 * SHADOW_WIDTH, SEPARATOR_HEIGHT));
m_menuItemListWidget->addItem(item);
m_menuItemListWidget->setItemWidget(item, separatorLabel);
m_currentMenuHeight += SEPARATOR_HEIGHT;
this->setFixedHeight(m_currentMenuHeight);
}
void QQCustomMenu::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::white);
painter.drawRoundedRect(QRect(SHADOW_WIDTH, SHADOW_WIDTH, \
width() - SHADOW_WIDTH * 2, height() - SHADOW_WIDTH * 2), BORDER_RADIUS, BORDER_RADIUS);
}
void QQCustomMenu::onMenuItemClicked(int menuItemIndex)
{
// 根据点击不同的菜单项进行不同操作,这里应发出信号去通知调用菜单的widget;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QQCustomMenu w;
w.addMenuItem(QIcon(":/Resources/busy.png"), "忙碌");
w.addMenuItem(QIcon(":/Resources/hide.png"), "隐身");
w.addMenuItem(QIcon(":/Resources/lock.png"), "锁定");
w.addSeparator();
w.addMenuItem(QIcon(":/Resources/offLine.png"), "离线");
w.addMenuItem(QIcon(":/Resources/message.png"), "消息");
w.show();
return a.exec();
}