C++ 带有QStackedWidget的层次QTreeView映射
我正在创建一个UI,其中QTreeView表示项目列表(可能有子项,也可能没有子项),并使用QStackedWidget在右侧显示相应的小部件。以前,我的数据或上面提到的项目列表的行为是扁平的,因此我使用QListView,但当数据必须有子项时,我用QTreeView替换了QListView,这样我也可以添加子项。我通过以下方式实现了上述目标:C++ 带有QStackedWidget的层次QTreeView映射,c++,qt,C++,Qt,我正在创建一个UI,其中QTreeView表示项目列表(可能有子项,也可能没有子项),并使用QStackedWidget在右侧显示相应的小部件。以前,我的数据或上面提到的项目列表的行为是扁平的,因此我使用QListView,但当数据必须有子项时,我用QTreeView替换了QListView,这样我也可以添加子项。我通过以下方式实现了上述目标: for(std::vector<AWidget* >::iterator it=widgets.begin(); it!=widgets.e
for(std::vector<AWidget* >::iterator it=widgets.begin(); it!=widgets.end(); ++it)
{
AWidget* w = *it;
QStandardItem *parent = new QStandardItem(w->Name());
model->setItem(i, 0, parent);
QWidget *PageWidget = w->getWidget();
QScrollArea * pScrollArea = new QScrollArea();
pScrollArea->setWidget(PageWidget);
m_ui.AStackedWidget->addWidget(pScrollArea);
if(!w->hasChildren())
{
std::vector<AWidget*> children = w->getChildren();
for(std::vector<AWidget*>::iterator iChild=children.begin(); iChild!=children.end(); ++iChild)
{
AWidget* childWidget = *iChild;
QStandardItem *child = new QStandardItem(childWidget->Name());
parent->appendRow(child);
QWidget *childPageWidget = childWidget->getWidget();
QScrollArea * pChildScrollArea = new QScrollArea();
pChildScrollArea->setWidget(childPageWidget);
pChildScrollArea->setWidgetResizable(true);
m_ui.AStackedWidget->addWidget(pChildScrollArea);
}
}
i++;
}
m_ui.ATreeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_ui.ATreeView->setTabKeyNavigation(true);
m_ui.ATreeView->setModel(model);
QModelIndex index = m_ui.ATreeView->model()->index(0,0);
QItemSelectionModel * selModel = m_ui.ATreeView->selectionModel();
if(selModel)
{
connect(selModel, SIGNAL( currentChanged(const QModelIndex &, const QModelIndex &) ), this , SLOT(slotOptionSelectedForChangeUI(const QModelIndex & )) );
selModel->select(index,QItemSelectionModel::Select);
}
slotOptionSelectedForChangeUI(index);
Definition of slotOptionSelectedForChangeUI() is as follows:
void slotOptionSelectedForChangeUI(const QModelIndex & indx)
{
int rowNum = indx.row();
if(m_ui.AStackedWidget)
m_ui.AStackedWidget->setCurrentIndex(rowNum);
}
A、 B、C、D、E在QStackedWidget的右侧显示正确的对应小部件。但是E1、E2、E3、E4、E5、E6、E7分别显示widget1、2、3、4、5、6、7。这意味着E1的索引再次从0开始,堆叠的小部件显示索引0的widget0,以此类推。E1-E7应如何与widget6-12映射,以便在右侧堆叠的小部件上显示正确的小部件?正确的方法是不使用
QStackedWidget,而只显示一个。要做到这一点,您只需:
使用将小部件添加到项目中
在ui中,不要使用QStackedWidget
,只需使用简单的QWidget
(具有无边距的水平/垂直布局)
将selection model index changed信号连接到从简单小部件中删除所有子部件的插槽,并添加与该项一起存储的子部件。您可以使用函数(或模型数据函数)检索它
以下是这些步骤的一个简单示例:
#define MyRole Qt::UserRole + 42
//...
//adding the item
AWidget* w = *it;
QStandardItem *parent = new QStandardItem(w->Name());
parent->setData(QVariant::fromValue(w), MyRole);
model->setItem(i, 0, parent);
//...
//the index changed slot
void slotOptionSelectedForChangeUI(const QModelIndex & indx)
{
AWidget *w = model->data(index, MyRole).value<AWidget*>();//will internally call QStandardItem::data
//remove old children
QList<QWidget*> children = m_ui.containerWidget->findChildren<QWidget*>(QString(), Qt::FindDirectChildrenOnly);
foreach(QWidget *child, children)
child->deleteLater();
//add the new one
QWidget *PageWidget = w->getWidget();
ScrollArea * pScrollArea = new QScrollArea(m_ui.containerWidget);
pScrollArea->setWidget(PageWidget);
m_ui.containerWidget->layout()->addWidget(pScrollArea);
}
#定义MyRole Qt::UserRole+42
//...
//添加项目
AWidget*w=*it;
QStandardItem*parent=新的QStandardItem(w->Name());
父->设置数据(QVariant::fromValue(w),MyRole);
模型->设置项(i,0,父项);
//...
//索引已更改插槽
为变更UI选择的无效槽位(常数QModelIndex和indx)
{
AWidget*w=model->data(index,MyRole).value();//将在内部调用QStandardItem::data
//搬走年迈的孩子
QList children=m_ui.containerWidget->findChildren(QString(),Qt::FindDirectChildrenOnly);
foreach(QWidget*子项,子项)
child->deleteLater();
//添加新的
QWidget*PageWidget=w->getWidget();
ScrollArea*pscrollara=新的QScrollara(m_ui.containerWidget);
pscrolrea->setWidget(页面widget);
m_ui.containerWidget->layout()->addWidget(pscrolrea);
}
我还没有完全实现上述逻辑,但只是出于好奇,在问题中提到的示例中,SLOTOPIONSELECTED FORCHANGEI中的indx是否会为E1给出5或0?它将是0。因为这就是QModelIndex
的工作原理。但是,返回的索引将有一个父项
,父项行将是4,即E项。模型索引总是描述与其父项相关的行和列。是的,因此需要添加额外的逻辑来计算平面索引,在这种情况下,E1为5。还有,如果D也有像D1和D2这样的孩子呢。在这种情况下,E1应该是0+4(父项)+2(从D1,D2)+1=7。好的,在加入这个逻辑之后,我想它会很好地工作。为什么你想要一个“平面索引”?在我的例子中,你不需要它。对树模型使用平面索引是错误的。如果需要,则应该提供某种映射。
#define MyRole Qt::UserRole + 42
//...
//adding the item
AWidget* w = *it;
QStandardItem *parent = new QStandardItem(w->Name());
parent->setData(QVariant::fromValue(w), MyRole);
model->setItem(i, 0, parent);
//...
//the index changed slot
void slotOptionSelectedForChangeUI(const QModelIndex & indx)
{
AWidget *w = model->data(index, MyRole).value<AWidget*>();//will internally call QStandardItem::data
//remove old children
QList<QWidget*> children = m_ui.containerWidget->findChildren<QWidget*>(QString(), Qt::FindDirectChildrenOnly);
foreach(QWidget *child, children)
child->deleteLater();
//add the new one
QWidget *PageWidget = w->getWidget();
ScrollArea * pScrollArea = new QScrollArea(m_ui.containerWidget);
pScrollArea->setWidget(PageWidget);
m_ui.containerWidget->layout()->addWidget(pScrollArea);
}