crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Тема закрытаНачать новую тему
> Работа с деревом - отметка узлов и листьев, Есть ли примеры работы с этим?
AD
  опции профиля:
сообщение 24.2.2009, 16:34
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Есть ли пример, где можно увидеть, как правильно отмечать узлы и листья дерева. Что-то мой код работает не так, как я хотел бы. Вроде бы такая вещь стандартна и, наверняка, подобные вещи уже делали. Можно ли где-нибудь посмотреть?
Вот мой самописный код, который работает не совсем так, как положено:
/// где - то
connect(treePhaseView, SIGNAL(itemPressed(QTreeWidgetItem*, int)), this,
        SLOT(treeItemPress(QTreeWidgetItem*, int)));


/// Нажатие на элемент дерева
void TLV::treeItemPress(QTreeWidgetItem* item, int column)
{
    if(item == 0) return;
    for(register int i=0; i<item -> childCount(); ++i)
    {
        QTreeWidgetItem* childItem = item -> child(i);
        if(childItem == 0) continue;
        Qt::CheckState check = (childItem -> checkState(column) == 2 || childItem -> checkState(column) == 1) ?
            Qt::Unchecked : Qt::Checked;
        childItem -> setCheckState(column, check);
        treeItemPress(childItem, column);
    }
    QTreeWidgetItem* parentItem = item -> parent();
    if(parentItem == 0) return;
    Qt::CheckState check = (parentItem -> checkState(column) == 2 || parentItem -> checkState(column) == 1) ?
            Qt::Unchecked : Qt::Checked;
    parentItem -> setCheckState(column, check);
}


Вот рисунок дерева. Есть желание сделать стандартно: т.е. если все листья не отмечены, то и узел не отмечен, если отмечен узел, то какой-то из листьев является отмеченным. Если пользователь отмечает узел, то отмечаются все листья этого узла.
Вот рисунок дерева:
[attachment=441:tree_widget.JPG]


Поможете сделать этот алгоритм? Или подскажите, где его можно найти?

Да и еще одно: в дереве возможно только три степени вложенности, как показано на рисунке....

Сообщение отредактировал AD - 24.2.2009, 16:32
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 24.2.2009, 18:35
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Прошу помочь. Запутался! :(
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 24.2.2009, 18:56
Сообщение #3


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


похоже у нас к этой теме никто не подходил, спроси на прогорге там народу поболе, может кто-то сталкивался.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 24.2.2009, 19:09
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(Litkevich Yuriy @ 24.2.2009, 18:56) *
похоже у нас к этой теме никто не подходил, спроси на прогорге там народу поболе, может кто-то сталкивался.

Ну может кто-нибудь вдруг что-то вспомнит...
Вот более адекватный вариант.
/// Нажатие на элемент дерева
void TLV::treeItemPress(QTreeWidgetItem* item, int column)
{
    if(item == 0) return;
    Qt::CheckState check((item -> checkState(column) == Qt::Checked) ? Qt::Unchecked : Qt::Checked);
    for(register int i=0; i<item -> childCount(); ++i)
    {
        QTreeWidgetItem* childItem = item -> child(i);
        if(childItem == 0) continue;
        childItem -> setCheckState(column, check);
        treeItemPress(childItem, column);
    }
    QTreeWidgetItem* parentItem = item -> parent();
    if(parentItem == 0) return;
    parentItem -> setCheckState(column, check);
}


Но все же есть некоторые некорректности:
1) когда я нажимаю на корень, выделяются(снимаются выделения) с узлов, а на листьях - остаются.
2) когда в узле не один лист, а несколько - то при нажатии на лист - выделение затрагивает и узел.

Я понимаю, что у меня эти ситуации и не учтены в коде. Но вот хотел бы учесть. Буду благодарен за помощь!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 25.2.2009, 13:10
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Cделать корректный рекурсивный алгоритм не удалось. Спасло то, что максимально-возможная вложенность равна 3. Поэтому сделал таким образом:
/// Нажатие на элемент дерева
void TLV::itemPress(QTreeWidgetItem* item, int column)
{
    if(item == 0) return;

    Qt::CheckState state((item -> checkState(column) == Qt::Checked) ? Qt::Unchecked : Qt::Checked);
    for(register int i=0; i<item -> childCount(); ++i)
    {
        QTreeWidgetItem* child = item -> child(i);
        if(child == 0) continue;
        if(child -> checkState(column) != state) child -> setCheckState(column, state);
        for(register int j=0; j<child -> childCount(); ++j)
        {
            QTreeWidgetItem* grandchild = child -> child(j);
            if(grandchild == 0) continue;
            if(grandchild -> checkState(column) != state) grandchild -> setCheckState(column, state);
        }
    }

    QTreeWidgetItem* parent = item -> parent();
    if(parent == 0) return;
    bool all = true;
    for(register int i=0; i<parent -> childCount(); ++i)
    {
        QTreeWidgetItem* child = parent -> child(i);
        if(child == 0) break;
        if(item != child && child -> checkState(column) != Qt::Unchecked)
        { all = false; break; }
    }
    if(all) parent -> setCheckState(column, state);
}


Если кто-то сможет помочь сделать из этого корректный алгоритм для любой вложенности - буду благодарен. Ну а так - в принципе - для вложенности не больше 3 - алгоритм работает! :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 25.2.2009, 14:29
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Подсказали алгоритм, который работает с любой вложенностью! :)
/// Где-то
connect(treePhaseView, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this,
        SLOT(itemPress(QTreeWidgetItem*, int)));

/// Нажатие на элемент дерева
void TLV::itemPress(QTreeWidgetItem* item, int column)
{
    if(item == 0) return;

    Qt::CheckState check = item -> checkState(column);
    QList<QTreeWidgetItem*> items;        items << item;

    while(!items.isEmpty())
    {
        QTreeWidgetItem *itm = items.takeFirst();
        for(register int i=0; i<itm -> childCount(); ++i)
        {
            QTreeWidgetItem *child = itm -> child(i);
            child -> setCheckState(column, check);
            items << child;
        }
    }

    QTreeWidgetItem* parent = item -> parent();
    if(parent == 0) return;
    bool all = true;
    for(register int i=0; i<parent -> childCount(); ++i)
    {
        QTreeWidgetItem* child = parent -> child(i);
        if(child == 0) break;
        if(item != child && child -> checkState(column) != Qt::Unchecked)
        { all = false; break; }
    }
    if(all) parent -> setCheckState(column, check);
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 27.2.2009, 11:12
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Вот решение для QTreeView


Tree Model
#ifndef OBJECT_TREE_MODEL_H
#define OBJECT_TREE_MODEL_H

#include <QStandardItemModel>

/// Класс модели описания дерева этапов полета
class ObjectTreeModel: public QStandardItemModel
{
    Q_OBJECT

public:
    ObjectTreeModel(QObject* parent = 0): QStandardItemModel(parent)
    { connect(this, SIGNAL(itemChanged(QStandardItem*)), SLOT(itemPress(QStandardItem*))); }
    ~ObjectTreeModel() {}

protected slots:
    void itemPress(QStandardItem* item);
};

#endif // OBJECT_TREE_MODEL_H





#include "ObjectTreeModel.h"
#include "QGlobal.h"

#include <string>
using namespace std;

/// Нажатие на элемент дерева
void ObjectTreeModel::itemPress(QStandardItem* item)
{
    if(!item -> isCheckable() || item -> column() != 0) return;

    Qt::CheckState state = item -> checkState();
    string item_text(item -> text().toStdString());
    if(state == Qt::Checked || state == Qt::Unchecked)
    {
        for(register int i=0; i<item -> rowCount(); ++i)
        {
            QStandardItem* child(item -> child(i));
            if(child == 0) break;
            if(child -> isCheckable() && child -> checkState() != state) child -> setCheckState(state);
        }
    }

    QStandardItem* parent(item -> parent());
    if(parent == 0) { writeElement(item_text.c_str(), state); return; }
    string parent_text(parent -> text().toStdString());
    if(item -> rowCount() == 0 && item -> text().indexOf(".log", 0, Qt::CaseInsensitive) != -1)
        item_text += "_" + parent_text;
    if(parent && parent -> isCheckable())
    {
        Qt::CheckState _state = parent -> child(0) -> checkState();
        if(_state == Qt::PartiallyChecked) parent -> setCheckState(_state);
        else
        {
            register int i = 1;
            for(;i<parent -> rowCount() && parent -> child(i) -> checkState()==_state; ++i);
            if(i != parent -> rowCount()) _state = Qt::PartiallyChecked;
            parent -> setCheckState(_state);
        }                
    }
    writeElement(item_text.c_str(), state);    ///< запись значения в реестр
}


Сообщение отредактировал AD - 27.2.2009, 11:26
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Тема закрытаНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.3.2024, 18:56