Зависящие от родителей флажки QTreeWidgetItem в динамически генерируемом QTreeWidget - PullRequest
3 голосов
/ 08 февраля 2012

Я пишу приложение, в котором есть QTreeWidget, который заполняется путем анализа XML-файла, содержащего уровни дерева. Если я выберу флажок верхнего уровня, мне нужно будет также проверить все флажки подуровня.

У меня уже работает синтаксический анализатор XML, и я заполняю QTreeWidget QTreeWidgetItems, у которых есть флажки, но их можно проверить только по отдельности.

Ответы [ 3 ]

6 голосов
/ 09 февраля 2012

Для этого сохраните код, который вам нужен, чтобы сгенерировать дерево с вашим 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));
    }   
}

Несколько замечаний для рассмотрения:

  1. Вы можете испытать искушение использовать сигнал itemClicked вместо сигнала itemChanged.Это обычно работает, но не будет работать, когда пользователь использует клавиши со стрелками и пробел для изменения контрольных состояний.
  2. Вам нужно будет подумать о том, что произойдет, если вы снимите отметку с одного из подпунктов, которые былипроверил, нажав на его родителя.Обычно это означает, что вам нужно отключить или частично проверить всех предков.Это может быть неверно для вашего случая.
  3. itemUpdated также будет запущен за другие изменения элемента (например, изменение текста), поэтому имейте в виду, что это не очень эффективный способ сделать это.
2 голосов
/ 21 августа 2013

Я просто немного поработал над этим и получил хорошие результаты, основываясь на ответе Рика. Может быть, это может помочь другим там. Он обновляет состояние родителей и детей с состоянием в трех состояниях только для родителей (проверено, не проверено, частично проверено).

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);
    }
}

Больше не нуждается в recursiveChecks (). Соединение между treeWidget и updateChecks все еще активно.

1 голос
/ 28 апреля 2019

Это выглядит все еще довольно высоко в поисковых системах, и является устаревшим.Просто установите флаг Qt :: ItemIsAutoTristate на элементе верхнего уровня.

...