Russian Qt Forum
Ноябрь 24, 2024, 10:59 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: QTreeWidget - нажатие на узел дерева  (Прочитано 30191 раз)
AD
Гость
« Ответ #15 : Февраль 24, 2009, 21:24 »

Кто-нибудь, помогите, пожалуйста!
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #16 : Февраль 24, 2009, 22:56 »

Итератор, который проходит все элементы, начиная с item! Почему он не считает элемент item базовым, т.е. максимальная проходимость - это родитель элемента item? Как обрезать его дальнейший проход?

Что-то неопнятны вопросы... QTreeWidgetItemIterator пройдет по всем подчиненным айтемам и подчиненным айтемам подчиненных айтемов и т.д.  Улыбающийся

Уточни свои вопросы.

ЗЫ: Приаттач свой компилябельный код, чтобы самому не писать экзампл.
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Sergeich
Гость
« Ответ #17 : Февраль 24, 2009, 23:32 »

При нажатии на чекбокс выделяюся все потомки, при снятии галочки все дочерние соответсвенно помечаются ненажатыми, плюс прмежуточное состояние, когда отмечено не все:

objecttreemodel.h
Код:
#ifndef OBJECT_TREE_MODEL_H
#define OBJECT_TREE_MODEL_H

#include <QStandardItemModel>

class ObjectTreeModel : public QStandardItemModel
{
Q_OBJECT
public:
ObjectTreeModel( QObject* parent = 0 );
protected slots:
void onItemChanged( QStandardItem* item );
};

#endif // OBJECT_TREE_MODEL_H

objecttreemodel.cpp
Код:
#include "objecttreemodel.h"

ObjectTreeModel::ObjectTreeModel( QObject* parent )
: QStandardItemModel( parent )
{
connect( this, SIGNAL(itemChanged(QStandardItem*)), SLOT(onItemChanged(QStandardItem*)) );
}

void ObjectTreeModel::onItemChanged( QStandardItem* item )
{
if ( !item->isCheckable() || item->column() != 0 )
return;

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

QStandardItem* parent = item->parent();
if ( parent && parent->isCheckable() ) {
state = parent->child(0)->checkState();
if ( state == Qt::PartiallyChecked )
parent->setCheckState( state );
else {
int i = 1;
while ( i < parent->rowCount() && parent->child(i)->checkState() == state )
i++;
if ( i != parent->rowCount() )
state = Qt::PartiallyChecked;
parent->setCheckState( state );
}
}

}
Записан
AD
Гость
« Ответ #18 : Февраль 25, 2009, 10:29 »

Цитата: Sergeich
При нажатии на чекбокс выделяюся все потомки, при снятии галочки все дочерние соответсвенно помечаются ненажатыми, плюс прмежуточное состояние, когда отмечено не все:
Sergeich, cпасибо. Попробую

Цитировать
Уточни свои вопросы.

ЗЫ: Приаттач свой компилябельный код, чтобы самому не писать экзампл.
Так spirit накатал компилябельный код. Осталось main добавить и усе!
pastor, что именно уточнять и не знаю. Все вроде бы сказал. Мне неясно, почему итератор идет по всем оставшимся после item узлам. Мне казалось, в нем должен быть немного другой принцип работы....
Записан
AD
Гость
« Ответ #19 : Февраль 25, 2009, 10:41 »

Sergeich, я правильно понял, что мне следует сделать представление вместо виджета, т.е. QTreeView вместо QTreeWidget. А в качестве модели задать созданную Вами на основе QStandardItemModel?
Записан
spirit
Гость
« Ответ #20 : Февраль 25, 2009, 10:43 »

имхо, алгоритм Сергеича можно адаптировать к вашей задачи не используя модели.
Записан
AD
Гость
« Ответ #21 : Февраль 25, 2009, 11:10 »

Цитата: spirit
имхо, алгоритм Сергеича можно адаптировать к вашей задачи не используя модели.
Это и пытался сделать, но нет у QTreeWidgetItem функции rowCount(), а без нее самому считать? Или как?
Записан
spirit
Гость
« Ответ #22 : Февраль 25, 2009, 11:12 »

childCount == rowCount
Записан
AD
Гость
« Ответ #23 : Февраль 25, 2009, 12:42 »

Sergeich, спасибо большое за идею. Чтобы не использовать модель, по совету spiritа постарался подкорректировать алгоритм под свой QTreeWidgetItem. Единственное, что мне в том алгоритме не нужно было - это третье состояние. Пользователей оно введет в транс, им оно не нужно. Поэтому его нафиг убрал. После обработки напильником, рубанком и наждачной бумагой вышло такое: Улыбающийся
Код
C++ (Qt)
/// Нажатие на элемент дерева
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;
parent -> setCheckState(column, state);
}
 

Понимаю, алгоритм получился не самым удачным. Была бы вложенность листьев равна 5-6 или более, то такая штука не прокатила бы, но через рекурсию как было показано в ранних постах, не прокатывает. Если это делать через модель, то думаю, алгоритм Sergeicha подошел бы идеально.
Осталось чуть скорректировать работу отметки предка и все нормуль будет! Улыбающийся
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #24 : Февраль 25, 2009, 12:48 »

Мне неясно, почему итератор идет по всем оставшимся после item узлам.

"после" имеется в виду по тем, которые с ним на одном уровне вложенности?
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
AD
Гость
« Ответ #25 : Февраль 25, 2009, 12:58 »

Цитировать
"после" имеется в виду по тем, которые с ним на одном уровне вложенности?
Ну не совсем. Проверка всех элементов того же уровня вложенности и его родителя. Не более. Никаких соседей учитывать не надо, а итератор учитывает...


Сделал окончательный вариант. Получилось такое чудо:
Код
C++ (Qt)
/// Нажатие на элемент дерева
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);
}
 
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #26 : Февраль 25, 2009, 13:57 »

Да, с итератором там все понятно.. )))

Немного передалал твой код, вернее только его первую часть. Теперь она способна "выдержать" любой уровень вложенности и без рекурсии. Я законектил этот слот на itemClicked вместо itemPressed (т.к. наблюдались глюки при быстром кликанье на узле)

Код
C++ (Qt)
void TreeWidget::treeItemPress(QTreeWidgetItem *item, int column)
{
   if (!item) return;
 
   Qt::CheckState check = item->checkState(0);
   QList<QTreeWidgetItem *> items;
   items << item;
 
   while (!items.isEmpty()) {
       QTreeWidgetItem *itm = items.takeFirst();
       for (int i = 0; i < itm->childCount(); ++i) {
           QTreeWidgetItem *child = itm->child(i);
           child->setCheckState(0, 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);
}

Вторую часть кода я не трогал, так как несовсем понял что нужно получить в итоге. Если установлено состояние для айтема как checked то и для родителя устанавливается точно такое-же состояние. А вот для прародтеля нет. И это несовсем понятно (логично).

Я бы восользовался 3 состояниями:

checked - выделены все айтемы
unchecked - не выделен ниодин
partially checked - выделены не все айтемы
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
spirit
Гость
« Ответ #27 : Февраль 25, 2009, 14:01 »

Цитировать
Я бы восользовался 3 состояниями:

checked - выделены все айтемы
unchecked - не выделен ниодин
partially checked - выделены не все айтемы
+1
Записан
AD
Гость
« Ответ #28 : Февраль 25, 2009, 14:16 »

Да, с итератором там все понятно.. )))

Немного передалал твой код, вернее только его первую часть. Теперь она способна "выдержать" любой уровень вложенности и без рекурсии. Я законектил этот слот на itemClicked вместо itemPressed (т.к. наблюдались глюки при быстром кликанье на узле)

Вторую часть кода я не трогал, так как несовсем понял что нужно получить в итоге. Если установлено состояние для айтема как checked то и для родителя устанавливается точно такое-же состояние. А вот для прародтеля нет. И это несовсем понятно (логично).

Я бы восользовался 3 состояниями:

checked - выделены все айтемы
unchecked - не выделен ниодин
partially checked - выделены не все айтемы
ООО, вот тоже такие глюки наблюдаю. Спасибо, попробую! Улыбающийся

Спасибо, попробую этот код. Нет, 3 состояния - перебор. У летчиков мозги съедут. Если хотя-бы один элемент (лист) (т.е. название файла) присутствует в этапе полета (узел), тогда этот элемент выделен. Да и потом на таком принципе удобнее дальнейшую обработку вести (в смысле когда 2 состояния)!
Записан
spirit
Гость
« Ответ #29 : Февраль 25, 2009, 14:18 »

ну тебе виднее, но логичнее всего и правилнее -- это как сказл pastor иметь три состояния. Подмигивающий
Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.18 секунд. Запросов: 23.