Qt自定义菜单

 Qt开发过程中,弹出菜单时我们一般使用QMenu,但是QMenu都是一条项固定的格式,如查想要自己的设计界面就没法使用默认的Action项了,因此我们得用自定义的QMenu。

本篇介绍使用自定义的QMenu设计出UI。我们使用QWidget + QWidgetAction来实现。QWidgetAction继承自QAction,无法通过继承来实现一个界面,但它提供了setDefaultWidget来绑定一个界面,使用起来就更加方便了。

首先创建一个PlayWidget带UI的类,里面添加两个按钮,然后把这个类嵌进QWidgetAction中。代码如下:

#ifndef PLAYWIDGET_H
#define PLAYWIDGET_H#include <QWidget>namespace Ui {
class PlayWidget;
}class PlayWidget : public QWidget
{Q_OBJECTpublic:explicit PlayWidget(QWidget *parent = nullptr);~PlayWidget();private:Ui::PlayWidget *ui;
};#endif // PLAYWIDGET_H

#include "playwidget.h"
#include "ui_playwidget.h"PlayWidget::PlayWidget(QWidget *parent) :QWidget(parent),ui(new Ui::PlayWidget)
{ui->setupUi(this);
}PlayWidget::~PlayWidget()
{delete ui;
}
void CustomMenu::initData()
{QString strLineEditStyle = QString("QLineEdit{background-color:#E9E9EA;color:#6D6E6B;border-radius:8px;}""QLineEdit:hover{background-color:#E9E9EA;border-radius:8px;border:2px solid rgba(47, 137, 252, 1);}""QLineEdit:focus{background-color:#E9E9EA;border-radius:8px;border:2px solid rgba(47, 137, 252, 1);}""QLineEdit:disabled{background-color:#F0F0F0;border-radius:8px;}");QFont font = qApp->font();font.setPixelSize(12);QLineEdit *pLineEdit = new QLineEdit(this);pLineEdit->setFont(font);pLineEdit->setMaximumSize(QSize(86, 24));pLineEdit->setMinimumSize(QSize(86, 24));pLineEdit->setStyleSheet(strLineEditStyle);//播放项QWidgetAction *pWdtAction = new QWidgetAction(this);//播放项界面,继承自QWidget的类PlayWidget *playWdt = new PlayWidget(this);playWdt->setMinimumSize(QSize(200, 50));pWdtAction->setDefaultWidget(playWdt);//创建一个包含声音调整控件的界面项QWidgetAction *pVoice = new QWidgetAction(this);QWidget *pVoiceWdt = new QWidget(this);QSlider *pSlider = new QSlider(Qt::Horizontal);QHBoxLayout *layout = new QHBoxLayout(pVoiceWdt);layout->addWidget(pSlider);layout->addWidget(pLineEdit);pVoiceWdt->setLayout(layout);pVoice->setDefaultWidget(pVoiceWdt);//生成菜单栏if(m_menu == nullptr) {m_menu = new QMenu(this);m_menu->addAction(pWdtAction);m_menu->addSeparator();m_menu->addAction(pVoice);m_menu->addAction(QStringLiteral("显示歌词"));m_menu->addAction(QStringLiteral("锁定歌词"));m_menu->addSeparator();m_menu->addAction(QStringLiteral("选项设置"));m_menu->addSeparator();m_menu->addAction(QStringLiteral("登陆"));m_menu->addAction(QStringLiteral("退出"));}
}void CustomMenu::initConnect()
{connect(ui->btnCreateMenu, SIGNAL(clicked()), this, SLOT(slotCreateMenu()));
}void CustomMenu::slotCreateMenu()
{QPoint point = ui->btnCreateMenu->pos();point.setY(point.y() + 50);m_menu->popup(this->mapToGlobal(point));//ui->btnCreateMenu->setMenu(m_menu);}

 运行效果

这是使用QMenu的方式,还有一个直接使用QWidget的方式,把属性设置为

setWindowFlags(Qt::FramelessWindowHint|Qt::Popup);

这样弹出菜单后,点击其他地方会自动关闭此Widget,达到与弹出菜单一样的效果。

完整代码如下:

#ifndef PROVINCEWIDGET_H
#define PROVINCEWIDGET_H#include <QWidget>class QLineEdit;
class QListView;class ProvinceWidget : public QWidget
{Q_OBJECT
public:explicit ProvinceWidget(QWidget *parent = nullptr);void initView();void initConnect();void setClearFocus();signals:void signalChangeScale(int scale);protected:void paintEvent(QPaintEvent *event) override;public slots:void slotReturnPressed();void slotEditingFinished();void slotClicked(const QModelIndex &index);private:QListView *m_listView;QLineEdit *m_lineEdit;};#endif // PROVINCEWIDGET_H

#include "provincewidget.h"
#include <QGraphicsDropShadowEffect>
#include <QPainter>
#include <QtMath>
#include <QStyleOption>
#include <QBitmap>
#include <QApplication>
#include <QStringListModel>
#include <QVBoxLayout>
#include <QDebug>
#include <QListView>
#include <QLineEdit>ProvinceWidget::ProvinceWidget(QWidget *parent): QWidget{parent},m_listView(new QListView(this)),m_lineEdit(new QLineEdit(this))
{setWindowFlags(Qt::FramelessWindowHint|Qt::Popup);initView();initConnect();
}void ProvinceWidget::initView()
{QString strLineEditStyle = QString("QLineEdit{background-color:#E9E9EA;color:#6D6E6B;padding-left:20px;border-radius:8px;}""QLineEdit:hover{background-color:#E9E9EA;border-radius:8px;border:2px solid rgba(47, 137, 252, 1);}""QLineEdit:focus{background-color:#E9E9EA;border-radius:8px;border:2px solid rgba(47, 137, 252, 1);}""QLineEdit:disabled{background-color:#F0F0F0;border-radius:8px;}");QFont font = qApp->font();font.setPixelSize(14);m_lineEdit->setFont(font);m_lineEdit->setMaximumSize(QSize(108, 24));m_lineEdit->setMinimumSize(QSize(108, 24));m_lineEdit->setStyleSheet(strLineEditStyle);// 使用QListView显示一个简单的列表QStringListModel* model = new QStringListModel();model->setStringList({QStringLiteral("广东"), QStringLiteral("广西"), QStringLiteral("海南"),QStringLiteral("云南"), QStringLiteral("浙江"), QStringLiteral("江西"),QStringLiteral("北京"), QStringLiteral("黑龙江")});m_listView->setModel(model);//margin item离外边框的间距 padding 内容与item项的边框QString listViewStyle = QString("QListView{color:#6D6E6B; background-color:white;border:none;outline:none;}""QListView::item{height:24px;background:gray;margin-top:3px; margin-right:10px;margin-bottom:4px; margin-left:10px;padding-left:20px;padding-right:10px;color:#333333;border:none;outline:none;}""QListView::item:hover{background:#2F89FC;color:#ffffff;border-radius:4px;border:none;outline:none;}""QListView::item:selected{background:white;color:#ff0000;border:none;outline:none;}""QListView::item:selected:!active{background:white;color:#00ff00;border:none;outline:none;}""QListView::item:selected:active{background:white;color:#0000ff;border:none;outline:none;}");QString listViewStyle2 = QString("QListView{color:#6D6E6B; background-color:white;border:none;outline:none;}""QListView::item{height:24px;background:white;margin-top:3px; margin-right:10px;margin-bottom:4px; margin-left:10px;padding-left:20px;padding-right:10px;color:#333333;border:none;outline:none;}""QListView::item:hover{background:#2F89FC;color:#ffffff;border-radius:4px;border:none;outline:none;}""QListView::item:selected{background:white;color:#ff0000;border:none;outline:none;}""QListView::item:selected:!active{background:white;color:#00ff00;border:none;outline:none;}""QListView::item:selected:active{background:white;color:#0000ff;border:none;outline:none;}");m_listView->setStyleSheet(listViewStyle2);QVBoxLayout *layout = new QVBoxLayout();layout->setContentsMargins(0, 1, 0, 0);layout->setSpacing(1);layout->addWidget(m_listView);layout->addWidget(m_lineEdit);setLayout(layout);
}void ProvinceWidget::initConnect()
{connect(m_lineEdit, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));connect(m_lineEdit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished()));connect(m_listView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slotClicked(const QModelIndex &)));
}void ProvinceWidget::setClearFocus()
{m_listView->clearFocus();m_listView->clearSelection();m_lineEdit->clearFocus();
}void ProvinceWidget::paintEvent(QPaintEvent *event)
{Q_UNUSED(event);
//    QPainterPath path;
//    path.setFillRule(Qt::WindingFill);
//    path.addRoundedRect(5, 5, this->width() - 5 * 2, this->height() - 5 * 2, 3, 3);
//    painter.fillPath(path, QBrush(Qt::red));//绘制样式QStyleOption opt;opt.initFrom(this);QPainter p(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);//绘制样式QBitmap bmp(this->size());bmp.fill();QPainter painter(&bmp);painter.setPen(Qt::NoPen);painter.setBrush(Qt::black);painter.setRenderHint(QPainter::Antialiasing);//设置边框为圆角12pxpainter.drawRoundedRect(bmp.rect(), 8, 8);setMask(bmp);//再画颜色块QRect tmpRect = QRect(0, 0, this->width(), this->height());QBrush brush = QBrush(QColor("#ffffff"));p.setPen(Qt::NoPen);  //去掉边框线p.setBrush(brush);p.drawRect(tmpRect);//    QColor color(Qt::gray);
//    for (int i = 0; i < 5; i++)
//    {
//        QPainterPath path;
//        path.setFillRule(Qt::WindingFill);
//        path.addRoundedRect(5 - i, 5 - i, this->width() - (5 - i) * 2, this->height() - (5 - i) * 2, 3 + i, 3 + i);
//        color.setAlpha(80 - qSqrt(i) * 40);
//        painter.setPen(color);
//        painter.drawPath(path);
//    }}void ProvinceWidget::slotReturnPressed()
{int scale = m_lineEdit->text().toInt();qDebug() << "slotReturnPressed===========================" << scale;emit signalChangeScale(scale);
}void ProvinceWidget::slotEditingFinished()
{int scale = m_lineEdit->text().toInt();qDebug() << "slotEditingFinished===========================" << scale;
}void ProvinceWidget::slotClicked(const QModelIndex &index)
{QString data = index.data().toString();int scale = data.left(data.size() - 1).toInt();qDebug() << "PopupScaleList::slotClicked==========data======" << data << data.size() << scale;emit signalChangeScale(scale);
}

#ifndef CUSTOMMENU_H
#define CUSTOMMENU_H#include <QMainWindow>
#include "provincewidget.h"class QMenu;QT_BEGIN_NAMESPACE
namespace Ui { class CustomMenu; }
QT_END_NAMESPACEclass CustomMenu : public QMainWindow
{Q_OBJECTpublic:CustomMenu(QWidget *parent = nullptr);~CustomMenu();void initData();void initConnect();public slots:void slotCreateMenu();void slotPopupMenu();void slotTriggered(QAction *action);private:Ui::CustomMenu *ui;ProvinceWidget *provinceWidget{nullptr};QMenu *m_menu{nullptr};};
#endif // CUSTOMMENU_H

#include "custommenu.h"
#include "ui_custommenu.h"
#include "playwidget.h"
#include <QWidgetAction>
#include <QMenu>
#include <QSlider>
#include <QHBoxLayout>
#include <QDebug>
#include <QLineEdit>CustomMenu::CustomMenu(QWidget *parent): QMainWindow(parent), ui(new Ui::CustomMenu)
{ui->setupUi(this);initData();initConnect();
}CustomMenu::~CustomMenu()
{delete ui;
}void CustomMenu::initData()
{provinceWidget = new ProvinceWidget(this);provinceWidget->setObjectName(QString::fromUtf8("provinceWidget"));provinceWidget->setMinimumSize(QSize(108, 280));provinceWidget->setMaximumSize(QSize(108, 280));QString strLineEditStyle = QString("QLineEdit{background-color:#E9E9EA;color:#6D6E6B;border-radius:8px;}""QLineEdit:hover{background-color:#E9E9EA;border-radius:8px;border:2px solid rgba(47, 137, 252, 1);}""QLineEdit:focus{background-color:#E9E9EA;border-radius:8px;border:2px solid rgba(47, 137, 252, 1);}""QLineEdit:disabled{background-color:#F0F0F0;border-radius:8px;}");QFont font = qApp->font();font.setPixelSize(12);QLineEdit *pLineEdit = new QLineEdit(this);pLineEdit->setFont(font);pLineEdit->setMaximumSize(QSize(86, 24));pLineEdit->setMinimumSize(QSize(86, 24));pLineEdit->setStyleSheet(strLineEditStyle);//播放项QWidgetAction *pWdtAction = new QWidgetAction(this);//播放项界面,继承自QWidget的类PlayWidget *playWdt = new PlayWidget(this);playWdt->setMinimumSize(QSize(200, 50));pWdtAction->setDefaultWidget(playWdt);//创建一个包含声音调整控件的界面项QWidgetAction *pVoice = new QWidgetAction(this);QWidget *pVoiceWdt = new QWidget(this);QSlider *pSlider = new QSlider(Qt::Horizontal);QHBoxLayout *layout = new QHBoxLayout(pVoiceWdt);layout->addWidget(pSlider);layout->addWidget(pLineEdit);pVoiceWdt->setLayout(layout);pVoice->setDefaultWidget(pVoiceWdt);//生成菜单栏if(m_menu == nullptr) {m_menu = new QMenu(this);m_menu->addAction(pWdtAction);m_menu->addSeparator();m_menu->addAction(pVoice);m_menu->addAction(QStringLiteral("显示歌词"));m_menu->addAction(QStringLiteral("锁定歌词"));m_menu->addSeparator();m_menu->addAction(QStringLiteral("选项设置"));m_menu->addSeparator();m_menu->addAction(QStringLiteral("登陆"));m_menu->addAction(QStringLiteral("退出"));}
}void CustomMenu::initConnect()
{connect(ui->btnCreateMenu, SIGNAL(clicked()), this, SLOT(slotCreateMenu()));connect(ui->btnPopupMenu, SIGNAL(clicked()), this, SLOT(slotPopupMenu()));connect(m_menu, SIGNAL(triggered(QAction *)), this, SLOT(slotTriggered(QAction *)));
}void CustomMenu::slotCreateMenu()
{QPoint point = ui->btnCreateMenu->pos();point.setY(point.y() + 50);m_menu->popup(this->mapToGlobal(point));//ui->btnCreateMenu->setMenu(m_menu);}void CustomMenu::slotPopupMenu()
{QPoint point = ui->btnPopupMenu->pos();point.setY(point.y() + 50);QPoint mapPoint = mapToGlobal(point);provinceWidget->setClearFocus();provinceWidget->move(mapPoint);provinceWidget->show();
}void CustomMenu::slotTriggered(QAction *action)
{qDebug() << "slotCreateMenu====================" << action->text();
}
#include "custommenu.h"#include <QApplication>
#include <QFont>int main(int argc, char *argv[])
{QApplication a(argc, argv);QFont defaultFont = qApp->font();defaultFont.setFamily("Microsoft YaHei");qApp->setFont(defaultFont);CustomMenu w;w.show();return a.exec();
}

运行效果:

 

参考:

https://www.cnblogs.com/lingluotianya/p/3789245.html
https://blog.csdn.net/yyz_1987/article/details/130986313

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/146513.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring注册Bean系列--方法1:@Component

原文网址&#xff1a;Spring注册Bean系列--方法1&#xff1a;Component_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Spring注册Bean的方法&#xff1a;Component。 注册Bean的方法我写了一个系列&#xff0c;见&#xff1a;Spring注册Bean(提供Bean)系列--方法大全_IT利刃出鞘…

前期开发用最内聚环境,最直观简单的方法管理代码

代码稍微一多我们就会思考代码如何去规划和管理&#xff0c;首先想到MVN等管理工具去帮助我们&#xff0c;结果配置了好长时间感觉不是很方便。首先因为没有系统去了解这个工具的使用方法&#xff0c;另外发现IDEA在原本松散的工具之间以插件的形式做了一定的配置&#xff0c;将…

数据分析三剑客之一:Numpy详解及实战

1 NumPy介绍 NumPy 软件包是Python生态系统中数据分析、机器学习和科学计算的主力军。它极大地简化了向量和矩阵的操作处理。Python的一些主要软件包&#xff08;如 scikit-learn、SciPy、pandas 和 tensorflow&#xff09;都以 NumPy 作为其架构的基础部分。除了能对数值数据…

基于Java的城市天然气费管理系统的设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

QT:鼠标画线(双画布)

widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPoint> //点 #include <QMouseEvent> //鼠标事件 #include <QPaintEvent> //绘图事件class Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent 0);~Wi…

大模型 Decoder 的生成策略

本文将介绍以下内容&#xff1a; IntroductionGreedy Searchbeam searchSamplingTop-K SamplingTop-p (nucleus) sampling总结 一、Introduction 1、简介 近年来&#xff0c;由于在数百万个网页数据上训练的大型基于 Transformer 的语言模型的兴起&#xff0c;开放式语言生…

[题]修剪草坪 #单调队列优化

题目 洛谷上的题目 Acwing上的题目 根据y总的一波分析&#xff0c;我们得出……公式就是一切…… 所以&#xff0c;我要学会推公式…… 推公式…… 公式…… #include<bits/stdc.h> using namespace std; typedef long long ll; const int N 1e5 10; int n, m; ll s[N…

Matlab随机数的产生

目录 1、常见分布随机数的产生 1.1 二项分布 1.2 泊松分布 1.3 几何分布 1.4 均匀分布&#xff08;离散&#xff0c;等可能分布&#xff09; 1.5 均匀分布&#xff08;连续型等可能&#xff09; 1.6 指数分布&#xff08;描述“寿命”问题&#xff09; 1.7 正态分布 1.8…

支持向量机SVM:从数学原理到实际应用

目录 一、引言背景SVM算法的重要性 二、SVM基础线性分类器简介什么是支持向量&#xff1f;超平面和决策边界SVM的目标函数 三、数学背景和优化拉格朗日乘子法&#xff08;Lagrange Multipliers&#xff09;KKT条件核技巧&#xff08;Kernel Trick&#xff09;双重问题和主问题&…

[JAVAee]MyBatis

目录 MyBatis简介 MyBatis的准备工作 框架的添加 连接数据库字符串的配置 MyBatis中XML路径的配置 ​编辑 MyBatis的使用 各层的实现 进行数据库操作 增加操作 拓展 修改操作 删除操作 查询操作 结果映射 单表查询 多表查询 like模糊查询 动态SQL / MyBa…

传输层协议—UDP协议

传输层协议—UDP协议 文章目录 传输层协议—UDP协议传输层再谈端口号端口号范围划分pidofnetstat UDP协议端格式UDP报文UDP特点UDP缓冲区基于UDP的应用层协议 传输层 在学习HTTP/HTTPS等应用层协议时&#xff0c;为了方便理解&#xff0c;可以简单认为HTTP将请求和响应直接发送…

【算法优选】双指针专题——贰

文章目录 &#x1f60e;前言&#x1f332;[快乐数](https://leetcode.cn/problems/happy-number/)&#x1f6a9;题目描述&#x1f6a9;题⽬分析&#xff1a;&#x1f6a9;算法思路&#xff1a;&#x1f6a9;代码实现&#xff1a; &#x1f38b;[盛水最多的容器](https://leetco…

CocosCreator3.8研究笔记(二十二)CocosCreator 动画系统-动画剪辑和动画组件介绍

国庆假期&#xff0c;闲着没事&#xff0c;在家研究技术~ 大家都知道在Cocos Creator3.x 的版本的动画编辑器中&#xff0c;可以实现不用写一行代码就能实现各种动态效果。 Cocos Creator动画编辑器中主要实现关键帧动画&#xff0c;不仅支持位移、旋转、缩放、帧动画&#xff…

【算法】算法基础课模板大全

一、基础算法 快速排序算法模板 void quick_sort(int q[], int l, int r) {//递归的终止情况if (l > r) return;//选取分界线。这里选数组中间那个数int i l - 1, j r 1, x q[l r >> 1];//划分成左右两个部分while (i < j){do i ; while (q[i] < x);do …

正点原子嵌入式linux驱动开发——TF-A初探

上一篇笔记中&#xff0c;正点原子的文档简单讲解了一下什么是TF-A&#xff0c;并且也学习了如何编译TF-A。但是TF-A是如何运行的&#xff0c;它的一个运行流程并未涉及。TF-A的详细运行过程是很复杂的&#xff0c;涉及到很多ARM处理器底层知识&#xff0c;所以这一篇笔记的内容…

PHP 反序列化漏洞:__PHP_Incomplete_Class 与 serialize(unserialize($x)) !== $x;

文章目录 参考环境声明__PHP_Incomplete_Class灵显为什么需要 __PHP_Incomplete_Class&#xff1f;不可访问的属性 serialize(unserialize($x)) $x;serialize(unserialize($x)) ! $x;雾现__PHP_Incomplete_Class 对象与其序列化文本的差异试构造 __PHP__Incomplete_Class 对象…

UE5.1编辑器拓展【二、脚本化资产行为,快速更改资产名字,1.直接添加前缀或后缀2.通过资产类判断添加修改前缀】

目录 了解相关的函数 第一种做法&#xff1a;自定义添加选择资产的前缀或后缀 代码 效果 第二种做法&#xff1a;通过映射来获取资产类型添加前缀和修改前缀 映射代码 代码 效果 在之前一章中&#xff0c;我们创建了插件&#xff0c;用来扩展编辑器的使用&#xff1a; …

VS Code 如何搭建 C/C++开发环境

目录 VScode是什么? VScode的下载和安装? 2.1 下载和安装 安装&#xff1a; 2.2 环境的介绍 环境介绍&#xff1a;​编辑 安装中文插件&#xff1a; VScode配置 C/C 开发环境 3.1 下载和配置MinGW-w64 编译器套件 下载&#xff1a; 配置MinGW64&#xff1a; 3.2 安…

加入PreAuthorize注解鉴权之后NullPointerException报错

记录一次很坑的bug&#xff0c;加入PreAuthorize注解鉴权之后NullPointerException报错&#xff0c;按理来说没有权限应该403报错&#xff0c;但是这个是500报错&#xff0c;原因是因为controller层的service注入失败&#xff0c;然而我去掉注解后service注入成功&#xff0c;并…

python之股票财务分析

#import akshare as ak import pandas as pd import matplotlib.pyplot as plt symbol1"资产负债表" symbol2"利润表" symbol3"现金流量表" #df1ak.stock_financial_report_sina(stock"601633",symbolsymbol1) #df2ak.stock_financial…