• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • Qt之QComboBox下拉框實現勾選

    標簽: C++  Qt 學習之路  qt

    QComboBox下拉界面帶勾選


    1、前言

    QComboBox每次只能選擇一個,現項目中需要可以多次勾選,不想基于第三方庫qxtlib進行開發,所以自己參考qxtcheckcombobox源碼,在此基礎上進行修改。可保持QComboBox風格,不另行設置界面。


    2、實現效果如下

    在這里插入圖片描述


    3、思路

    主體思路就是對于下拉的數據源model的數據標志位添加可勾選屬性。
    下面列舉一些Qt::ItemDataRole

    ConstantValueDescription
    Qt::FontRole6The font used for items rendered with the default delegate. (QFont)
    Qt::TextAlignmentRole7The alignment of the text for items rendered with the default delegate. (Qt::Alignment)
    Qt::BackgroundRole8The background brush used for items rendered with the default delegate. (QBrush)
    Qt::BackgroundColorRole8This role is obsolete. Use BackgroundRole instead.
    Qt::ForegroundRole9The foreground brush (text color, typically) used for items rendered with the default delegate. (QBrush)
    Qt::TextColorRole9This role is obsolete. Use ForegroundRole instead.
    Qt::CheckStateRole10This role is used to obtain the checked state of an item. (Qt::CheckState)
    Qt::InitialSortOrderRole14This role is used to obtain the initial sort order of a header view section. (Qt::SortOrder). This role was introduced in Qt 4.8.

    4、代碼干貨

    以下代碼僅供參考,可根據實際需求修改

    class DSCheckComboModel : public QStandardItemModel
    {
    	Q_OBJECT
    
    public:
    	explicit DSCheckComboModel(QObject* parent = Q_NULLPTR);
    
    	virtual Qt::ItemFlags flags(const QModelIndex& index) const;
    	virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
    	virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
    
    Q_SIGNALS:
    	void checkStateChanged();
    };
    
    class DSCheckComboBoxPrivate;
    class DSCheckComboBox : public QComboBox
    {
    	Q_OBJECT
    
    	Q_PROPERTY(QString separator READ separator WRITE setSeparator)
    	Q_PROPERTY(QString defaultText READ defaultText WRITE setDefaultText)
    	Q_PROPERTY(QStringList checkedItems READ checkedItems WRITE setCheckedItems)
    
    public:
    	DSCheckComboBox(QWidget *parent = Q_NULLPTR);
    	~DSCheckComboBox();
    
    	//隱藏下拉框
    	virtual void hidePopup();
    
    	//獲取默認文本
    	QString defaultText() const;
    	//設置默認文本
    	void setDefaultText(const QString& text);
    
    	//獲取勾選狀態
    	Qt::CheckState itemCheckState(int index) const;
    	//設置勾選狀態
    	void setItemCheckState(int index, Qt::CheckState state);
    
    	//獲取字符串分割方式
    	QString separator() const;
    	//設置字符串分割方式
    	void setSeparator(const QString& separator);
    
    	//獲取所有勾選的文本
    	QStringList checkedItems() const;
    	//獲取所有勾線的下標
    	QVariantList checkedIndexs() const;
    
    public Q_SLOTS:
    	void setCheckedItems(const QStringList& items);
    
    Q_SIGNALS:
    	void checkedItemsChanged(const QStringList& items);
    
    protected:
    	virtual bool eventFilter(QObject *watched, QEvent *event);
    	virtual void wheelEvent(QWheelEvent *e);
    
    private:
    	QScopedPointer<DSCheckComboBoxPrivate> d_ptr;
    	Q_DISABLE_COPY(DSCheckComboBox)
    	Q_DECLARE_PRIVATE(DSCheckComboBox)
    	Q_PRIVATE_SLOT(d_func(), void updateCheckedItems())
    	Q_PRIVATE_SLOT(d_func(), void toggleCheckState(int index))
    };
    
    
    DSCheckComboModel::DSCheckComboModel(QObject* parent /* = Q_NULLPTR */)
    	: QStandardItemModel(0, 1, parent) //rows,cols
    {
    }
    
    Qt::ItemFlags DSCheckComboModel::flags(const QModelIndex& index) const
    {
    	return QStandardItemModel::flags(index) | Qt::ItemIsUserCheckable;
    }
    
    QVariant DSCheckComboModel::data(const QModelIndex& index, int role /* = Qt::DisplayRole */) const
    {
    	QVariant value = QStandardItemModel::data(index, role);
    	if (index.isValid() && role == Qt::CheckStateRole && !value.isValid())
    		value = Qt::Unchecked;
    
    	return value;
    }
    
    bool DSCheckComboModel::setData(const QModelIndex& index, const QVariant& value, int role /* = Qt::EditRole */)
    {
    	bool ok = QStandardItemModel::setData(index, value, role);
    	if (ok && role == Qt::CheckStateRole)
    	{
    		emit dataChanged(index, index);
    		emit checkStateChanged();
    	}
    
    	return ok;
    }
    
    
    class DSCheckComboBoxPrivate : public QObject
    {
    	Q_DECLARE_PUBLIC(DSCheckComboBox)
    	DSCheckComboBox* q_ptr;
    
    public:
    	DSCheckComboBoxPrivate(QObject* parent = Q_NULLPTR);
    	bool eventFilter(QObject* obj, QEvent* e);
    
    	QString separator;
    	QString defaultText;
    	bool containerMousePress;
    
    	void updateCheckedItems();
    	void toggleCheckState(int index);
    };
    
    DSCheckComboBoxPrivate::DSCheckComboBoxPrivate(QObject* parent)
    	: containerMousePress(false)
    {
    	separator = QLatin1String(",");
    }
    
    bool DSCheckComboBoxPrivate::eventFilter(QObject* obj, QEvent* e)
    {
    	switch (e->type())
    	{
    	case QEvent::KeyPress:
    	case QEvent::KeyRelease:
    	{
    		QKeyEvent* keyEvent = static_cast<QKeyEvent*>(e);
    		if (obj == q_ptr && (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down))
    		{
    			q_ptr->showPopup();
    			return true;
    		}
    		else if (keyEvent->key() == Qt::Key_Enter || 
    				 keyEvent->key() == Qt::Key_Return || 
    				 keyEvent->key() == Qt::Key_Escape)
    		{
    			q_ptr->hidePopup();
    			if (keyEvent->type() != Qt::Key_Escape)
    				return true;
    		}
    	}
    	case QEvent::MouseButtonPress:
    		containerMousePress = (obj == q_ptr->view()->window());
    		break;
    	case QEvent::MouseButtonRelease:
    		containerMousePress = false;
    		break;
    	default:
    		break;
    	}
    	return false;
    }
    
    void DSCheckComboBoxPrivate::updateCheckedItems()
    {
    	QStringList items = q_ptr->checkedItems();
    	if (items.empty())
    		q_ptr->setEditText(defaultText);
    	else
    		q_ptr->setEditText(items.join(separator));
    
    	emit q_ptr->checkedItemsChanged(items);
    }
    
    void DSCheckComboBoxPrivate::toggleCheckState(int index)
    {
    	QVariant value = q_ptr->itemData(index, Qt::CheckStateRole);
    	if (value.isValid())
    	{
    		Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
    		q_ptr->setItemData(index, (state == Qt::Unchecked ? Qt::Checked : Qt::Unchecked), Qt::CheckStateRole);
    	}
    }
    
    DSCheckComboBox::DSCheckComboBox(QWidget *parent)
    	: QComboBox(parent)
    	, d_ptr(new DSCheckComboBoxPrivate)
    {
    	d_ptr->q_ptr = this;
    	setModel(new DSCheckComboModel(this));
    
    	connect(this, SIGNAL(activated(int)), this, SLOT(toggleCheckState(int)));
    	connect(model(), SIGNAL(checkStateChanged()), this, SLOT(updateCheckedItems()));
    	connect(model(), SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(updateCheckedItems()));
    	connect(model(), SIGNAL(rowsRemoved(const QModelIndex&, int, int)), this, SLOT(updateCheckedItems()));
    
    	QLineEdit* lineEdit = new QLineEdit(this);
    	lineEdit->setReadOnly(true);
    	setLineEdit(lineEdit);
    	lineEdit->disconnect(this);
    	setInsertPolicy(QComboBox::NoInsert);
    
    	installEventFilter(this);
    	view()->installEventFilter(this);
    	view()->window()->installEventFilter(this);
    	view()->viewport()->installEventFilter(this);
    }
    
    DSCheckComboBox::~DSCheckComboBox()
    {
    }
    
    void DSCheckComboBox::hidePopup()
    {
    	if (d_ptr->containerMousePress)
    		QComboBox::hidePopup();
    }
    
    Qt::CheckState DSCheckComboBox::itemCheckState(int index) const
    {
    	return static_cast<Qt::CheckState>(itemData(index, Qt::CheckStateRole).toInt());
    }
    
    void DSCheckComboBox::setItemCheckState(int index, Qt::CheckState state)
    {
    	setItemData(index, state, Qt::CheckStateRole);
    }
    
    QStringList DSCheckComboBox::checkedItems() const
    {
    	QStringList items;
    	if (model())
    	{
    		QModelIndex index = model()->index(0, modelColumn(), rootModelIndex());
    		QModelIndexList indexs = model()->match(index, Qt::CheckStateRole, Qt::Checked, -1, Qt::MatchExactly);
    		foreach(const QModelIndex& index, indexs)
    			items += index.data().toString();
    	}
    	return items;
    }
    
    QVariantList DSCheckComboBox::checkedIndexs() const
    {
    	QVariantList indexs;
    	if (model())
    	{
    		QModelIndex index = model()->index(0, modelColumn(), rootModelIndex());
    		QModelIndexList indexs_2 = model()->match(index, Qt::CheckStateRole, Qt::Checked, -1, Qt::MatchExactly);
    		foreach(const QModelIndex& index, indexs_2)
    			indexs += index.row();
    	}
    	return indexs;
    }
    
    void DSCheckComboBox::setCheckedItems(const QStringList& items)
    {
    	foreach(const QString& text, items)
    	{
    		const int index = findText(text);
    		setItemCheckState(index, index != -1 ? Qt::Checked : Qt::Unchecked);
    	}
    }
    
    bool DSCheckComboBox::eventFilter(QObject *watched, QEvent *event)
    {
    	return d_ptr->eventFilter(watched,event);
    }
    
    void DSCheckComboBox::wheelEvent(QWheelEvent *e)
    {
    	e->accept();
    }
    
    QString DSCheckComboBox::defaultText() const
    {
    	return d_ptr->defaultText;
    }
    
    void DSCheckComboBox::setDefaultText(const QString& text)
    {
    	if (d_ptr->defaultText != text)
    	{
    		d_ptr->defaultText = text;
    		d_ptr->updateCheckedItems();
    	}
    }
    
    QString DSCheckComboBox::separator() const
    {
    	return d_ptr->separator;
    }
    
    void DSCheckComboBox::setSeparator(const QString& separator)
    {
    	if (d_ptr->separator != separator)
    	{
    		d_ptr->separator = separator;
    		d_ptr->updateCheckedItems();
    	}
    }
    
    

    以上代碼大家可只做參考。

    源碼免費在此傳送門


    5、注意事項

    注意: 因為cpp中定義的Private類包含Q_OBJECT,所以需要在源文件中包含 #include “moc_DSCheckComboBox.cpp”,如果工程能正常編譯則不需要要進行后續操作
    后續操作:修改頭文件編譯條件為如下:在這里插入圖片描述

    在常規中修改如下:
    在這里插入圖片描述

    在commanderline中輸入命令:"$(QTDIR)/bin/moc.exe" "%(FullPath)" -o "./GeneratedFiles/$(Configuration)/moc_%(Filename).cpp" -D -DQT_CORE_LIB -DQT_GUI_LIB -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DUNICODE -DWIN32 -I"$(QTDIR)/include" -I"$(QTDIR)/include/QtCore" -I"$(QTDIR)/include/QtGui" -I"$(QTDIR)/include/qtmain" -I"." -I"./GeneratedFiles" -I"./GeneratedFiles/$(Configuration)"
    
    Description中輸入:Moc%27ing %(Filename)%(Extension)...
    
    OutPuts中輸入:./GeneratedFiles/$(Configuration)/moc_%(Filename).cpp
    
    AdditionnalOutPuts中輸入:$(QTDIR)/bin/moc.exe;%(FullPath);%(AdditionalInputs)
    

    具體為什么這里就不過多說明,可度娘。

    版權聲明:本文為zl_95520原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/zl_95520/article/details/110533247

    智能推薦

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    猜你喜歡

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    styled-components —— React 中的 CSS 最佳實踐

    https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...

    基于TCP/IP的網絡聊天室用Java來實現

    基于TCP/IP的網絡聊天室實現 開發工具:eclipse 開發環境:jdk1.8 發送端 接收端 工具類 運行截圖...

    19.vue中封裝echarts組件

    19.vue中封裝echarts組件 1.效果圖 2.echarts組件 3.使用組件 按照組件格式整理好數據格式 傳入組件 home.vue 4.接口返回數據格式...

    精品国产乱码久久久久久蜜桃不卡