Название: Как создать DelegateItem с wordWrap для QTreeWidget?
Отправлено: billy4685 от Июль 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?
Название: Re: Как создать DelegateItem с wordWrap для QTreeWidget?
Отправлено: billy4685 от Июль 27, 2020, 16:20
Ах да, забыл. Вот сам проект.
Название: Re: Как создать DelegateItem с wordWrap для QTreeWidget?
Отправлено: Igors от Июль 27, 2020, 17:58
Что еще нужно дописать в DelegeteItem, чтобы при изменении ширины QTreeWidget менялась и высота для каждого QTreeWidgetItem?
Посмотрите setUniformRowHeights(false)
Название: Re: Как создать DelegateItem с wordWrap для QTreeWidget?
Отправлено: billy4685 от Июль 28, 2020, 13:47
Что еще нужно дописать в DelegeteItem, чтобы при изменении ширины QTreeWidget менялась и высота для каждого QTreeWidgetItem?
Посмотрите setUniformRowHeights(false) Задал я это свойство для QTreeWidget, но ничего не изменилось. Думаю мне нужно в классе DelegateItem дописать какой-то метод, чтобы в метод paint option.rect попадал с измененной высотой. А то выходит, что option.rect.width меняется, а option.rect.height всегда постоянный для конкретного Itema, и походу эта высота максимальная (тоесть как буд-то у нас QTreeWidget зжат до минимальной ширины). Но пока не могу понять, куда мне дальше двигаться.
Название: Re: Как создать DelegateItem с wordWrap для QTreeWidget?
Отправлено: billy4685 от Сентябрь 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 (с максимальным переносом строк) и размер, когда строка без переносов. Если у когото есть дельный совет, радости прошу.
|