简体   繁体   中英

How to use multiline text / linebreaks in QTableView/QAbstractTableModel?

I have subclassed QAbstractTableModel and QTabelView (and QSortFilterProxyModel) and I'd like to allow multi-line text to be displayed to and entered by the user in text cells (currently, hitting return will confirm the edit instead of inserting a line break).

There should be some simple flag to set, I just don't know which one...

QItemDelegate can actually draw the text over multiple lines (if it contains explicit '\n' characters), while the default QStyledItemDelegate doesn't do that (at least not on Linux, I didn't test other platforms). So we'll need to use QItemDelegate for the rendering.

But we also need to change the widget used for editing, which can't be a QLineEdit anymore, it needs to be a QPlainTextEdit . So we'll have to derive from QItemDelegate and change the type of widget being created for editing.

#ifndef MULTILINEDELEGATE_H
#define MULTILINEDELEGATE_H

#include <QItemDelegate>

class MultilineDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    using QItemDelegate::QItemDelegate;

public:
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
    void setEditorData(QWidget *editor, const QModelIndex &index) const override;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
};

#endif
#include "multilinedelegate.h"
#include <QPlainTextEdit>

QWidget *MultilineDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_UNUSED(option);
    Q_UNUSED(index);
    return new QPlainTextEdit(parent);
}

void MultilineDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    if (auto *textEdit = qobject_cast<QPlainTextEdit *>(editor)) {
        textEdit->setPlainText(index.data(Qt::EditRole).toString());
    } else {
        QItemDelegate::setEditorData(editor, index);
    }
}

void MultilineDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    if (auto *textEdit = qobject_cast<QPlainTextEdit *>(editor)) {
        model->setData(index, textEdit->toPlainText());
    } else {
        QItemDelegate::setModelData(editor, model, index);
    }
}

And now all that remains to be done is using that delegate on the appropriate columns. For instance tableView->setItemDelegateForColumn(MyModel::AddressColumn, new MultilineDelegate(this));

This also looks better if the rows grow vertically as needed: tableView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);

Tested with Qt 5.15, hopefully it should work with Qt 6 as well.

Not entirely sure what you are asking but I'll assume you already have your cell set up with a widget that can accept multi-line input (ie QTextEdit using setItem on your QTableView ).

If you have that, I believe you would want to create a custom QItemDelegate derived class and override the default Enter behaviour to insert a line break rather than committing the delegate's data as is the default behaviour

Seehttp://qt-project.org/doc/qt-4.8/qitemdelegate.html#eventFilter to get you started in the right direction.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM