Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [Qt] Выбор QTreeWidgetItem'ов в дереве QTreeWidget, Постановка/снятие чекбоксов 
V
    Опции темы
mosg
  Дата 24.9.2008, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 3.3.2008
Где: Moscow

Репутация: 1
Всего: 1



Добрый день

Проблема в следующем: есть окно QTreeWidget, в котором создаются QTreeWidgetItem'ы иерархично, посмотреть можно тут:

 >> http://www.mosg.info/images/trash/checkbox.png

Необходимо при выборе любого из item'ов, ставить соответствующие флаги для родителей в трех состояниях? Механизм работы мой у меня есть, ниже я его привожу, вот только работает он через одно место.

Код

void    XXX::on_treeWidget_itemChanged(QTreeWidgetItem *item, int column) {

    if (!item || column != 0)
        return;

    bool isFolder = (item->childCount() != 0);

    // Это каталог или ячейка
    if (isFolder) {

        // Всего детей        
        int    n_childrens = item->childCount();

        // Выставляем checked/unchecked
        switch (item->checkState(0)) {

            case (Qt::Unchecked):
                for (int i = 0; i < n_childrens; i++) {

                    QTreeWidgetItem    *subItem = item->child(i);
                    subItem->setCheckState(0, Qt::Unchecked);
                    subItem->setSelected(true);
                    itemChangeIcon(subItem, column);
                }
                break;

            case (Qt::PartiallyChecked):
                break;

            case (Qt::Checked):
                for (int i = 0; i < n_childrens; i++) {

                    QTreeWidgetItem    *subItem = item->child(i);
                    subItem->setCheckState(0, Qt::Checked);    
                    subItem->setSelected(true);
                    itemChangeIcon(subItem, column);
                }
                break;
        }

        // Меняем состояние флага родителя в зависимости от количества выбранных ячеек
        // Считаем количество и тех, и тех
        // Логика, мать её :)
        int    checked = 0,
            notchecked = 0;

        QTreeWidgetItem    *parentItem = treeWidget->topLevelItem(0);

        for (int i = 0; i < (parentItem->childCount()); i++)
            (parentItem->child(i)->checkState(0) == Qt::Checked) ? checked++ : notchecked++;

        if (checked >= 1 && (checked < parentItem->childCount()))
            parentItem->setCheckState(0, Qt::PartiallyChecked);
        else if (!checked)
            parentItem->setCheckState(0, Qt::Unchecked);
        else
            parentItem->setCheckState(0, Qt::Checked);

        // Убираем выделения
        for (int i = 0; i < n_childrens; i++) {

            QTreeWidgetItem    *subItem = item->child(i);
            subItem->setSelected(false);
        }

    } else {

        // Меняем значек
        for (int i = 0; i < (treeWidget->topLevelItemCount()); i++) {
            itemChangeIcon(treeWidget->topLevelItem(i), column);
        }

        // Меняем состояние флага родителя в зависимости от количества выбранных ячеек
        // Считаем количество и тех, и тех
        // Логика, мать её :)
        int    checked = 0,
            notchecked = 0;

        QTreeWidgetItem    *parentItem = item->parent();
        
        for (int i = 0; i < (parentItem->childCount()); i++)
            (parentItem->child(i)->checkState(0) == Qt::Checked) ? checked++ : notchecked++;
        
        if (checked >= 1 && (checked < parentItem->childCount()))
            parentItem->setCheckState(0, Qt::PartiallyChecked);
        else if (!checked)
            parentItem->setCheckState(0, Qt::Unchecked);
        else
            parentItem->setCheckState(0, Qt::Checked);
    }
}


Есть ли светлый человек, который встречался уже с подобной проблемой и удачно её решил? smile

Заранее спасибо!
PM MAIL WWW ICQ Skype GTalk Jabber YIM MSN   Вверх
mosg
Дата 25.9.2008, 20:41 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 3.3.2008
Где: Moscow

Репутация: 1
Всего: 1



Всем спасибо за внимание, пришлось решить проблему самому!  smile 

Решение:

1). Создаем класс ABC от, например, QWidget, где:
Код
private slots:
    void    on_treeWidget_itemChanged(QTreeWidgetItem *, int );

protected:
    void    setCheckState(QTreeWidgetItem * /*item*/, int /*column*/, Qt::CheckState /*state*/);
    void    setCheckStateForParents(QTreeWidgetItem * /*item*/, int /*column*/, Qt::CheckState /*state*/);
    void    setCheckStateOnce(QTreeWidgetItem * /*item*/, int /*column*/, Qt::CheckState /*state*/);

    QTreeWidget    *treeWidget;


2). Добавляем при создание конструктора (ABC::ABC()) в коннектах:
Код
    connect(treeWidget, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(on_treeWidget_itemChanged(QTreeWidgetItem *, int)));


3). Определения,
Код
void    ABC::on_treeWidget_itemChanged(QTreeWidgetItem *item, int column) {
    Qt::CheckState newState = item->checkState(column);
    setCheckState(item, column, newState);
}
/****************************************************************************/
void    ABC::setCheckState(QTreeWidgetItem *pItem, int column, Qt::CheckState state) {

    if (!pItem)
        return;

    bool isFolder = (pItem->childCount() != 0);

    // Это каталог или ячейка
    if (isFolder) {

        pItem->setCheckState(column, state);

        for (int i = 0; i < pItem->childCount(); i++)
            setCheckState(pItem->child(i), column, state);

    } else {

        setCheckStateForParents(pItem, column, state);

        pItem->setCheckState(column, state);
    }
}
/****************************************************************************/
void    ABC::setCheckStateForParents(QTreeWidgetItem *pItem, int column, Qt::CheckState state) {

    if (!pItem)
        return;

    QTreeWidgetItem    *parent = pItem->parent();

    if (!parent)
        return;

    // если у родителя нет родителя :(
    if (!parent->parent()) {

        setCheckStateOnce(parent, column, state);

    } else {

        setCheckStateOnce(parent, column, state);
        setCheckStateForParents(parent, column, state);
    }
}
/****************************************************************************/
void    ABC::setCheckStateOnce(QTreeWidgetItem *pItem, int column, Qt::CheckState state) {

    treeWidget->blockSignals(true);

    // считает детей
    int marked        = 0,
        semimarked    = 0,
        unmarked    = 0;

    int n_childCount = pItem->childCount();

    for (int i = 0; i < n_childCount; i++) {

        Qt::CheckState currentState = pItem->child(i)->checkState(column);
        switch (currentState) {
            case (Qt::Unchecked):
                unmarked++;
                break;
            case (Qt::PartiallyChecked):
                semimarked++;
                break;
            case (Qt::Checked):
                marked++;
                break;
        }
    }

    if (marked == n_childCount) {
        pItem->setCheckState(column, Qt::Checked);
    } else if (unmarked == n_childCount) {
        pItem->setCheckState(column, Qt::Unchecked);
    } else {
        pItem->setCheckState(column, Qt::PartiallyChecked);
    }

    treeWidget->blockSignals(false);
}


Аминь!
PM MAIL WWW ICQ Skype GTalk Jabber YIM MSN   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0642 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.