QT-对于MVC中典型QTreeView简单使用参考记录

发布时间 2023-12-01 16:11:25作者: Neko_Code
//创建以ui文件中对应View为载体的model<-此处使用QStandardItemModel(比较常用)
QStandardItemModel* model = new QStandardItemModel(ui->treeView);
    model->setHorizontalHeaderLabels(QStringList()<<QStringLiteral("国家")<<QStringLiteral("省份")<<QStringLiteral("城市"));	//设置表头信息


    QList<QStandardItem *> items1;	//定义第一个(行)节点的信息
    QStandardItem * item1 = new QStandardItem(QStringLiteral("中国"));
    QStandardItem * item2 = new QStandardItem(QStringLiteral("\\"));

    items1.append(item1);
    items1.append(item2);

    QList<QStandardItem *> items1_;
    QStandardItem * item1_item1 = new QStandardItem(QStringLiteral("↑"));
    QStandardItem * item1_item2 = new QStandardItem(QStringLiteral("四川省"));

    items1_.append(item1_item1);
    items1_.append(item1_item2);
    item1->appendRow(items1_);	//此处将省节点加入第一节点下

    QList<QStandardItem *> items_city;
    QStandardItem * CityItem1 = new QStandardItem(QStringLiteral(" "));
    QStandardItem * CityItem2 = new QStandardItem(QStringLiteral("↑"));
    QStandardItem * CityItem3 = new QStandardItem(QStringLiteral("成都市"));

    items_city.append(CityItem1);
    items_city.append(CityItem2);
    items_city.append(CityItem3);

    item1_item1->appendRow(items_city);	//此处将城市节点加入省节点下



    QList<QStandardItem *> items2;
    QStandardItem * item3 = new QStandardItem(QStringLiteral("英国"));
    QStandardItem * item4 = new QStandardItem(QStringLiteral("\\"));

    items2.append(item3);
    items2.append(item4);

    model->appendRow(items1);	//将节点与model绑定,此处设定为添加行
    model->appendRow(items2);


    ui->treeView->setModel(model);	//设置View对应的数据来源model

image-20231201123400752

此处参照:QTreeView使用总结1,一个简单示例-CSDN博客

效果展示:

image-20231201123452950

image-20231201123509349

常用API介绍:

image-20231201123623542

通过ui获得View对应的指针,该指针就可以直接修改实例的属性.

enum EditTrigger {	//对应setEditTriggers设定单元格的编辑状态及如何编辑操作
    NoEditTriggers = 0,     //不可编辑
    CurrentChanged = 1,     //任何时候都能对单元格修改
    DoubleClicked = 2,      //双击单元格
    SelectedClicked = 4,    //单击已选中的内容
    EditKeyPressed = 8,     //键盘的编辑键,如F2
    AnyKeyPressed = 16,     //按下任意键就能修改
    AllEditTriggers = 31    //以上条件全包括
};

enum SelectionBehavior {	//对应setSelectionBehavior设定选中单元格的方式
    SelectItems,        //选中单个单元格
    SelectRows,         //选中一行
    SelectColumns       //选中一列
};

enum SelectionMode {	//设置多选单选属性
    NoSelection,        //不能选择
    SingleSelection,    //单选
    MultiSelection,     //多选,不用按ctrl键即可多选,选择新项时不取消之前选择,已选中的再选择会取消选择
    ExtendedSelection,  //多选,按ctrl、shift键多选,选择新项时取消之前选择
    ContiguousSelection   //多选,需要按ctrl或shift都是shift选中效果,即选中两次点击之间的所有元素
};

setAlternatingRowColors(bool) //每间隔一行的背景色不同,如第一节点为灰黑色,第二节点为灰色,第三节点为灰白色
setFocusPolicy(Qt::NoFocus)	//用于取消单元格的虚线框
    
QTreeView * view = ui->TreeView;

//表头,列
view->header()->setStrechLastSection(true);	//最后一列Header自适应宽度
view->header()->setDefaultAlignment(Qt::AlignCenter); //header中的文字默认居中对齐
view->header()->setDefaultSectionSize(100);	//设置默认的列宽
void setColumnWidth(int column,int width); //直接调用设置设置指定列的列宽,QTreeView直接调用
//ui->treeview->setColumnWidth(,);
view->header()->setSortIndicator(0,Qt::AscendingOrder)	//设置view内容按照指定方式排序
view->header()->resizeSection(0,100); //设置header指定列的宽度param:(location,width)
view->header()->setSectionResizeMode(0,QHeaderView::Fixed); //设置对应列固定宽度,根据param不同效果不同
view->header()->hide();	//隐藏表头
view->header()->setHighlightSections(true); //点击view时,如果出现该列header文字加粗的情况,可以使用该属性取消

//行高
//QTreeView没有提供设置行高的方法,一般由Delegate代设置
//qss样式表设置:
QTreeView::item{
	height:30px;
}

//设置默认选中第一行
QModelIndex rootIndex = view->rootIndex();
QModelIndex selIndex = model->index(0,0,rootIndex);
view->setCurrentIndex(selIndex);

对单元格选中相关信号介绍:

QTreeView的选中内容由封装的QItemSelectionModel进行管理,该model的指针可以这样获得↓

QItemSelectionModel * selectModel = ui->treeview->selectionModel();

SIGNAL:

Q_SIGNALS:
    void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);//多行改变时
    void currentChanged(const QModelIndex ¤t, const QModelIndex &previous);	//单个元素选中时(改变时)
    void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);//单行改变时
    void currentColumnChanged(const QModelIndex ¤t, const QModelIndex &previous);
    void modelChanged(QAbstractItemModel *model);

SLOT:

private:
    void slotSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
    void slotCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous);
    void slotCurrentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);

绑定信号示例:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    InitTree();
 	//不再单独拿出指针
/**    connect(ui->treeView->selectionModel(),&QItemSelectionModel::selectionChanged,this,&MainWindow::slotSelectionChanged);
    connect(ui->treeView->selectionModel(),&QItemSelectionModel::currentChanged,this,&MainWindow::slotCurrentChanged);
    connect(ui->treeView->selectionModel(),&QItemSelectionModel::currentRowChanged,this,&MainWindow::slotCurrentRowChanged);
}
**/
        //建议使用旧格式书写connect
connect(ui->treeView->selectionModel(),SIGNAL(selectionChanged(QItemSelection,QItemSelection)),this,SLOT(slotSelectionChanged(QItemSelection,QItemSelection)));
    connect(ui->treeView->selectionModel(),SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(slotcurrentChanged(QModelIndex,QModelIndex)));
    connect(ui->treeView->selectionModel(),SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),this,SLOT(slotCurrentRowChanged(QModelIndex,QModelIndex)));

SLOT实现:

//选中内容变化,覆盖单选和多选的情况
void MainWindow::slotSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
    QItemSelectionModel *selections = ui->treeView->selectionModel();
    QModelIndexList indexes = selections->selectedIndexes();    //得到所有选中的index
    foreach(QModelIndex index, indexes)
    {
        //从索引index获取item指针,mModel是tree的数据Model,这里是QStandardItemModel*类型
        QStandardItem* item = mModel->itemFromIndex(index);
        if (item)
        {
            //你的操作,比如取文本、取附带的data
//            QString text = item->text();
//            QString data1 = item->data(Qt::UserRole + 1).toString();
//            QString data2 = item->data(Qt::UserRole + 2).toInt();
        }
    }
}
 
//当前选中index变化,单个
void MainWindow::slotCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
    QStandardItem* item = mModel->itemFromIndex(current);
    if (item)
    {
        //你的操作,同上
    }
}
 
//当前选中行变化,单行
void MainWindow::slotCurrentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
    //取选中的这行的第一个元素的index
    QModelIndex index = current.sibling(current.row(),0);
    QStandardItem* item = mModel->itemFromIndex(index);
    if(item)
    {
        //同上
    }
}

参考文献:QTreeView使用总结5,选中信号处理_qtreeview选中信号处理-CSDN博客

单击双击信号响应:

QTreeView继承的父类QAbstractItemView内定义的视图组件信号

Q_SIGNALS:
    void pressed(const QModelIndex &index);	//按下
    void clicked(const QModelIndex &index);	//单击
    void doubleClicked(const QModelIndex &index);	//双击
 
    void activated(const QModelIndex &index);
    void entered(const QModelIndex &index);
    void viewportEntered();
 
    void iconSizeChanged(const QSize &size);

拦截这些信号,可以继承QTreeView重写以下事件:

protected:
    void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;

示例:

void MyTreeView::mousePressEvent(QMouseEvent *e)
{
    if( e->button() == Qt::LeftButton )          //是否左键按下
    {
        QModelIndex index = indexAt(e->pos());  //取出按下点的元素索引index
        if( index.isValid() )                   //判断index是否有效
        {
            //你的处理
            QVariant data = index.data(Qt::UserRole+1);
        }
        
        
        //如果需要判断组合键,使用下面代码
        if(QApplication::keyboardModifiers () == Qt::ControlModifier)
        {
            //当前CTRL是否按下,根据需要加此情况
        }
        else if(QApplication::keyboardModifiers() == Qt::ShiftModifier)
        {
            //当前SHIFT是否按下,根据需要加此情况
        }
        else
        {
	    //只是左键按下,没有CTRL和SHIFT
            //你的处理...
        }
    }
}