效果:
废话不多说,上代码
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。