加强门户网站建设提升/苏州优化收费
QTableview 隐藏单元格内控件无效的原因
背景:
在QTableview的单元格中创建多个QComboBox,当某条件成立时,隐藏特定单元格中的QComboBox,使得该单元格为空。
DEMO:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QStandardItemModel>
#include <QMainWindow>#include <QComboBox>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:void init();void changeData();private:QStandardItemModel *mpDataModel; ///< 表格数据模型QList<QComboBox*> mComboList;private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);init();changeData();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::init()
{mpDataModel = new QStandardItemModel;mpDataModel->setRowCount(10 );mpDataModel->setColumnCount(1);ui->tableView->setModel(mpDataModel);QStringList strList;strList<<"1"<<"2";for(int i=0; i<10; i++){QComboBox *combo = new QComboBox(this);combo->addItems(strList);mComboList.append(combo);QModelIndex index = mpDataModel->index(i, 0);ui->tableView->setIndexWidget(index, combo);}
}void MainWindow::changeData()
{//第一种方式
// int row1 = 1;
// QWidget *widget = ui->tableView->indexWidget(mpDataModel->index(row1,0));
// QComboBox *combo = dynamic_cast<QComboBox*>(widget);
// if(combo != nullptr)
// {
// combo->setVisible(false);
// }//第二种方式
// widget->hide();//第三种方式
// mComboList.at(row)->setVisible(false);//第四种方式int row2 = 1;ui->tableView->setIndexWidget(mpDataModel->index(row2,0),nullptr);}
demo中创建了一个简单的主窗口,包含一个表格视图 (QTableView)。表格视图有 10 行和 1 列,每个单元格都包含一个下拉列表 (QComboBox)。
init() 函数设置了表格视图,创建一个包含两个选项 (“1” 和 “2”) 的下拉列表 (QComboBox),并将其添加到表格视图的每个单元格中。最后,将每个 QComboBox 对象添加到 mComboList 向量中。
changeData()试图隐藏表格视图中的某个特定单元格内的 QComboBox。
运行结果:除了第四种方式,其余方式隐藏无效。
分析原因:
<帮助手册>
<源代码:qabstractitemview.cpp>
探讨setIndexWidget函数的作用:
如果在放入新控件时,当前单元格存在旧控件,那么d->persistent.remove(oldWidget);会将旧控件从persistent 集合中移除,防止内存泄漏,同时确保旧控件不再与模型索引关联。除此之外,会将其从编辑器列表中移除,并取消对它的事件过滤,deleteLater将其安排在稍后删除。
排查隐藏失败的原因:
在demo中:
1、该下拉列表框已经被正确添加到了视图中,目标隐藏位置确实存在QComboBox控件:
语句:
qDebug() << ui->tableView->indexWidget(mpDataModel->index(row1,0));
输出:
2、控件的visible属性没有在其他代码部分重新设置为true
3、控件没有被其他控件遮挡
4、控件所在的父控件没有设置setVisible(false)
5、强制视图重新绘制后也无法隐藏
语句:
ui->tableView->viewport()->update();
6、控件的可见性属性确实被设置为false
语句:
bool isVisible = combo->testAttribute(Qt::WA_WState_Visible);
qDebug() << "Is visible: " << isVisible;
输出:
合理推测隐藏失败原因:
在tableview被创建时,单元格存在默认的控件:在放入下拉框前打印
语句:
for(int row=0; row<10;row++)
{qDebug() << ui->tableView->indexWidget(mpDataModel->index(row,0));
}
输出:
我们使用setIndexWidget时,将新控件代替了旧控件,此时旧控件已经从视图中移除。如果我们删除或隐藏新控件,该单元格中没有可以显示的控件,也许这样导致了删除或隐藏失败,保留原视图显示。
欢迎一起讨论!