QT QComboBox+QTreeView 实现二级或多级菜单并带滚轮

效果:

QT QComboBox+QTreeView 实现二级或多级菜单并带滚轮_第1张图片

废话不多说,上代码

ComboBox.h

#pragma once
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "TreeView.h"
#include "ComboBox.h"

class ComboBox : public QComboBox
{
	Q_OBJECT
public:
	ComboBox(QWidget *parent = 0);
	~ComboBox();

public:
	void hidePopup();
	void showPopup();
    TreeView *m_pTreeView;

signals:

	private slots :
		void SetEditModel(bool _editModel);
	    void SetCurrentToolTip(const QString &tooltip);
private:

	bool _editMode = true;
};

 ComboBox.cpp

#include "ComboBox.h"

ComboBox::ComboBox(QWidget *parent)
	: QComboBox(parent)
{
    m_pTreeView = new TreeView(this);
    connect(m_pTreeView, SIGNAL(SignalClickExpandOrCollape(bool)), this, SLOT(SetEditModel(bool)));
    connect(this, SIGNAL(currentTextChanged(QString)), this, SLOT(SetCurrentToolTip(QString)));

    m_pTreeView->setHeaderHidden(true);
    m_pTreeView->header();
    m_pTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers); // 不可选项编辑



    this->setView(m_pTreeView);
    //设置宽度数值小加上数据多的情况下会出现滚动条
    this->view()->setFixedHeight(100);
}

ComboBox::~ComboBox()
{

}

// 解决垂直滚动条出现,多次popup时item错乱的问题  (重要)
void ComboBox::hidePopup()
{
	if (!_editMode)
	{
        m_pTreeView->setLastIndex();
        m_pTreeView->scrollToTop();
		QComboBox::hidePopup();
	}
	_editMode = false;
}

void ComboBox::showPopup()
{
    QComboBox::showPopup();
    m_pTreeView->scrollToTop();
}


void ComboBox::SetEditModel(bool _editModel)
{
    this->_editMode = _editModel;
}

void ComboBox::SetCurrentToolTip(const QString &tooltip)
{
	this->setToolTip(tooltip);
}

TreeView.h

#pragma once
#include 
#include 
#include 

class TreeView : public QTreeView
{
	Q_OBJECT

public:
	TreeView(QWidget *parent = 0);
	~TreeView();

	void setLastIndex();
	void initLastIndex();
signals:
	void SignalClickExpandOrCollape(bool _editModel);

protected:
	void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;

private:
	QModelIndex m_lastPressIndex;
};

TreeView.cpp

#include "TreeView.h"
#include 
#include 
#include 
TreeView::TreeView(QWidget *parent)
	: QTreeView(parent)
{
}

TreeView::~TreeView()
{
}

void TreeView::mousePressEvent(QMouseEvent *event)
{
    qDebug()<<"clicked";
	int isExpandError = -1;
	QModelIndex index;
	if (event->button() == Qt::LeftButton)          //是否左键按下
	{
		index = indexAt(event->pos());  //取出按下点的元素索引index
		if (index.isValid())                   //判断index是否有效
		{
			//你的处理
			QRect rect = visualRect(index);
			QRect expandOrCollape = QRect(rect.left() - 20, rect.top(), 20, rect.height());

			if (isExpanded(index)){
				isExpandError = 1;
			}
			else{
				isExpandError = 0;
			}
			//判断是否点击的是三角形
			if (expandOrCollape.contains(event->pos()))
				emit SignalClickExpandOrCollape(true);
			else{
				emit SignalClickExpandOrCollape(false);
				isExpandError = -1;
			}
            m_lastPressIndex = index;
		}

	}
    QTreeView::mousePressEvent(event);
	if (isExpandError != -1){
		if (isExpanded(index) && isExpandError == 1){
			setExpanded(index, false);
		}
		else if (!isExpanded(index) && isExpandError == 0){
			setExpanded(index, true);
		}
	}
}

void TreeView::setLastIndex()
{
	setCurrentIndex(m_lastPressIndex);
}

void TreeView::initLastIndex()
{
	m_lastPressIndex = QModelIndex();
}

实现方式创建个widget把这个box塞进去

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    box=new ComboBox(this);
    QStandardItemModel *model = new QStandardItemModel();

    QStandardItem *item1 = new QStandardItem("四年级");

    model->setItem(0,0,item1);

    QStandardItem *item00 = new QStandardItem("张三");
    QStandardItem *item10 = new QStandardItem("张四");
    QStandardItem *item20 = new QStandardItem("张五");
    
    model->item(0,0)->setChild(0,0,item00);
    model->item(0,0)->setChild(1,0,item10);
    model->item(0,0)->setChild(2,0,item20);

    QStandardItem *item2 = new QStandardItem("五年级");

    model->setItem(1,0,item2);

    QStandardItem *item200 = new QStandardItem("李三");
    QStandardItem *item210 = new QStandardItem("李四");
    QStandardItem *item220 = new QStandardItem("李五");

    model->item(1,0)->setChild(0,0,item200);
    model->item(1,0)->setChild(1,0,item210);
    model->item(1,0)->setChild(2,0,item220);

    box->setModel(model);
    box->m_pTreeView->initLastIndex();
    box->setGeometry(0,0,200,80);
}

疑点:

创建的QStandardItem为什么吗不给treeviee而是给combobox?

按我的理解就是QT的控件时基于MVC架构的item相当于模型,treeview相当于视图层,而我们操作控件相当于控制层。他们是一个整体,这里相当于是给combobox这个控件设置了一个treeview的视图,而元素是属于box的,所以model应该给box。

你可能感兴趣的:(QT,qt,开发语言,c++)