QSS系列:自定义QMenu

简述

本文将通过简单示例介绍QMenu样式如何自定义。

常用属性、子控件和伪状态

QMenu同样支持盒子模型

QMenu通用属性如下:

QMenu子控件如下:

QMenu只支持子控件item的伪状态,如下:

效果图

简单定义QMenu在使用QWidgetAction、QAction以及有子菜单下的样式。
在这里插入图片描述

QSS

如何使用样式表,请参考QSS系列:设置样式表

* {
	outline: none;
}

QDialog {
	background: #D6DBE9;
}

QMenu {
	border: 1px solid #CCCCCC; /* 边框宽度为1px,颜色为#CCCCCC */
	border-radius: 3px; /* 边框圆角 */
	background-color: #FAFAFC; /* 背景颜色 */
	font-size: 10pt; /* 文本字体大小 */
	font-family: "Microsoft YaHei"; /* 文本字体族 */
	padding: 5px 0px 5px 0px; /* 菜单项距菜单顶部边界和底部边界分别有5px */
}

QMenu::item { /* 菜单子控件item,为菜单项在default的状态 */
	border: 0px solid transparent;
	background-color: transparent;
	color: black; /* 文本颜色 */
	min-height: 40px; /* 菜单项的最小高度 */
	margin: 2px 5px 2px 10px; /* 菜单项距其上下菜单项分别有2px,距菜单左右边界分别有10px和5px */
	/*padding: 0px 0px 0px 25px;*/ /* 也可使用padding定义菜单项与上下左右的距离 */
}

QMenu::item:selected { /* 为菜单项在selected的状态 */
	background-color: #EDEDEF;
}

QMenu::item:disabled{ /* 为菜单项在disabled的状态 */
	color: #CCCCCC;
	background: none;
}

QMenu::separator { /* 菜单子控件separator,定义菜单项之间的分隔线 */
	height: 1px;
	background: #CCCCCC;
	margin-left: 2px; /* 距离菜单左边界2px */
	margin-right: 2px; /* 距离菜单右边界2px */
}

QMenu::right-arrow { /* 菜单子控件right-arrow,定义子菜单指示器 */
	width: 24px;
	height: 24px;
	image: url(:/Resource/right_arrow);
}

QMenu::left-arrow { /* 菜单子控件left-arrow,定义子菜单指示器 */
	width: 24px;
	height: 24px;
	image: url(:/Resource/left_arrow);
}

/*
QMenu::icon:checked {
	border: none;
	background-color: transparent;
	position: absolute;
	width: 24px;
	height: 24px;
}*/

QMenu::item::indicator { /* 菜单项子控件indicator,定义菜单项在选中状态下的指示器 */
	width: 24px;
	height: 24px;
}

QMenu::item::indicator:unchecked { /* 定义菜单项未选中的状态 */
	image: none;
}

QMenu::item::indicator:checked { /* 定义菜单项选中的状态 */
	image: url(:/Resource/checkebox);
}

QPushButton#PlayerButton { /* 自定义菜单项中的按钮 */
	border: none;
	background-color: transparent;
}

QPushButton#PlayerButton:hover {
	padding-top: 2px;
	padding-left: 2px;
}

QPushButton#PlayerButton:pressed {
	padding: 0px;
}

源码

  • main.cpp
#include "MainWindow.h"
#include <QtWidgets/QApplication>
#include <QFile>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

	//全局加载样式表
	QFile styleFile(":/Resource/DefaultTheme");
	if (styleFile.open(QIODevice::ReadOnly))
	{
		QString string = styleFile.readAll();
		qApp->setStyleSheet(string);
	}

    MainWindow w;
    w.show();
    return a.exec();
}
  • CustomMenu.h、CustomMenu.cpp
#ifndef CUSTOMMENU_H
#define CUSTOMMENU_H

#include <QMenu>

class CustomMenu : public QMenu
{
	Q_OBJECT

public:
	explicit CustomMenu(QWidget *parent = nullptr);
	~CustomMenu();
};

#endif
#include "CustomMenu.h"

CustomMenu::CustomMenu(QWidget *parent)
	: QMenu(parent)
{
	//自定义QMenu
	//取消边框和阴影
	this->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);
	this->setAttribute(Qt::WA_TranslucentBackground);
}

CustomMenu::~CustomMenu()
{
}
  • MainWindow.h、MainWindow.cpp
#ifndef MainWindow_H
#define MainWindow_H

#include <QDialog>
#include <QWidget>
#include <QMenu>
#include <QAction>
#include <QWidgetAction>
#include <QPushButton>
#include <QBoxLayout>
#include "CustomMenu.h"

class MainWindow : public QDialog
{
	Q_OBJECT

public:
	MainWindow(QWidget *parent = Q_NULLPTR);

private:
	void Init();

private slots:
	void SlotContextMenuRequested(const QPoint& pos);

private:
	CustomMenu *m_pPlayerMenu;
	QAction *m_pSongNameAction;

	QWidgetAction *m_pPlayWidgetAction;
	QWidget *m_pPlayWidget;
	QPushButton *m_pPlayBackButton;
	QPushButton *m_pPlayButton;
	QPushButton *m_pPlayForwardButton;
	QHBoxLayout *m_pHLayout;

	QAction *m_pPlayProcedureAction;
	CustomMenu *m_pProcedureMenu;
	QAction *m_pListCycleAction;
	QAction *m_pSingleCycleAction;
	QAction *m_pRandomPlayAction;
	QAction *m_pOrderPlayAction;
	QActionGroup *m_pProcedureActionGroup;

	QAction *m_pFavoriteAction;
	QAction *m_pSettingsAction;
	QAction *m_pExitAction;
};

#endif // !MainWindow_H
#include "MainWindow.h"

#include "CommonDefines.h"
#include "MenuWidget.h"

MainWindow::MainWindow(QWidget *parent)
    : QDialog(parent)
{
	Init();
}

void MainWindow::Init()
{
	m_pPlayerMenu = new CustomMenu(this); //使用自定义菜单
	m_pPlayerMenu->setMinimumWidth(220);

	m_pSongNameAction = new QAction("凡人修仙传", this);
	m_pSongNameAction->setIcon(QIcon(":/Resource/contacter")); //定义菜单项的图标

	//
	m_pPlayWidgetAction = new QWidgetAction(this); //使用QWidgetAction可以定义复杂的菜单项
	m_pPlayWidget = new QWidget(this); //存放自定义菜单项所需的控件及设置布局

	m_pPlayBackButton = new QPushButton(this);
	m_pPlayBackButton->setObjectName("PlayerButton");
	m_pPlayBackButton->setIcon(QIcon(":/Resource/previous"));
	m_pPlayBackButton->setIconSize(QSize(32, 32));

	m_pPlayButton = new QPushButton(this);
	m_pPlayButton->setObjectName("PlayerButton");
	m_pPlayButton->setIcon(QIcon(":/Resource/play"));
	m_pPlayButton->setIconSize(QSize(32, 32));

	m_pPlayForwardButton = new QPushButton(this);
	m_pPlayForwardButton->setObjectName("PlayerButton");
	m_pPlayForwardButton->setIcon(QIcon(":/Resource/next"));
	m_pPlayForwardButton->setIconSize(QSize(32, 32));

	m_pHLayout = new QHBoxLayout(m_pPlayWidget);
	m_pHLayout->addWidget(m_pPlayBackButton);
	m_pHLayout->addWidget(m_pPlayButton);
	m_pHLayout->addWidget(m_pPlayForwardButton);
	m_pPlayWidgetAction->setDefaultWidget(m_pPlayWidget); //为QWidgetAction设置默认QWidget

	//
	m_pPlayProcedureAction = new QAction("顺序播放", this); //此为子菜单项
	m_pPlayProcedureAction->setIcon(QIcon(":/Resource/order"));
	m_pProcedureMenu = new CustomMenu(this); //子菜单
	m_pProcedureMenu->setMinimumWidth(150);

	m_pListCycleAction = new QAction("列表循环", this);
	m_pListCycleAction->setIcon(QIcon(":/Resource/listcycle"));
	m_pListCycleAction->setCheckable(true); //菜单项可选中
	m_pListCycleAction->setChecked(false); //菜单项处于未选中状态
	m_pSingleCycleAction = new QAction("单曲循环", this);
	m_pSingleCycleAction->setIcon(QIcon(":/Resource/singlecycle"));
	m_pSingleCycleAction->setCheckable(true);
	m_pSingleCycleAction->setChecked(false);
	m_pRandomPlayAction = new QAction("随机播放", this);
	m_pRandomPlayAction->setIcon(QIcon(":/Resource/randomplay"));
	m_pRandomPlayAction->setCheckable(true);
	m_pRandomPlayAction->setChecked(false);
	m_pOrderPlayAction = new QAction("顺序播放", this);
	m_pOrderPlayAction->setIcon(QIcon(":/Resource/order"));
	m_pOrderPlayAction->setCheckable(true);
	m_pOrderPlayAction->setChecked(true); //菜单项处于选中状态

	m_pProcedureActionGroup = new QActionGroup(this); //QActionGroup,为组中的QAction设置exclusive状态
	m_pProcedureActionGroup->setExclusive(true);
	m_pProcedureActionGroup->addAction(m_pListCycleAction);
	m_pProcedureActionGroup->addAction(m_pSingleCycleAction);
	m_pProcedureActionGroup->addAction(m_pRandomPlayAction);
	m_pProcedureActionGroup->addAction(m_pOrderPlayAction);

	m_pProcedureMenu->addAction(m_pListCycleAction);
	m_pProcedureMenu->addAction(m_pSingleCycleAction);
	m_pProcedureMenu->addAction(m_pRandomPlayAction);
	m_pProcedureMenu->addAction(m_pOrderPlayAction);
	m_pPlayProcedureAction->setMenu(m_pProcedureMenu);

	//
	m_pFavoriteAction = new QAction("喜欢", this);
	m_pFavoriteAction->setIcon(QIcon(":/Resource/favorite"));
	m_pSettingsAction = new QAction("设置", this);
	m_pSettingsAction->setIcon(QIcon(":/Resource/setting"));
	m_pExitAction = new QAction("退出", this);
	m_pExitAction->setIcon(QIcon(":/Resource/exit"));

	//
	m_pPlayerMenu->addAction(m_pSongNameAction);
	m_pPlayerMenu->addSeparator(); //添加分隔线
	m_pPlayerMenu->addAction(m_pPlayWidgetAction);
	m_pPlayerMenu->addSeparator();
	m_pPlayerMenu->addAction(m_pPlayProcedureAction);
	m_pPlayerMenu->addSeparator();
	m_pPlayerMenu->addAction(m_pFavoriteAction);
	m_pPlayerMenu->addAction(m_pSettingsAction);
	m_pPlayerMenu->addAction(m_pExitAction);

	this->setContextMenuPolicy(Qt::CustomContextMenu); //可显示右键菜单
	connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(SlotContextMenuRequested(const QPoint&)));
	this->setMinimumSize(600, 500);
}

void MainWindow::SlotContextMenuRequested(const QPoint& pos)
{
	m_pPlayerMenu->exec(mapToGlobal(pos)); //显示菜单
}

参考

参考Qt助手,如有错误,请指正,谢谢!

©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页