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

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

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: QTableWidget иерархические заголовки  (Прочитано 17743 раз)
Иваныч
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #15 : Август 21, 2019, 17:00 »

Спасибо за совет Улыбающийся Я же новичок:)
В архиве последняя версия.
« Последнее редактирование: Август 21, 2019, 17:10 от Иваныч » Записан
Иваныч
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #16 : Август 22, 2019, 11:23 »

Чёт я сам с собою Улыбающийся
Иногда полезно просто высказаться.
paintSection константная функция и вызвать из нее слот для обновления соседней секции ну никак не удавалось.
Написал в своем классе константный сигнал и законнектил на неконстантный слот. Всё заработало.
Новый код paintSection

Код:
void CDataHeaderView::paintSection(QPainter* pPainter,const QRect& rect,int logicalIndex) const
{
QStandardItem* pItem=m_headerModel.item(0,logicalIndex);
QVariant data=pItem->data();
QRect rc=rect;
    if(!data.isNull())//пока вот так ловлю "костыль"
    {
        pItem=m_headerModel.item(0,0);
rc.setLeft(sectionPosition(0));
rc.setWidth(sectionSize(0));
    }

    //Теперь начинаю разбирать новости
int colCount=pItem->columnCount();//ловлю элементы с вложенными колонками


if(colCount)//знаю про первую сложную колонку
    {
        int w=sectionSize(1);//индекс пока в тупую 1
        rc.setWidth(rc.width()+w);
        rc.setHeight(QHeaderView::sizeHint().height());

QRect rcs=rc;
QList<QStandardItem*>cols=pItem->takeRow(0);
for(int n=0;n<cols.size();n++)
{
QStandardItem* pColItem=cols[n];
rcs.setLeft(sectionPosition(n));
rcs.setWidth(sectionSize(n));
rcs.setTop(QHeaderView::sizeHint().height());
rcs.setHeight(QHeaderView::sizeHint().height());
pPainter->drawRect(rcs);
QString name=pColItem->text();
pPainter->drawText(rcs,Qt::AlignHCenter|Qt::AlignVCenter,name);
}
    }

    pPainter->drawRect(rc);
    pPainter->drawText(rc,Qt::AlignHCenter|Qt::AlignVCenter,pItem->text());

//if(colCount)//знаю про первую сложную колонку
    //{

    //}
if(!data.isNull())//пока вот так ловлю "костыль"
emit drawSection(0);
}
Записан
Иваныч
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #17 : Август 22, 2019, 11:27 »

Сознательно не усложняю код для обработки иерархии.
Хочу на простом примере разобраться.
Сейчас ну никак не рисуются два нижних подзаголовка, хотя отладчик туда попадает.
И геометрия правильная.
« Последнее редактирование: Август 22, 2019, 11:34 от Иваныч » Записан
Иваныч
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #18 : Август 22, 2019, 12:20 »

Ну что, благодаря форуму вопрос решил Улыбающийся
Последняя ошибка связана была с тем, что QStandardItem::takeRow(...)
не только возвращает столбцы строки, но и удаляет их.
Перешел на функцию child(...) и всё заработало.
« Последнее редактирование: Август 22, 2019, 15:17 от Иваныч » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #19 : Август 22, 2019, 12:43 »

Ну что, благодаря форуму вопрос решил Улыбающийся

Это хорошо. На форум надейся, а сам не плошай Улыбающийся.
Записан

Пока сам не сделаешь...
Dimas
Чайник
*
Offline Offline

Сообщений: 50



Просмотр профиля
« Ответ #20 : Август 22, 2019, 13:14 »

Для истории прикрепите пожалуйста итоговую версию
Записан

qt 4.8.6, qt 5.12.4
Иваныч
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #21 : Август 22, 2019, 14:34 »

Ещё раз выражаю огромную благодарность
Zmeishe  
http://www.prog.org.ru/topic_6637_15.html
Ответ #25 : Апрель 05, 2008, 08:40
Не нашёл способа на форуме сделать это лично, да и времени прошло... Надеюсь он вырос в нашей среде.
И дай Бог ему здоровья.

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

Переопределяемая QHeaderItemView::paintSection(...) const не позволяет внутри себя вызывать слоты базового класса
для перерисовки объединенных ячеек. Для реализации необходимого был введен константный сигнал
signals:
   void drawSection(int Idx) const;

который я связал с нужным слотом

connect(this,SIGNAL(drawSection(int)),this,SLOT(updateSection(int)));

Работает. Хотя, намеренно последовательно излагал свои шаги, чтобы уберечься от "костылей" Улыбающийся

Последние штрихи связаны с текущим уровнем новичка, который на Ваших глазах подрос Улыбающийся
Новичок мотивирован на получение знаний и летает с удовольствием на c++ и Qt Улыбающийся

Прилагаю финальный архив.
Сейчас занимаюсь абстрагированием изученного кода, чтобы реализовать многоуровневую вложенность заголовков.
Как писал стратег Zmeishe(с)
"
Далее создаём функцию
QVariant headerData(int Section, Qt::Orientation orientation, int nRole) const;
Вообще это функция Модели её там надо было перекрывать, но я сделал здесь, т.к. уже написал, что не принял оконч. решения где им быть.
Для работы headerData понадобятся две рекурсивные функции, которые по int Section будут возвращать номер начальной секции группы (ветки) в которую входит Section и номер конечной секции группы.
"

Некоторое время, пока код не начал обрастать корпоративными особенностями, готов им делиться Улыбающийся
« Последнее редактирование: Август 22, 2019, 17:46 от Иваныч » Записан
Иваныч
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #22 : Август 22, 2019, 14:49 »

Закралась мысль Подмигивающий
Будь я поближе к разработчикам Qt, то научил бы QHeaderView правильно разгребать модель,
дабы не устраивать пляски вокруг известной темы иерархических заголовков Улыбающийся
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #23 : Август 22, 2019, 14:58 »

Будь я поближе к разработчикам Qt, то научил бы QHeaderView правильно разгребать модель,
дабы не устраивать пляски вокруг известной темы иерархических заголовков Улыбающийся

Тогда становитесь ближе, вносите свой вклад: Contribute to Qt Улыбающийся.
Записан

Пока сам не сделаешь...
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #24 : Август 22, 2019, 15:28 »

Вот подходящий тикет: Use span data from QAbstractItemModel in QTableView. Ему всего 10 лет Улыбающийся.

Хотя нет, это не про заголовки.
« Последнее редактирование: Август 22, 2019, 15:40 от ViTech » Записан

Пока сам не сделаешь...
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #25 : Август 22, 2019, 15:53 »

Хотя нет, это не про заголовки.

Я начал писать долгий текст с тем же посылом, но потом бросил, ибо...
Если мы хотим иерархические заголовки с несколькими рядами/колонками и спанами то мы придем к тому, что такому заголовку надо устанавливать отдельную _модель_ которая будет отдавать данные для хедера через rowCount/columnCount/index/data а не через headerData. Иначе придется тупо продубрировать весь API еще и для хедера (headerRowCount/headerColumnCount/headerIndex (мы же хотим деревья)/headerData/headerSpan). Кажется, такой подход слишком сложный (особенно если учесть что в горизонтальном хедере должно быть headerRowCount рядов но columnCount (без header) колонок, чтобы колонки/ряды совпадали с теми, что в основной таблице. а в вертикальном - всё наоборот). А еще надо теперь не запутаться где headerIndex а где обычный и не перепутать их случайно.
Так что да, это таки применимо, но как указано выше - для кастомной view, которая игнорит headerData и берет данные из отдельной полноценной модели.
Записан
Иваныч
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #26 : Август 22, 2019, 16:56 »

Абстрагировался немного. Теперь дополнительные столбцы мечу индексами в подзаголовках.
Шалю с третьим столбцом.
Архив и результат на экране выкладываю.
В результате смущает игра с толщиной текста в сложных заголовках.
Понятно, что от лишней перерисовки Непонимающий не зря же слот так просто не вызывался.
Руки чешутся - теперь абстрактно пойду на третий этаж заголовка Улыбающийся
« Последнее редактирование: Август 22, 2019, 17:03 от Иваныч » Записан
Иваныч
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #27 : Август 22, 2019, 17:34 »

Мне бы в данный момент (для лазания по этажам) пригодился QStandatrdItem::parent(),
но он в нуле, казалось бы у дочерних элементов (подстолбцов). Попробовал для их
добавления использовать setChild(...) вместо appendRow(...) эффект тот же.
Ни в конструкторах ничего про parent, ни в методах...

Может подскажет кто как проинициализировать parent в дочерних элементах QStandatrdItem Непонимающий

Понятно, что от безысходности можно вопрос решить усложнением QStandardItem::data,
но не хотелось бы Улыбающийся
« Последнее редактирование: Август 22, 2019, 17:41 от Иваныч » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #28 : Август 22, 2019, 18:25 »

Если хотите нестандартного поведения от таблицы, лучше пользуйтесь QAbstractItemModel и QTableView/QAbstractItemView. Их можно гибче настроить под свои хотелки, чем готовые модели/виды переделывать.
Записан

Пока сам не сделаешь...
Иваныч
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #29 : Август 30, 2019, 17:42 »

Спасибо за участие Улыбающийся. Воспользовался Вашим советом, но в итоге (по моему разумению) всё равно всё сводится к
эффективному переопределению QHeaderView::paintSection(...) const.
Повозился, нашёл, что некорректно работает QHeaderView::sectionPosition(...) при сдвиге ScrollBar-а. Для всех
секций, слева за окном возвращает 0. Справился через перебор QHeaderView::sectionWidth(...).
Разделил операции наполнения "дерева" сложных колонок и формирования дополнительных колонок.
Рекурсия рулит на разборе строки с колонками и их отрисовке.
Для отладки внедрил над таблицей счетчик отрисовок секций.
Жалко, что никто особо не поддержал тему Грустный.
Честь имею.
Результаты прилагаю.
« Последнее редактирование: Август 30, 2019, 18:00 от Иваныч » Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


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