qtableView автоматический перенос строк
Как можно реализовать автоматический перенос строк в qtableView с фиксированным размером столбцов?
model = new QSqlTableModel(this,db);
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->setTable("TableEventBalancer");
model->select();
ui->tableView->setModel(model);
int id = QFontDatabase::addApplicationFont("/usr/share/fonts/dejavu/DejaVuSansMono.ttf");
QFont font = QFont(QFontDatabase::applicationFontFamilies(id).first());
font.setPointSize(12);
ui->tableView->setFont(font);
ui->tableView->resizeColumnToContents(0);
ui->tableView->resizeColumnToContents(1);
ui->tableView->horizontalHeader()->setResizeMode(0, QHeaderView::Fixed);
ui->tableView->horizontalHeader()->setResizeMode(1, QHeaderView::Fixed);
ui->tableView->horizontalHeader()->setResizeMode(2, QHeaderView::Stretch);
ui->tableView->verticalHeader()->setResizeMode(0, QHeaderView::ResizeToContents);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableView->setWordWrap(true);
ui->tableView->setTextElideMode(Qt::ElideRight);
model->setHeaderData(model->fieldIndex("number"), Qt::Horizontal, QString::fromLocal8Bit("ID"));
model->setHeaderData(model->fieldIndex("_date"), Qt::Horizontal, QString::fromLocal8Bit("Дата"));
model->setHeaderData(model->fieldIndex("text"), Qt::Horizontal, QString::fromLocal8Bit("Событие"));
Ответы (3 шт):
В Qt по каким-то причинам откровенно плохо реализовано вычисление размеров элементов ItemView, особенно в случае деревьев. Согласно документации, должен работать setWordWrap(true), но не работает. Если вызватьsetTextElideMode(Qt::ElideNone) и установить QStyledItemDelegate для проблемных столбцов, в некоторых простых случаях перенос все же сработает, но только если ширина столбцов действительно фиксирована (в вашем случае может сработать). На практике, как минимум при появлении полосы прокрутки возникают проблемы, т.к. размеры ячеек не обновляются при изменении размера viewport. Даже если перенос заработает, неразрывные пробелы игнорируются (это проблему особенно сложно решить), иногда возникают проблемы с кириллицей.
Стандартных решения два: использование ItemWidget с установкой QLabel в качестве содержимого, и использование делегата. Первый вариант не для вашего случая, но иногда полезен. Для второго варианта нужно создать наследник QStyledItemDelegate и переопределить sizeHint и paint. Причем при правильной реализации sizeHint, стандартная реализация paint может сработать корректно, если это простой текст, а не html.
Для реализации делегата есть два подхода. Можно пытаться использовать QTextDocument для отрисовки иQFontMetrics для определения размера. Если ширина ячейки известна, определить высоту не сложно. QTextDocument также умеет отображать html, в отличие от стандартной реализации.
Другой вариант - создать фиктивный QLabel без родителя с setWordWrap(true), и в реализации делегата вызывать label->setFixedWidth(columnWidth); label->setText(text); и использовать его sizeHint для определения размера и render для отрисовки. QLabel тоже умеет в html.
В обоих случаях нужно не забыть учесть отступы, которые получаются из стилей, QStyle::pixelMetric и QStyle::drawControl.
Ну и это все работает только с текстовыми ячейками. Если у вас, например, появляется ячейки с checkbox, все становится сложнее. Я в таких случаях стараюсь использовать QStyledItemDelegate для ячеек с checkbox, и многострочный делегат для остального.
Помимо текста в ячейках, проблема может возникнуть с текстом в заголовках. Решается аналогичным образом, но переопределением QHeaderView.
Для того, чтобы учесть изменение ширины столбцов при появлении полосы прокрутки, приходится устанавливать eventFilter на viewport, и при изменении его размера вызывать dataChanged для всех ячеек, что, мягко говоря, неэффективно, но работатет.
Тоже столкнулся с такой проблемой. Мне помог метод resizeRowsToContents(), только вызывать его надо не при создании таблицы, а каждый раз после добавления элемента.
Странно, у меня есть свой QTableView (4.8.1) и там wrap работает как надо. Естественно надо размер ячейки делать по высоте побольше:

И вот уменьшаем ширину столбца и происходит перенос текста
resizeRowsToContents() у меня не используется.
Делегат для "длинная строка для примера" тоже не используется, то есть делегат штатный по умолчанию.
Кстати какой Qt (версия)?
Чтобы выяснить проблему можно отладчиком пройтись по QTableView::paintEvent(..) и все станет очевидным. Тут гадать бессмысленно, надо смотреть код Qt, как он выполняется.
