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.xdnf.cn/news/146987.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

此芯科技加入百度飞桨硬件生态共创计划,加速端侧AI生态布局

近日&#xff0c;此芯科技&#xff08;上海&#xff09;有限公司&#xff08;以下简称“此芯科技”&#xff09;与百度签署硬件生态共创计划合作协议&#xff0c;正式加入由百度发起的硬件生态共创计划。双方将共同推动端侧AI和大模型在个人计算、车载计算以及元宇宙计算等领域…

拒绝水文!八大排序(二)【适合初学者】冒泡排序和选择排序

文章目录 冒泡排序选择排序 大家好&#xff0c;我是纪宁。 这篇文章介绍八大排序中思路最简单&#xff0c;但效率也是最低的两种排序算法&#xff01; 冒泡排序 冒泡排序&#xff0c;可以说是每个人在接触编程时最先学会的一种排序。 冒泡排序基本思想 冒泡排序&#xff08;…

Rust 围炉札记

文章目录 一、安装二、文档 一、安装 rust 安装 卸载&#xff08;自定义路径&#xff09; Rust配置镜像源 Rust in Visual Studio Code Rust 官网 Rust 中文网 windows系统下Rust环境搭建以及vscode调试环境配置 二、文档 Rust 菜鸟教程 Rust 官方文档中文教程 Rust 包管理…

Docker从认识到实践再到底层原理(七)|Docker存储卷

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…

【1++的Linux】之进程(五)

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的Linux】 文章目录 一&#xff0c;什么是进程替换二&#xff0c;替换函数三&#xff0c;实现我们自己的shell 一&#xff0c;什么是进程替换 我们创建出来进程是要其做事情的&#xff0c;它可…

【爬虫】用wget命令爬虫的简易教程

文章目录 1. 获取登录的请求2. 用postman模拟登录请求3. 用wget模拟登录请求并保存cookie4. 开始爬取网站5. 查看爬取结果6. 网站爬虫简易教程 爬取需要登录的网站的资源 背景&#xff1a;对于一些网站需要使用用户名和密码登录并且使用了https&#xff0c;我们如果不通过凭证将…

网络工程师对口的岗位是什么

大家好&#xff0c;我是网络工程师成长日记实验室的郑老师&#xff0c;您现在正在查看的是网络工程师成长日记专栏&#xff0c;记录网络工程师日常生活的点点滴滴 网络工程师可以从事哪些职位呢&#xff1f;其实网络工程师最对应的最对口的这个岗位就是高级网络工程师、系统集成…

番外6:下载+安装+配置Linux

#########配置Linux---后续 step08: 点击编辑虚拟机设置&#xff0c;选择下载好的映像文件.iso进行挂载&#xff1b; step09: 点击编辑虚拟机选项&#xff0c;选择UEFI启动模式并点击确定&#xff1b; step10: 点击开启虚拟机&#xff0c;选择Install rhel &#xff1b; 备注&…

飞桨EasyDL-Mac本地部署离线SDK-Linux集成Python

前言&#xff1a;本文对使用飞桨EasyDL桌面版实现本地部署物体检测做一下说明 一、训练模型 如何使用飞桨EasyDL桌面版这里就不再赘述&#xff0c;直接参照官方文档进行物体检测模型训练。 飞桨EasyDL桌面版-用零代码开发实现物体检测https://ai.baidu.com/ai-doc/EASYDL/Tl2…

探索社会工程的深度:从定义到高级攻击策略

在广阔的网络安全领域&#xff0c;社会工程作为一种微妙的威胁而出现&#xff0c;它利用人类的漏洞来访问敏感信息或实施欺诈。网络安全背景下的社会工程的定义很明确&#xff1a;它包括使用欺骗手段操纵个人泄露机密或个人信息&#xff0c;然后将这些信息用于欺诈目的。 此类…

实现水平垂直居中的十种方式

本文节选自我的博客&#xff1a;实现水平垂直居中的十种方式 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是MilesChen&#xff0c;偏前端的全栈开发者。&#x1f4dd; CSDN主页&#xff1a;爱吃糖的猫&#x1f525;&#x1f4e3; 我的博客&#xff1a;爱吃糖的猫&…

AJAX--Express速成

一、基本概念 1、AJAX(Asynchronous JavaScript And XML)&#xff0c;即为异步的JavaScript 和 XML。 2、异步的JavaScript 它可以异步地向服务器发送请求&#xff0c;在等待响应的过程中&#xff0c;不会阻塞当前页面。浏览器可以做自己的事情。直到成功获取响应后&#xf…

Scala第十五章节

Scala第十五章节 1. 递归 2. 案例一: 求阶乘 3. 案例二: 斐波那契数列 4. 案例三: 打印目录文件 scala总目录 文档资料下载

淘宝天猫复制商品链接粘贴到草柴查优惠券iPhone苹果手机粘贴弹窗怎么关闭?

经常在淘宝、天猫、京东网购&#xff0c;挑选商品后复制链接&#xff0c;到草柴APP查询要购买商品的优惠券和返利&#xff0c;iPhone苹果手机每次粘贴复制的商品链接都弹窗提示特别烦人。接下来分享如何关闭草柴APP复制粘贴提醒的弹窗&#xff1b; 如何永久关闭iPhone苹果手机复…

云服务器租用价格表概览_阿里云腾讯云华为云

云服务器租用价格多少钱一年&#xff1f;阿腾云分享阿里云、腾讯云和华为云的云服务器租用价格表&#xff1a;阿里云2核2G服务器108元一年起、腾讯云2核2G3M带宽轻量服务器95元一年、华为云2核2G3M云耀L实例89元一年起&#xff0c;阿腾云分享更多关于云服务器租用价格明细&…

前端JavaScript入门到精通,javascript核心进阶ES6语法、API、js高级等基础知识和实战 —— Web APIs(四)

思维导图 一、日期对象 1.1 实例化 实例化&#xff0c;默认得到当前时间&#xff0c;也可以指定时间 1.2 日期对象方法 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible&q…

[Realtek sdk-3.4.14b]RTL8197FH-VG 2.4G to WAN吞吐量低于60%的问题分析及解决方案

问题描述 RTL8197FH-VG 2.4G wifi to WAN吞吐量低于65%的标准,正常2T2R的wifi 300Mbps x 65% = 195Mbps,但是实际只能跑到160Mbps,这个时候CPU的idl已经为0,sirq占用率达到98%左右 网络拓扑 一台PC通过2.4G WiFi连接到RTL8197FH-VG,另外一台PC直接通过WAN口连接到RTL8197…

milvus 结合Thowee 文本转向量 ,新建表,存储,搜索,删除

1.向量数据库科普 【上集】向量数据库技术鉴赏 【下集】向量数据库技术鉴赏 milvus连接 from pymilvus import connections, FieldSchema, CollectionSchema, DataType, Collection, utility connections.connect(host124.****, port19530)2.milvus Thowee 文本转向量 使用 …

web:[RoarCTF 2019]Easy Calc

题目 进入页面是一个计算器的页面 随便试了一下 查看源代码看看有什么有用的信息 访问一下这个calc.php 进行代码审计 <?php error_reporting(0); if(!isset($_GET[num])){show_source(__FILE__); }else{$str $_GET[num];$blacklist [ , \t, \r, \n,\, ", , \[, \]…

C语言编译与链接过程详解

C语言编译与链接过程详解 源文件 main.c #include <stdio.h>extern int data; extern int add(int a,int b);int a1; int a2 0; int a3 10;static int b1; static int b2 0; static int b3 20;int main() {int c1;int c2 0;int c3 30;static int d1;static int …