C++ 在QTreeView中维护checkedstatus继承
我正在尝试做一些基本的事情:你有一个C++ 在QTreeView中维护checkedstatus继承,c++,model-view-controller,qt,qtreeview,qstandarditemmodel,C++,Model View Controller,Qt,Qtreeview,Qstandarditemmodel,我正在尝试做一些基本的事情:你有一个QTreeView。第一个深度仅为文件夹,第二个深度仅为文件。我想在每个项目旁边有一个复选框,其状态为选中。检查或取消检查文件,也可以根据文件夹的文件部分检查文件夹;总的来说,我相信这是很自然的 我认为应该使用QStandardItemModel并用QStandardItem的自定义子类填充它:descriptionleItem。也许这是个坏主意,如果有更简单的方法请告诉我 我尝试使用信号和插槽,以便将文件上的信号CheckStateChanged连接到其包含
QTreeView
。第一个深度仅为文件夹,第二个深度仅为文件。我想在每个项目旁边有一个复选框,其状态为选中。检查或取消检查文件,也可以根据文件夹的文件部分检查文件夹;总的来说,我相信这是很自然的
我认为应该使用QStandardItemModel
并用QStandardItem
的自定义子类填充它:descriptionleItem
。也许这是个坏主意,如果有更简单的方法请告诉我
我尝试使用信号和插槽,以便将文件上的信号CheckStateChanged
连接到其包含文件夹上的插槽UpdateCheckedStateOnChildStateChanged
。这要求我的DescriptionFileItem
也继承自QObject
(顺便说一句,我很惊讶qstandarItem
没有继承自QObject
)。我最初希望它能与提供的基类无缝地工作,但事实并非如此:emitDataChanged()
似乎没有触发模型的dataChanged()信号
直接使用模型的dataChanged
信号也不起作用:它的调用受到保护,因此在没有子类化的情况下无法使用它(我认为这是我的下一步行动,除非有人能帮我把它做好)
目前我有一个信号->插槽连接无法工作,我不知道为什么;编译和链接工作正常。这是代码;也许你会很容易发现我的错误。我留下了一些注释行,这样你就可以看到我在以前的尝试中做错了什么。谢谢你的意见
#ifndef DESCRIPTIONFILEITEM_H
#define DESCRIPTIONFILEITEM_H
#include <QStandardItem>
#include <Qt>
class DescriptionFileItem : public QObject, public QStandardItem
{
Q_OBJECT
public:
explicit DescriptionFileItem(const QString & text, bool isFileName=false, QObject* parent = 0);
void setData ( const QVariant & value, int role = Qt::UserRole + 1 );
QVariant data( int role = Qt::UserRole + 1 ) const;
QString text;
Qt::CheckState checkedState;
bool isFileName;
signals:
void CheckStateChanged();
public slots:
void UpdateCheckedStateOnChildStateChanged();
};
#endif // DESCRIPTIONFILEITEM_H
\ifndef descriptionleItem\H
#定义DESCRIPTIONFILEITEM\u H
#包括
#包括
类DescriptionFileItem:公共QObject、公共QStandardItem
{
Q_对象
公众:
显式DescriptionFileItem(常量QString&text,bool isFileName=false,QObject*parent=0);
void setData(const QVariant&value,int-role=Qt::UserRole+1);
QVariant数据(int-role=Qt::UserRole+1)常量;
QString文本;
Qt::CheckState checkedState;
bool-isFileName;
信号:
void CheckStateChanged();
公众时段:
void UpdateCheckedStateOnChildStateChanged();
};
#endif//DESCRIPTIONFILEITEM\u H
对应的cpp:
#include "DescriptionFileItem.h"
DescriptionFileItem::DescriptionFileItem(const QString & text, bool isFileName, QObject* parent):
QObject(parent),QStandardItem(text)
{
this->isFileName = isFileName;
checkedState = Qt::Checked;
}
void DescriptionFileItem::setData ( const QVariant & value, int role){
if(role == Qt::CheckStateRole){
Qt::CheckState newCheckState = (Qt::CheckState)value.toInt();
checkedState = newCheckState;
if(isFileName){
if(newCheckState == Qt::Unchecked || newCheckState == Qt::Checked){
for(int i = 0; i<rowCount(); i++){
DescriptionFileItem* child = (DescriptionFileItem*)QStandardItem::child(i);
QModelIndex childIndex = child->index();
child->model()->setData(childIndex,newCheckState, Qt::CheckStateRole);
//child->setCheckState(newCheckState);
//child->setData(newCheckState,Qt::CheckStateRole);
}
/*if(rowCount()>1){
emit this->model()->dataChanged(this->child(0)->index(),this->child(rowCount()-1)->index());
}else{
emit this->model()->dataChanged(this->child(0)->index(),this->child(0)->index());
}*/
}
}else{
emit CheckStateChanged();
}
//emit this->model()->dataChanged(this->index(),this->index());
}else{
QStandardItem::setData(value,role);
}
}
QVariant DescriptionFileItem::data( int role ) const{
if (role == Qt::CheckStateRole){
return checkedState;
}
return QStandardItem::data(role);
}
void DescriptionFileItem::UpdateCheckedStateOnChildStateChanged()
{
Qt::CheckState min = Qt::Checked;
Qt::CheckState max = Qt::Unchecked;
Qt::CheckState childState;
for(int i = 0; i<rowCount(); i++){
DescriptionFileItem* child = (DescriptionFileItem*)QStandardItem::child(i);
childState = (Qt::CheckState) child->data(Qt::CheckStateRole).toInt();
min = min>childState ? childState: min;
max = max<childState ? childState: max;
}
if(min >= max)
setData(min, Qt::CheckStateRole);
else
setData(Qt::PartiallyChecked, Qt::CheckStateRole);
}
#包括“DescriptionFileItem.h”
DescriptionFileItem::DescriptionFileItem(常量QString&text,bool isFileName,QObject*父项):
QObject(父对象)、QStandardItem(文本)
{
此->isFileName=isFileName;
checkedState=Qt::Checked;
}
void DescriptionFileItem::setData(常量QVariant&value,int角色){
如果(角色==Qt::CheckStateRole){
Qt::CheckState newCheckState=(Qt::CheckState)value.toInt();
checkedState=newCheckState;
if(isFileName){
if(newCheckState==Qt::Unchecked | | newCheckState==Qt::Checked){
对于(int i=0;iindex();
child->model()->setData(childIndex,newCheckState,Qt::checkstate角色);
//child->setCheckState(newCheckState);
//child->setData(newCheckState,Qt::checkstate角色);
}
/*如果(rowCount()>1){
发出此->模型()->数据更改(此->子项(0)->索引(),此->子项(行计数()-1)->索引());
}否则{
发出this->model()->dataChanged(this->child(0)->index(),this->child(0)->index());
}*/
}
}否则{
发出CheckStateChanged();
}
//发出此->模型()->数据更改(此->索引(),此->索引());
}否则{
QStandardItem::setData(值、角色);
}
}
QVariant DescriptionFileItem::数据(int角色)常量{
如果(角色==Qt::CheckStateRole){
返回checkedState;
}
返回QStandardItem::data(角色);
}
void DescriptionFileItem::UpdateCheckedStateOnChildStateChanged()
{
Qt::CheckState min=Qt::Checked;
Qt::CheckState max=Qt::Unchecked;
Qt::CheckState子状态;
for(int i=0;idata(Qt::CheckStateRole).toInt();
min=min>childState?childState:min;
最大值=最大值=最大值)
setData(min,Qt::CheckStateRole);
其他的
setData(Qt::PartiallyChecked,Qt::CheckStateRole);
}
以及连接/树的构造:
DescriptionFileItem* descFileStdItem = new DescriptionFileItem(descriptionFileName, true);
descFileStdItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsTristate);
descriptionFileSIModel.appendRow(descFileStdItem);
typedef pair<string,int> indexType;
foreach(indexType index,dataFile->indexes){
DescriptionFileItem* key_xItem = new DescriptionFileItem(index.first.c_str());
descFileStdItem->appendRow(key_xItem);
key_xItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
QObject::connect(key_xItem,SIGNAL(CheckStateChanged()),descFileStdItem,SLOT(UpdateCheckedStateOnModelDataChanged()));
}
DescriptionFileItem*descfilestItem=新的DescriptionFileItem(descriptionFileName,true);
descfilestItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsTristate);
descriptionFileSIModel.appendRow(descfilesItem);
typedef对indexType;
foreach(indexType索引,数据文件->索引){
DescriptionFileItem*key_xItem=新的DescriptionFileItem(index.first.c_str());
descfilestItem->appendRow(key_xItem);
key_xItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
QObject::connect(key_xItem,SIGNAL(CheckStateChanged()),descfilestItem,SLOT(UpdateCheckedStateOnModelDataChanged());
}
编辑:最终答案,感谢stu(见下文)
void DataLoadWidget::ModelItemChanged(QStandardItem *item)
{
QStandardItem* parent = item->parent();
if(parent == 0){
//folder state changed--> update children if not partially selected
Qt::CheckState newState = item->checkState();
if(newState != Qt::PartiallyChecked){
for (int i = 0; i < item->rowCount(); i++)
{
item->child(i)->setCheckState(newState);
}
}
}
else{//child item changed--> count parent's children that are checked
int checkCount = 0;
for (int i = 0; i < parent->rowCount(); i++)
{
if (parent->child(i)->checkState() == Qt::Checked)
checkCount++;
}
if(checkCount == 0)
parent->setCheckState(Qt::Unchecked);
else if (checkCount == parent->rowCount())
parent->setCheckState(Qt::Checked);
else
parent->setCheckState(Qt::PartiallyChecked);
}
}
void DataLoadWidget::ModelItemChanged(QStandarItem*item)
{
QStandardItem*parent=item->parent();
如果(父项==0){
//文件夹状态已更改-->如果未部分选中,则更新子文件夹
Qt::CheckState newState=item->CheckState();
if(newState!=Qt::PartiallyChecked){
对于(int i=0;irowCount();i++)
{
item->child(i)->setCheckState(newState);
}
}
}
else{//子项已更改-->计数已检查的父项的子项
int checkCount=0;
对于(int i=0;irowCount();i++)
{
如果(父->子(i)->checkState()==Qt::Checked)
支票计数++;
}
如果(支票计数)
QObject::connect(model, SIGNAL(itemChanged(QStandardItem*)), someObject, SLOT(modelItemChanged(QStandardItem*)));
void modelItemChanged(QStandardItem* item)
{
QStandardItem* parent = item->parent();
int checkCount = 0;
int rowCount = parent->rowCount();
for (int i = 0; i < rowCount; i++)
{
if (parent->child(i)->checkState() == Qt::Checked)
checkCount++;
}
switch (checkCount)
{
case 0:
parent->setCheckState(Qt::Unchecked);
break;
case rowCount:
parent->setCheckState(Qt::Checked);
break;
default:
parent->setCheckState(Qt::PartiallyChecked);
}
}