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

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

Голосование
Вопрос: QT4. QTreeView+CheckBox  (Голосование закончилось: Май 23, 2007, 18:33)
Желательно указать пример кода. - 2 (40%)
Где описывается в Help QT4 - 3 (60%)
Всего голосов: 2

Страниц: [1]   Вниз
  Печать  
Автор Тема: QT4. Вопрос по QTreeView, как отобразить в нем CheckBox.  (Прочитано 17181 раз)
leobear
Гость
« : Май 23, 2007, 18:33 »

Смысл вопроса в том, что хотелось бы использовать модель, потому был взят класс QTreeView. Но у него нет функций как у QTreeWidget:

ТreeWidget->setItemWidget() - например для установки QCheckBox,

и как у QTreeWidgetItem нет функции

ItemWidget->setCheckState(0, Qt::Unchecked) - например.

Может я не досмотрел, но два дня потратил. Подскажите.
 :wink:  :?:  :wink:  :?:
Записан
SABROG
Гость
« Ответ #1 : Май 23, 2007, 21:38 »

Раз уж model based берешь, тогда смотри в сторону моделей. Например QStandardItemModel, где итемы QStandardItem, вот у него-то как-раз и есть чекбокс.
Записан
itan
Гость
« Ответ #2 : Май 24, 2007, 08:50 »

Код:
Qt::ItemFlags CTreeCheckedModel::flags(const QModelIndex &index) const
{
      if (!index.isValid())
         return Qt::ItemIsEnabled;

         return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
}

Цитировать
Qt::ItemIsUserCheckable
It can be checked or unchecked by the user.
Записан
leobear
Гость
« Ответ #3 : Май 25, 2007, 13:53 »

Ответ Itan:
Функцию flags() переопределил,
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
      if (!index.isValid())
         return Qt::ItemIsEnabled;

         return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
}
Понажатию мыши функция вызывается но нужной мне галочки невижу. Может нужна для этого специально выделенная колонка, или еще что-то.

Ответ SABROG:
Класс TreeModel наследуется от QAbstractItemModel. Переделал наследование от QStandardItemModel теперь не рисуется мое дерево.

добавлено спустя 13 минут:

 Для понятности, использую пример из QT4.2.2 examples/itemviews/simpletreemodel/treemodel.h. В нем либо переделать наследование на QStandardItemModel либо разобраться с функцией flags().


 :oops:  :oops:  :oops:
Записан
itan
Гость
« Ответ #4 : Май 25, 2007, 15:09 »

Чтобы увидеть галочки, их нужно возвращать в методе data() типа так:
Код:
QVariant CTreeCheckedModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();

CTreeItem *item = static_cast<CTreeItem*>(index.internalPointer());

if ( role == Qt::CheckStateRole )
{
return item->checkState();
}
 return QVariant();
}


А устанавливаются они через setData():
Код:
bool CTreeCheckedModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid())
return false;

CTreeItem *item = static_cast<CTreeItem*>(index.internalPointer());
if (role ==  Qt::CheckStateRole)
{
Qt::CheckState checkState = static_cast<Qt::CheckState>(value.toInt());
item->setCheckState(checkState);

return true;
}

return false;
}
Записан
leobear
Гость
« Ответ #5 : Май 25, 2007, 16:32 »

Спасибо за ответ Itan.  Подскажи как быть с данными которые возвращаются тоже функцией data().
Вот класс TreeItem:

class TreeItem
{
private:
    TreeItem *           parentItem;
    QList<TreeItem*>     childItems;

    QList<QVariant>      itemData;
    Qt::CheckState       checkSt;      //Добавил по твоей рекомендации

public:
    TreeItem(const QList<QVariant> &data, TreeItem *parent = 0);
    ~TreeItem();

    void       appendChild(TreeItem *child);

    TreeItem *child       (int row);
    TreeItem *parent      ();

    QVariant  data        (int column) const;

    int       childCount  ()           const;
    int       columnCount ()           const;
    int       row         ()           const;
    void             setCheckState(Qt::CheckState st);
    Qt::CheckState      checkState() { return checkSt; }
};

Завел функцию setData() по рекомендации твоего предыдущего сообщения.
Переделал функцию data().
Дерево рисуется но галочек нет. Немного не понятно как взаимодействуют функции setData() и flags().

QVariant TreeModel::data(const QModelIndex &index, int role) const
{
  if (!index.isValid())        return QVariant();
  if (role != Qt::DisplayRole) return QVariant();

  TreeItem *item = static_cast<TreeItem*>(index.internalPointer());

  if ( role == Qt::CheckStateRole ) return item->checkState();

  return item->data(index.column());  //Наверное должно быть так.
}


 :?  :?
Записан
itan
Гость
« Ответ #6 : Май 25, 2007, 18:22 »

Цитировать
Дерево рисуется но галочек нет

Конечно их не будет! Ты же сам игнорируешь роль Qt::CheckStateRole! Смотри внимательнее:
Код:
QVariant TreeModel::data(const QModelIndex &index, int role) const 
{
if (!index.isValid()) return QVariant();
if (role != Qt::DisplayRole) return QVariant();

TreeItem *item = static_cast<TreeItem*>(index.internalPointer());

if ( role == Qt::CheckStateRole ) return item->checkState();

return item->data(index.column()); //Наверное должно быть так.
}


Если работаешь с примером SimpleTreeModel, то CheckBox во 2-м столбце можно отключить:
Код:
 if (index.column() == 0 && role == Qt::CheckStateRole ) return item->checkState(); 
Записан
leobear
Гость
« Ответ #7 : Май 28, 2007, 14:00 »

Цитировать
Ты же сам игнорируешь роль Qt::CheckStateRole! Смотри внимательнее:

Сори, дело не во внимательности, а в непонимании мат.части, потому я и нахожусь на форуме. Действительно многое почерпнул на форуме.

Напишу как я понимаю работу функции QVariant TreeModel::data(const QModelIndex &index, int role) const:

Код:

QVariant TreeModel::data(const QModelIndex &index, int role) const
{
  if (!index.isValid()) return QVariant();
  if (role != Qt::DisplayRole) return QVariant();

  /*--- создается указатель на типа TreeItem для возможности
          обращения к данным данного типа ---*/
  TreeItem *item = static_cast<TreeItem*>(index.internalPointer());

  /*--- если role == Qt::CheckStateRole то запрашиваем данные у
          конкретного item-а, возвращаем для визуализации галочки*/
  if ( role == Qt::CheckStateRole ) return item->checkState();

  /*--- Вывод самих данных ячейки ---*/
  return item->data(index.column());
}


Причем, самого столбца для галочек я не выделяю, галочка должна рисоваться перед самим текстом Итема, вне зависимости от вложенности Итема (может здесь мое заблуждение).

Цитировать

Если работаешь с примером SimpleTreeModel, то CheckBox во 2-м столбце можно отключить:
Код:
 if (index.column() == 0 && role == Qt::CheckStateRole ) return item->checkState();


Как я понимаю данное условие и return наоборот вкл. галочку.

Немного не понятно как взаимодействуют функции setData() и flags().

добавлено спустя 28 минут:

 Переделал, добавил для галочки второй столбец:
Код:

Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
  if (!index.isValid()) return Qt::ItemIsEnabled;

  Qt::ItemFlags flags;
  if (index.column() == 0) flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable ;
  if (index.column() == 1) flags |= Qt::ItemIsUserCheckable;
  return flags;
}
//___________________________________________________________
QVariant TreeModel::data(const QModelIndex &index, int role) const
{
  if (!index.isValid())        return QVariant();
  if (role != Qt::DisplayRole) return QVariant();

  TreeItem *item = static_cast<TreeItem*>(index.internalPointer());

  if (index.column() == 1 && role == Qt::CheckStateRole ) return item->checkState();

  return item->data(index.column());
}


Ничо не понимаю, как эти галочки отобразить, может нужно еще что-то  инициализировать.

добавлено спустя 5 минут:

 На ино-форуме:
http://forum.qtfr.org/viewtopic.php?pid=19955
На другом форуме:
http://ru.opensuse.org/QT_%D0%B8_%D0%91%D0%B0%D0%B7%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85
Записан
itan
Гость
« Ответ #8 : Май 28, 2007, 15:20 »

Цитировать
Сори, дело не во внимательности, а в непонимании мат.части, потому я и нахожусь на форуме. Действительно многое почерпнул на форуме.

Нет, тут дело именно в невнимательности... Давай для начала перепишим метод data() следующим образом:
Код:
Variant TreeModel::data(const QModelIndex &index, int role) const 
{
  if (!index.isValid())        return QVariant();
  if (role != Qt::DisplayRole && role !=  Qt::CheckStateRole) return QVariant();

  TreeItem *item = static_cast<TreeItem*>(index.internalPointer());

  if (index.column() == 0 && role == Qt::CheckStateRole ) return item->checkState();

  return item->data(index.column());
}
Записан
leobear
Гость
« Ответ #9 : Май 28, 2007, 16:05 »

Заменил функцию data на твой вариант.

Только не могу понять как это если role  не равно Qt::CheckStateRole оно рисует CheckState.

Код:

if (role != Qt::DisplayRole && role !=  Qt::CheckStateRole) return QVariant();


О, получается. Переписал и функцию flags:

Код:

Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
  if (!index.isValid()) return Qt::ItemIsEnabled;

  Qt::ItemFlags flags;
  if (index.column() == 0) flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
  return flags;
}


Теперь нужно сделать функцию которая бы выделяла дерево если выделены все Итемы.

добавлено спустя 28 минут:

 Проанализировал строчку
Код:

if (role != Qt::DisplayRole && role !=  Qt::CheckStateRole) return QVariant();

Теперь понятно, если нет Qt::CheckStateRole вываливаем из функции иначе рисуем.

Конечно тему можно закрыть Itan-у ЖМУ "лапу".


Интересна будет тема о разнице QTreeView и QTreeWidget и что лучше использовать. Может начать такую тему?
Записан
itan
Гость
« Ответ #10 : Май 28, 2007, 16:49 »

Цитировать
Немного не понятно как взаимодействуют функции setData() и flags().

На сколько я понимаю, делегат (QItemDelegate) использует метод
1. data() при отрисовке checkBox'а:
Код:
void QItemDelegate::paint(QPainter *painter,
                          const QStyleOptionViewItem &option,
                          const QModelIndex &index) const
{
...
   QRect checkRect;
    Qt::CheckState checkState = Qt::Unchecked;
    value = index.data(Qt::CheckStateRole);
    if (value.isValid()) {
        checkState = static_cast<Qt::CheckState>(value.toInt());
        checkRect = check(opt, opt.rect, value);
...

2. метод flags() при редактирование элементов (проверяет разрешение на редактировние как таковое):
Код:
 // make sure that the item is checkable
    Qt::ItemFlags flags = model->flags(index);
    if (!(flags & Qt::ItemIsUserCheckable) || !((flags & Qt::ItemIsEnabled)))
        return false;

3. метод setData() для применения изменений в случае правильно выставленных флагов:
Код:
return model->setData(index, state, Qt::CheckStateRole);


Цитировать
Только не могу понять как это если role не равно Qt::CheckStateRole оно рисует CheckState.
Код:
if (role != Qt::DisplayRole && role !=  Qt::CheckStateRole) return QVariant();

Вот такой вот хитрый язык, этот С++ Улыбающийся Пройдись дебаггером, все поймешь.
Записан
leobear
Гость
« Ответ #11 : Май 28, 2007, 17:29 »

Получается, если QItemDelegate отрисовывает СheckBox в дереве, тогда нет необходимости использовать в QTreeView дополнительных Делегатов.

Вопрос:
1. Какие  возможности отрисовки и редактирование можно выполнить через флаги "enum Qt::ItemFlag"? Например выпадающее меню, отображение картинки или редактирование поля и т.д.

2. Почему галочка отображается только при непосредственном нажатии на поле CheckBox, а не при нажатии на строку с CheckBox-ом?
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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