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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как создать DelegateItem с wordWrap для QTreeWidget?  (Прочитано 1169 раз)
billy4685
Крякер
****
Offline Offline

Сообщений: 303


Просмотр профиля
« : Июль 27, 2020, 16:17 »

Здравствуйте, господа форумчане.

Задался тут я вопросом: Как в QTreeWidget для QTreeWidgetItem сделать перенос строки (wordWrap).
QTreeWidget имеет свойство wordWrap, но оно просто добавляет три точки, а не переносит саму строку.
Посмотрев в инете, нашел совет писать свой DelegateItem. Порывшись по примерам, что-то удалось написать.

Создал форму QMaiWindow. На форму положил QWidget и QTextBrowser. Взял эти два компонента под горизонтальный
сплитер. Далее на QWidget добавил QLabel и QTreeWidget, взял их в QGridLayout. Создал свой класс DelegateItem.
Вот код, а то словами долго описывать придется:

файл main.cpp
Код:
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}

файл mainwindow.h
Код:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H


#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

private:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

файл mainwindow.cpp
Код:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "delegateitem.h"
#include <QStyleFactory>

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
ui->setupUi(this);

DelegateItem * delegate = new DelegateItem;
ui->treeWidget->setItemDelegate(delegate);
ui->treeWidget->resizeColumnToContents(0);
ui->treeWidget->header()->setStretchLastSection(true);
ui->treeWidget->setTextElideMode(Qt::ElideNone);
ui->treeWidget->setStyle(QStyleFactory::create("windows"));

QIcon page_icon;
page_icon.addPixmap(QPixmap(":/icons/file.png"), QIcon::Normal, QIcon::On);

QTreeWidgetItem *item1 = new QTreeWidgetItem;
item1->setFlags(item1->flags() | Qt::ItemIsEditable);
item1->setIcon(0, page_icon);
item1->setText(0, "1. Вступ до історії України");
ui->treeWidget->addTopLevelItem(item1);

QTreeWidgetItem *item2 = new QTreeWidgetItem;
item2->setFlags(item2->flags() | Qt::ItemIsEditable);
item2->setIcon(0, page_icon);
item2->setText(0, "2. Стародавня історія України");
ui->treeWidget->addTopLevelItem(item2);

QTreeWidgetItem *item3 = new QTreeWidgetItem;
item3->setFlags(item3->flags() | Qt::ItemIsEditable);
item3->setIcon(0, page_icon);
item3->setText(0, "3. Київська держава (Русь-Україна)");
ui->treeWidget->addTopLevelItem(item3);

QTreeWidgetItem *item4 = new QTreeWidgetItem;
item4->setFlags(item4->flags() | Qt::ItemIsEditable);
item4->setIcon(0, page_icon);
item4->setText(0, "4. Галицько-Волинська держава. Монгольська навала");
ui->treeWidget->addTopLevelItem(item4);

QTreeWidgetItem *item5 = new QTreeWidgetItem;
item5->setFlags(item5->flags() | Qt::ItemIsEditable);
item5->setIcon(0, page_icon);
item5->setText(0, "5. Литовсько-Руська держава. Українські землі у складі Великого князівства Литовського та інших держав (у другій половині ХІV – першій половині ХVІ ст.)");
ui->treeWidget->addTopLevelItem(item5);

QTreeWidgetItem *item6 = new QTreeWidgetItem;
item6->setFlags(item6->flags() | Qt::ItemIsEditable);
item6->setIcon(0, page_icon);
item6->setText(0, "6. Українські землі у складі Речі Посполитої (друга половина ХVІ ст.)");
ui->treeWidget->addTopLevelItem(item6);
}

MainWindow::~MainWindow()
{
delete ui;
}

файл delegateitem.h
Код:
#ifndef DELEGATENEW_H
#define DELEGATENEW_H

#include <QItemDelegate>
#include <QTreeView>
#include <QResizeEvent>

class DelegateItem : public QItemDelegate
{
protected:
void resizeEvent(QResizeEvent *resize_event);

public:
DelegateItem();
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;

};
#endif // DELEGATENEW_H

файл файл delegateitem.cpp
Код:
#include "delegateitem.h"

#include <QPainter>
#include <QTreeView>

DelegateItem::DelegateItem()
{
}

QSize DelegateItem::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QSize text_size;

text_size = option.fontMetrics.boundingRect(option.rect, Qt::TextWordWrap | Qt::AlignVCenter | Qt::AlignLeft, index.data().toString()).size();

text_size.setWidth(option.fontMetrics.boundingRect(option.rect, Qt::TextWordWrap | Qt::AlignVCenter | Qt::AlignLeft,
   index.data().toString()).size().width());

text_size.setHeight(option.fontMetrics.boundingRect(option.rect, Qt::TextWordWrap | Qt::AlignVCenter | Qt::AlignLeft,
    index.data().toString()).size().height());

return text_size;
}

void DelegateItem::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (option.state & QStyle::State_Selected) {
  painter->fillRect(option.rect, option.palette.highlight());
  painter->setPen(option.palette.highlightedText().color());
  } else {
  painter->setPen(option.palette.text().color());
  }

painter->drawText(QRect(option.rect.x() + option.decorationSize.width() + 5, option.rect.y(), option.rect.width(),
option.rect.height()), Qt::TextWordWrap | Qt::AlignVCenter | Qt::AlignLeft, index.data(Qt::DisplayRole).toString());

sizeHint(option, index);

if (option.state & QStyle::State_Selected) {
  painter->setPen(QColor(Qt::black));
  }
else
  {
  painter->setPen(QColor(Qt::black));
  }

QIcon icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
painter->drawPixmap(option.rect.x(), option.rect.y() + (option.rect.height() - option.decorationSize.height())/2,
    option.decorationSize.width(), option.decorationSize.height(),icon.pixmap(option.decorationSize));
}

файл icons.qrc
Код:
<RCC>
    <qresource prefix="/">
<file>icons/file.png</file>
    </qresource>
</RCC>

Врезультате, перенос строки в каждом DelegateItem удалось сделать, вот только, высота строки расчитывается максимальная
(тоесть при самой маленькой ширине QTreeWidget). И эта высота остается постоянной, и при изменении ширины QTreeWidget она не меняется.

Что еще нужно дописать в DelegeteItem, чтобы при изменении ширины QTreeWidget менялась и высота для каждого QTreeWidgetItem?
Записан
billy4685
Крякер
****
Offline Offline

Сообщений: 303


Просмотр профиля
« Ответ #1 : Июль 27, 2020, 16:20 »

Ах да, забыл. Вот сам проект.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 10958


Просмотр профиля
« Ответ #2 : Июль 27, 2020, 17:58 »

Что еще нужно дописать в DelegeteItem, чтобы при изменении ширины QTreeWidget менялась и высота для каждого QTreeWidgetItem?
Посмотрите setUniformRowHeights(false)
Записан
billy4685
Крякер
****
Offline Offline

Сообщений: 303


Просмотр профиля
« Ответ #3 : Июль 28, 2020, 13:47 »

Что еще нужно дописать в DelegeteItem, чтобы при изменении ширины QTreeWidget менялась и высота для каждого QTreeWidgetItem?
Посмотрите setUniformRowHeights(false)

Задал я это свойство для QTreeWidget, но ничего не изменилось. Думаю мне нужно в классе
DelegateItem дописать какой-то метод, чтобы в метод paint option.rect попадал с измененной
высотой. А то выходит, что option.rect.width меняется, а option.rect.height всегда постоянный
для конкретного Itema, и походу эта высота максимальная (тоесть как буд-то у нас QTreeWidget
зжат до минимальной ширины). Но пока не могу понять, куда мне дальше двигаться.
Записан
billy4685
Крякер
****
Offline Offline

Сообщений: 303


Просмотр профиля
« Ответ #4 : Сентябрь 18, 2020, 16:01 »

Решил я вернуться к данной нерешенной задачи.
Что-то никак не выходит реализовать этот QItemDelegate. (( Текст переносится по строкам,
когда передвигаешь QSplitter. Но высота item в QTreeWidget остается неизменной (большая) (рис. ниже).

Я так понимаю, это происходит из-за того, что я в методе sizeHint использую boundingRect,
который как раз и возвращает максимальную область в которую помещается текст при
максимальном переносе строк.
Код:
text_size = option.fontMetrics.boundingRect(option.rect, Qt::TextWordWrap | Qt::AlignVCenter | Qt::AlignLeft,
                                                  index.data().toString()).size();

Заметил, что setWidth и setHeight были лишними у меня в коде, у себя это убрал:
Код:
text_size.setWidth(option.fontMetrics.boundingRect(option.rect, Qt::TextWordWrap | Qt::AlignVCenter | Qt::AlignLeft,
  index.data().toString()).size().width());

text_size.setHeight(option.fontMetrics.boundingRect(option.rect, Qt::TextWordWrap | Qt::AlignVCenter | Qt::AlignLeft,
   index.data().toString()).size().height());

Теперь догадаться бы как узнать во сколько строк влазить текст в текущий момент или текущую ширину item?
 Тогда можно будет как-то задать текущий размер item опираясь на уже имеющий размер text_size (с максимальным
переносом строк) и размер, когда строка без переносов.

Если у когото есть дельный совет, радости прошу.
« Последнее редактирование: Сентябрь 18, 2020, 16:51 от billy4685 » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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