Qt自定义下拉列表-可为选项设置标题、可禁用选项

         在Qt中,ComboBox(组合框)是一种常用的用户界面控件,它提供了一个下拉列表,允许用户从预定义的选项中选择一个。在项目开发中,如果简单的QComboBox无法满足需求,可以通过自定义QComboBox来实现更复杂的功能。本文介绍一个自定义的下拉列表,并为选项设置标题、可禁用选项。

一、简述

         本示例介绍一个Qt自定义下拉列表,可为选项设置标题、可禁用选项。

二、 设计思路             
  1. 继承QComboBox类: 创建一个新的类,继承自QComboBox类。在该类中,可以重写QComboBox的方法以实现自定义功能。

  2. 使用QListWidget和QListWidgetItem: QComboBox默认使用QStandardItemModel来管理下拉列表的数据。扩展时使用QListWidget的QListModel来替代QStandardItemModel。在QListWidget的QListWidgetItem中,可以自定义每个列表项的显示和交互逻辑。

  3. 使用自定义代理类: 通过自定义QItemDelegate类,可以实现对下拉列表中每个项的自定义绘制和交互逻辑。可以通过setItemDelegate方法将自定义的代理类设置为QComboBox的项代理。

三、效果 

四、核心代码  
1、头文件
#ifndef CustomCombo_H
#define CustomCombo_H#include <QComboBox>
#include <QListWidget>
#include <QItemDelegate>class CustomCombo : public QComboBox
{Q_OBJECTpublic:CustomCombo(QWidget *parent=0);QListWidget *list() const{ return list_; }void addTitle(const QString &text);void addItem (const QString &text);void setIsTitle(int ind, bool b);void setSelectable(int ind, bool b);private:void resetCurrentInd();private:QListWidget *list_;
};//------------------------------------------------------------------------------------------------------------
class CustomComboItem : public QListWidgetItem {
public:CustomComboItem(CustomCombo *combo, const QString &str);virtual ~CustomComboItem() { }CustomCombo *combo() const { return combo_; }void setIsTitle(bool b);inline bool isTitle() const { return isTitle_; }void setSelectable(bool selectable);inline bool isSelectable() const {return (flags() & (Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled));}private:CustomCombo *combo_;bool isTitle_;bool selectable_;
};//------------------------------------------------------------------------------------------------------------
class CustomComboTitle : public CustomComboItem {
public:CustomComboTitle(CustomCombo *combo, const QString &str) :CustomComboItem(combo, str) {setSelectable(false);setIsTitle(true);}
};//------------------------------------------------------------------------------------------------------------
class CustomComboDelegate : public QItemDelegate {
public:CustomComboDelegate(CustomCombo *combo) ;void paint(QPainter *painter, const QStyleOptionViewItem &option,const QModelIndex &index) const override;QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;QStyleOptionMenuItem getStyleOption(const QStyleOptionViewItem &option,const QModelIndex &index, CustomComboItem *item) const;static bool isSeparator(const QModelIndex &index) {return (index.data(Qt::AccessibleDescriptionRole).toString() == "separator");}private:CustomCombo *combo_;
};#endif
2、实现代码
#include "CustomCombo.h"#include <QPainter>
#include <QApplication>CustomCombo::CustomCombo(QWidget *parent) :QComboBox(parent), list_(nullptr)
{list_ = new QListWidget;list_->setItemDelegate(new CustomComboDelegate(this));setModel(list_->model());setView(list_);
}void CustomCombo::addTitle(const QString &text)
{list_->addItem(new CustomComboTitle(this, text));resetCurrentInd();
}void CustomCombo::addItem(const QString &text)
{list_->addItem(new CustomComboItem(this, text));resetCurrentInd();
}void CustomCombo::setIsTitle(int ind, bool b)
{auto *item = dynamic_cast<CustomComboItem *>(list_->item(ind));item->setIsTitle(b);resetCurrentInd();
}void CustomCombo::setSelectable(int ind, bool b)
{auto *item = dynamic_cast<CustomComboItem *>(list_->item(ind));item->setSelectable(b);resetCurrentInd();
}void CustomCombo::resetCurrentInd()
{auto *item = static_cast<CustomComboItem *>(list()->item(currentIndex()));if (item->isSelectable())return;for (int i = 0; i < count(); ++i) {auto *item = static_cast<CustomComboItem *>(list()->item(i));if (item->isSelectable()) {setCurrentIndex(i);break;}}
}//CustomComboItem
//------------------------------------------------------------------------------------------------------------
CustomComboItem::CustomComboItem(CustomCombo *combo, const QString &str) :QListWidgetItem(str), combo_(combo), isTitle_(false), selectable_(true){}void CustomComboItem::setIsTitle(bool b) {isTitle_ = b;if (isTitle_)setSelectable(false);
}void CustomComboItem::setSelectable(bool selectable) {selectable_ = selectable;if (selectable_)setFlags(flags() |  (Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled));elsesetFlags(flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled));
}//CustomComboDelegate
//------------------------------------------------------------------------------------------------------------
CustomComboDelegate::CustomComboDelegate(CustomCombo *combo) :combo_(combo) {}void CustomComboDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,const QModelIndex &index) const {auto *item = static_cast<CustomComboItem *>(combo_->list()->item(index.row()));QStyleOptionMenuItem opt = getStyleOption(option, index, item);painter->fillRect(opt.rect, opt.palette.window());combo_->style()->drawControl(QStyle::CE_MenuItem, &opt, painter, combo_);
}QSize CustomComboDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const {auto *item = static_cast<CustomComboItem *>(combo_->list()->item(index.row()));QStyleOptionMenuItem opt = getStyleOption(option, index, item);return combo_->style()->sizeFromContents(QStyle::CT_MenuItem, &opt, option.rect.size(), combo_);
}QStyleOptionMenuItem CustomComboDelegate::getStyleOption(const QStyleOptionViewItem &option,const QModelIndex &index, CustomComboItem *item) const {QStyleOptionMenuItem menuOption;QPalette resolvedpalette = option.palette.resolve(QApplication::palette("QMenu"));QBrush textBrush = resolvedpalette.brush(QPalette::Active, QPalette::Text);QVariant value = index.data(Qt::ForegroundRole);if (value.canConvert<QBrush>())textBrush = qvariant_cast<QBrush>(value);if (! item->isSelectable())textBrush = resolvedpalette.brush(QPalette::Disabled, QPalette::Text);if (item->isTitle())textBrush = resolvedpalette.brush(QPalette::Active, QPalette::HighlightedText);resolvedpalette.setBrush(QPalette::WindowText, textBrush);resolvedpalette.setBrush(QPalette::ButtonText, textBrush);resolvedpalette.setBrush(QPalette::Text      , textBrush);menuOption.palette = resolvedpalette;menuOption.state   = QStyle::State_None;if (combo_->window()->isActiveWindow())menuOption.state = QStyle::State_Active;if ((option.state & QStyle::State_Enabled) && (index.model()->flags(index) & Qt::ItemIsEnabled))menuOption.state |= QStyle::State_Enabled;elsemenuOption.palette.setCurrentColorGroup(QPalette::Disabled);if (option.state & QStyle::State_Selected)menuOption.state |= QStyle::State_Selected;menuOption.checkType = QStyleOptionMenuItem::NonExclusive;menuOption.checked   = (combo_->currentIndex() == index.row());if (isSeparator(index))menuOption.menuItemType = QStyleOptionMenuItem::Separator;elsemenuOption.menuItemType = QStyleOptionMenuItem::Normal;QBrush bgBrush = menuOption.palette.brush(QPalette::Window);if (index.data(Qt::BackgroundRole).canConvert<QBrush>())bgBrush = qvariant_cast<QBrush>(index.data(Qt::BackgroundRole));if (item->isTitle())bgBrush = resolvedpalette.brush(QPalette::Active, QPalette::Highlight);menuOption.palette.setBrush(QPalette::All, QPalette::Window, bgBrush);menuOption.text = index.model()->data(index, Qt::DisplayRole).toString();menuOption.tabWidth     = 0;menuOption.maxIconWidth = option.decorationSize.width() + 4;menuOption.menuRect     = option.rect;menuOption.rect         = option.rect;menuOption.font         = combo_->font();menuOption.fontMetrics  = QFontMetrics(menuOption.font);if (item->isTitle())menuOption.font.setBold(true);return menuOption;
}

        以上本文实现自定义ComboBox的方法,实际上自定义下拉列表可以根据具体的需求进行定制和扩展,适应不同的应用场景。

五、使用示例

以下是一个简单的示例代码,演示了如何在Qt中使用此控件:

#include "mainwindow.h"
#include "CustomCombo.h"
#include <QVBoxLayout>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{QWidget *pWidget = new QWidget;QHBoxLayout *layout = new QHBoxLayout(pWidget);CustomCombo *combo = new CustomCombo;combo->addTitle("文学类");combo->addItem ("红楼梦");combo->addItem ("三国演义");combo->addItem ("背影");combo->addItem ("荷塘月色");combo->addTitle("科技类");combo->addItem ("几何原本");combo->addItem ("自然哲学的数学原理");combo->addItem ("天工开物");combo->addItem ("梦溪笔谈");combo->setSelectable(3, false);//禁用选项layout->addWidget(combo);setCentralWidget(pWidget);
}MainWindow::~MainWindow()
{
}

        总结一下,自定义下拉列表是Qt中常用的控件之一,用于在界面中显示下拉选择项。一般来说,自定义下拉列表可以分为以下几个步骤:

  1. 创建下拉列表按钮:使用QPushButton或QLineEdit等Qt提供的控件作为下拉列表的按钮,用于显示当前选择的选项。

  2. 创建下拉列表框:使用QFrame或QListWidget等Qt提供的控件作为下拉列表的框,用于显示所有选项。

  3. 设置下拉列表框属性:可以设置下拉列表框的大小、位置、边框等属性,以及确定是否默认展开。

  4. 添加选项:使用addItem()或insertItem()等方法向下拉列表框中添加选项。

  5. 设置选项属性:可以设置选项的文本、图标、状态等属性。

  6. 处理选项选择事件:可以通过重写下拉列表的事件处理函数来实现对选项的选择。

  7. 更新按钮显示:在选项被选择后,需要更新按钮的显示文本,以反映所选选项。

        谢谢您的阅读,希望本文能为您带来一些帮助和启发。如果您有任何问题或意见,请随时与我联系。祝您度过美好的一天!

六、源代码下载

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

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

相关文章

二级医院LIS系统源码,医学检验系统,支持DB2,Oracle,MS SQLServer等主流数据库

系统概述&#xff1a; LIS系统即实验室信息管理系统。LIS系统能实现临床检验信息化&#xff0c;检验科信息管理自动化。其主要功能是将检验科的实验仪器传出的检验数据经数据分析后&#xff0c;自动生成打印报告&#xff0c;通过网络存储在数据库中&#xff0c;使医生能够通过医…

7.消息应答

消费者完成一个任务可能需要一段时间&#xff0c;如果其中一个消费者处理一个长时间的任务并且只完成了部分突然就挂掉了&#xff0c;会发生什么情况&#xff1f; RabbitMQ一旦向消费者传递了一条消息&#xff0c;便立即将该消息标记为删除。这种情况下&#xff0c;突然有个消…

代码随想录算法训练营day6 | 242.有效的字母异位词、349. 两个数组的交集、202. 快乐数、1.两数之和

文章目录 哈希表键值 哈希函数哈希冲突拉链法线性探测法 常见的三种哈希结构集合映射C实现std::unordered_setstd::map 小结242.有效的字母异位词思路复习 349. 两个数组的交集使用数组实现哈希表的情况思路使用set实现哈希表的情况 202. 快乐数思路 1.两数之和思路 总结 今天是…

OpenCV 遍历Mat,像素操作,使用TrackBar 调整图像的亮度和对比度 C++实现

文章目录 1.使用C遍历Mat,完成颜色反转1.1 常规遍历方式1.2 迭代器遍历方式1.3指针访问方式遍历&#xff08;最快&#xff09;1.4不同遍历方式的时间对比 2.图像像素操作&#xff0c;提高图像的亮度3.TrackBar 进度条操作3.1使用TrackBar 调整图像的亮度3.2使用TrackBar 调整图…

学术研讨 | 区块链网络体系结构研讨会顺利召开

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 近日&#xff0c;国家区块链技术创新中心组织了“区块链网络体系结构研讨会”&#xff0c;会议面向跨域交互多、计算规模大、数据管理复杂、性能与扩展性要求高等特征的区块链网络的体系结构展开交流研讨&…

docker相关内容学习

一、docker的四部分 二、镜像相关命令 三、容器相关命令

视频生成【文章汇总】SVD, Sora, Latte, VideoCrafter12, DiT...

视频生成【文章汇总】SVD, Sora, Latte, VideoCrafter12, DiT... 数据集指标 【arXiv 2024】MiraData: A Large-Scale Video Dataset with Long Durations and Structured Captions【CVPR 2024】VBench : Comprehensive Benchmark Suite for Video Generative Models【arxiv 20…

学习记录——day15 数据结构 链表

链表的引入 顺序表的优缺点 1、优点:能够直接通过下标进行定位元素&#xff0c;访问效率高&#xff0c;对元素进行查找和修改比较快 2、不足:插入和删除元素需要移动大量的元素&#xff0c;效率较低 3、缺点:存储数据元素有上限&#xff0c;当达到MAX后&#xff0c;就不能再…

[python]数字与字符串

目录 Python 数字类型转换 Python 数字运算 Python字符串操作 修改 查询 Python 数字数据类型用于存储数值。 数据类型是不允许改变的&#xff0c;这就意味着如果改变数字数据类型的值&#xff0c;将重新分配内存空间。 Python 支持三种不同的数值类型&#xff1a; 整型…

javafx的ListView代入项目的使用

目录 1. 创建一个可观察的列表&#xff0c;用于存储ListView中的数据,这里的User是包装了用户的相关信息。 2.通过本人id获取friendid&#xff0c;及好友的id&#xff0c;然后用集合接送&#xff0c;更方便直观一点。 3.用for遍历集合&#xff0c;逐个添加。 4.渲染器&…

文件包涵条件竞争(ctfshow82)

Web82 利用 session.upload_progress 包含文件漏洞 <!DOCTYPE html> <html> <body> <form action"https://09558c1b-9569-4abd-bf78-86c4a6cb6608.challenge.ctf.show//" method"POST" enctype"multipart/form-data"> …

grafana对接zabbix数据展示

目录 1、初始化、安装grafana 2、浏览器访问 3、安装zabbix 4、zabbix数据对接grafana 5、如何导入模板&#xff1f; ① 设置键值 ② 在zabbix web端完成自定义监控项 ③ garafana里添加nginx上面的的三个监控项 6、如何自定义监控项&#xff1f; 以下实验沿用上一篇z…

【React学习打卡第三天】

Redux快速上手、三个核心概念、React组件使用、修改store的数据、提交action传参、异步操作、Redux调试 一、Redux快速上手1.概念2.快速体验(纯redux计数案例&#xff09; 3.三个核心概念 二、Redux与React-环境准备1.配套工具2.配置基础环境3.store目录结构设计![在这里插入图…

SpringMvc有几个上下文

你好&#xff0c;我是柳岸花明。 SpringMVC作为Spring框架的重要组成部分&#xff0c;其启动流程和父子容器机制是理解整个框架运行机制的关键。本文将通过一系列详细的流程图&#xff0c;深入剖析SpringMVC的启动原理与父子容器的源码结构。 SpringMVC 父子容器 父容器的创建 …

数据结构初阶(c语言)-双向链表

这里首先纠正上篇文章一个错误&#xff0c;链表的一个有效数据点应该称为结点而不是节点。 一&#xff0c;双向链表的概念与结构 1.1概念与结构示意图 我们所说的双向链表全称为带头双向循环链表&#xff0c;也就是说此链表带有哨兵位结点(不存放任何数据的结点&#xff0c;且…

【Git多人协作开发】知识点总结

目录 知识点总结 1.创建dev分支开发 1.1在本地创建 1.1在远程创建&#xff08;推荐&#xff09; 2.远程分支和本地分支建立连接☞pull和push操作 2.1情况1 2.2情况2 2.3情况3 3.本地仓库对远程仓库的拉取pull操作 3.1情况1 3.2情况2 4.将开发分支的内容合并到远程m…

【Week-G5】适用于图像翻译的pix2pix模型-Pytorch版本

文章目录 1、基础知识1.1 图像翻译1.2 CGAN1.3 U-Net1.4 Pix2Pix 2、运行代码 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 本次主要学习Pix2Pix网络&#xff0c;常用于图像翻译&#…

CVE-2020-7248 OpenWRT libubox标记二进制数据序列化漏洞(更新中)

提要 该文档会一直处于更新当中&#xff0c;当状态为完毕后&#xff0c;才是更新完成。由于网络上关于该漏洞原理的分析文档和资源实在是太少&#xff0c;而本人关于该方向也才是刚入门&#xff0c;能力有限&#xff0c;所以复现需要的时间较长&#xff0c;需要补充和学习的东西…

用Manim实现【多边形】类的实现——[上]

用Manim实现【多边形】类的实现——[上] Polygram内容是关于不同几何图形的分类&#xff0c;特别是涉及多边形&#xff08;Polygon&#xff09;及其扩展形式&#xff0c;比如多图形&#xff08;Polygram&#xff09;。在manim中有10中特征&#xff0c;接下来5种类及其特征的解…

搜维尔科技:Cyber​​glove通过其前所未有的柔性传感器技术,带来了多年的经验、专业知识和可靠性

Cyberglove 概述 新一代数据手套技术 MoCap 手套采用了原始 CyberGlove 产品 20 年经验所建立的技术&#xff0c;产生了改进的和新的特性、能力和设计&#xff0c;非常适合动作捕捉环境。 旧与新相遇&#xff0c; Cyberglove 通过其前所未有的柔性传感器技术&#xff0c;带来…