C++ 动态生成的QTreeWidget中的父依赖QTreeWidgetItem复选框

C++ 动态生成的QTreeWidget中的父依赖QTreeWidgetItem复选框,c++,checkbox,qt4,c++11,qtreewidget,C++,Checkbox,Qt4,C++11,Qtreewidget,我正在编写一个应用程序,它有一个QTreeWidget,通过解析包含树级别的XML文件来填充它。如果我选中了一个顶级复选框,我需要同时选中所有的次级复选框 我已经让XML解析器工作并用带有复选框但只能单独选中的QTreeWidgetItems填充QTreeWidget 要做到这一点,请保留必须使用XML生成树的代码。然后连接到itemChanged()信号并更新插槽中的检查状态。它应该看起来像: connect(treeWidget, SIGNAL(itemChanged(QTreeWidget

我正在编写一个应用程序,它有一个QTreeWidget,通过解析包含树级别的XML文件来填充它。如果我选中了一个顶级复选框,我需要同时选中所有的次级复选框


我已经让XML解析器工作并用带有复选框但只能单独选中的QTreeWidgetItems填充QTreeWidget

要做到这一点,请保留必须使用XML生成树的代码。然后连接到itemChanged()信号并更新插槽中的检查状态。它应该看起来像:

connect(treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)),
        this,       SLOT(updateChecks(QTreeWidgetItem*, int)));

void ClassName::updateChecks(QTreewidgetItem* item, int column)
{
    // Checkstate is stored on column 0
    if(column != 0)
        return;

    recursiveChecks(item);
}

void ClassName::recursiveChecks(QTreeWidgetItem* parent)
{
    Qt::CheckState checkState = parent->checkState(0);
    for(int i = 0; i < parent->childCount(); ++i)
    { 
       parent->child(i)->setCheckState(0, checkState);
       recursiveChecks(parent->child(i));
    }   
}
connect(treeWidget,信号(itemChanged(QTreeWidgetItem*,int)),
这个插槽(updateChecks(QTreeWidgetItem*,int));
void ClassName::updateChecks(QTreewidgetItem*item,int列)
{
//Checkstate存储在列0上
如果(列!=0)
返回;
递归检查(项目);
}
void ClassName::recursiveChecks(QTreeWidgetItem*父项)
{
Qt::CheckState CheckState=parent->CheckState(0);
对于(int i=0;ichildCount();++i)
{ 
父->子(i)->设置检查状态(0,检查状态);
递归检查(父->子(i));
}   
}
需要考虑的几个注意事项:

  • 您可能会尝试使用itemClicked信号而不是itemChanged信号。这通常有效,但在用户使用箭头键和空格键更改CheckState时不起作用
  • 您需要考虑当您通过单击其父项取消选中已选中的子项时会发生什么情况。通常这意味着您需要取消选中或部分选中所有祖先。你的情况可能不是这样
  • itemUpdated还将因项目的其他更改(如文本更改)而被触发,因此请注意,这不是一种超高效的方法

  • 我只是在这方面做了一些工作,根据瑞克的回答,我得到了很好的结果。也许它可以帮助其他人。 它仅为父对象更新父对象和子对象的三态状态(选中、未选中、部分选中)

    void ClassName::updateChecks(QTreeWidgetItem*item,int列)
    {
    布尔差=假;
    if(列!=0&&column!=-1)
    返回;
    if(item->childCount()!=0&&item->checkState(0)!=Qt::PartiallyChecked&&column!=-1){
    Qt::CheckState CheckState=item->CheckState(0);
    对于(int i=0;ichildCount();++i){
    项->子项(i)->设置检查状态(0,检查状态);
    }
    }else if(item->childCount()==0 | |列==-1){
    如果(项->父项()==0)
    返回;
    对于(int j=0;jparent()->childCount();++j){
    如果(j!=item->parent()->indexOfChild(item)&&item->checkState(0)!=item->parent()->child(j)->checkState(0)){
    diff=真;
    }
    }
    if(diff)
    item->parent()->setCheckState(0,Qt::PartiallyChecked);
    其他的
    item->parent()->setCheckState(0,item->checkState(0));
    如果(项->父项()!=0)
    updateChecks(项->父项(),-1);
    }
    }
    

    不再需要recursiveChecks()。树状网络和updateChecks之间的连接仍然处于活动状态。

    这在搜索引擎中仍然很常见,并且已经过时。
    只需在顶级项目上设置标志Qt::ItemIsAutoTristate。

    rabid,这是两件不同的事情:选中复选框(第1段)和选择项目(第2段)。你什么意思?瑞克,非常感谢你!我对C++和QT完全陌生,所以这是一个巨大的帮助。但是我有一个问题,如果
    QTreeWidget
    是Qt创建者/设计者表单的一部分,那么
    ClassName
    应该是什么?它只是包含
    QMainWindow
    的类名称吗?还有,
    recursiveChecks()
    方法中的
    item
    变量来自何处?不管怎样,我将它添加到我正在使用的
    QMainWindow
    扩展类中,并在第二个方法中将
    item
    更改为
    parent
    。工作得很有魅力!!再次感谢@RabidWidget很高兴你找到了它…QMainWidget是一个放置我给你的代码的有效地方。祝你好运如果你使用的是现代Qt,这绝对是正确的答案。它的速度非常慢,有大量的项目。
    void ClassName::updateChecks(QTreeWidgetItem *item, int column)
    {
        bool diff = false;
        if(column != 0 && column!=-1)
            return;
        if(item->childCount()!=0 && item->checkState(0)!=Qt::PartiallyChecked && column!=-1){
            Qt::CheckState checkState = item->checkState(0);
            for (int i = 0; i < item->childCount(); ++i) {
               item->child(i)->setCheckState(0, checkState);
            }
        } else if (item->childCount()==0 || column==-1) {
            if(item->parent()==0)
                return;
            for (int j = 0; j < item->parent()->childCount(); ++j) {
                if(j != item->parent()->indexOfChild(item) && item->checkState(0)!=item->parent()->child(j)->checkState(0)){
                    diff = true;
                }
            }
            if(diff)
                item->parent()->setCheckState(0,Qt::PartiallyChecked);
            else
                item->parent()->setCheckState(0,item->checkState(0));
            if(item->parent()!=0)
                updateChecks(item->parent(),-1);
        }
    }