QTableWidgetItem doesn't have multiline edit mode?
-
Doesn't QTableWidgetItem have a multiline edit mode?
It's hard to believe that someone forgot to put that feature in.
When I double-click my QTableWidgetItem which contains multiline word-wrapped text, it becomes a line centered line during editing. It's very ugly.
Even if the QTableWidgetItem is 400 pixels high, the editable text will be only 1 line located in the center. Just terrible!
How can I do multiline editing with QTableWidgetItem? -
Hi,
Create a custom QStyledItemDelegate and provide a QTextEdit as editor in place of QLineEdit.
-
This post is deleted!
-
@SGaist OK that basically works. However the user can't tap Return to exit the multiline editing mode. What could I do to enable that? I prefer to have multiple lines that wrap, and maybe a Shift-Return for a line break, but the Return key still has to exit editing mode.
-
@Publicnamer
Then subclass and override e.g. QTextEdit::keyPressEvent(QKeyEvent *e). Or write an eventFiilter(). -
@JonB said in QTableWidgetItem doesn't have multiline edit mode?:
@Publicnamer
Then subclass and override e.g. QTextEdit::keyPressEvent(QKeyEvent *e). Or write an eventFiilter().I tried the first option, but it appears subclassing QPlainTextEdit isn't a matter of just subclassing. It wants me to implement some things like createEditor etc.
As for adding an event filter, isn't there a simple way to inject a closure into the text editor to intercept events? Why is subclassing always the solution? Seems like the wrong way.
-
@SGaist Who's using Python? In many modern compiled languages like Objective-C and Swift, you can do some useful amount of injection of closures.
Anyway, it seemed to me that the eventFilter required subclassing as well. Not so?
-
@Publicnamer said in QTableWidgetItem doesn't have multiline edit mode?:
I tried the first option, but it appears subclassing QPlainTextEdit isn't a matter of just subclassing. It wants me to implement some things like createEditor etc.
You do not have to supply
createEditor()
etc. You should be able to subclass and only override whatever you need to. However, you are going down theeventFilter()
route anyway.Anyway, it seemed to me that the eventFilter required subclassing as well. Not so?
No. Or at least it is only the container/parent which needs to subclassed, not the
QTextEdit
. ItseventFilter()
is effectively monitoring events sent to its children. -
@JonB Ah well the container is a table widget item, so that's no improvement. I'd still have to subclass. Or does the way that events are processed let me implement the filter in the container of the container of the container? That would be my window class.
-
@Publicnamer said in QTableWidgetItem doesn't have multiline edit mode?:
Ah well the container is a table widget item, so that's no improvement.
I don't think
QTableWidgetItem
counts for this anyway, since it's not aQWidget
/QObject
. And I think even if it were the top-level widget likeQMainWindow
or whatever still sees events before children do.One way or another, try it on your "window class" and see for yourself before proceeding.
-
This post is deleted!
-
@JonB
I find that the event filter is being called but there is something strange:
I am receiving QEvent::KeyRelease but not QEvent::KeyPress.
The example code says to use the latter.
Also, even though I'm intercepting Return (returning true from the filter), the key is still being received by the text editor. -
@Publicnamer
In the end I overrode the keypress/keyrelease methods and now it works. The eventFilter was not a good solution. -
@Publicnamer said in QTableWidgetItem doesn't have multiline edit mode?:
Why is subclassing always the solution?
In C++ it always is ;)
The eventFilter was not a good solution.
That should be THE solution, it's also explained in the docs
Super easy:
bool eventFilter(QObject *object, QEvent *event) override{ QWidget *editor = qobject_cast<QWidget*>(object); if (!editor) return false; if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); if (keyEvent->matches(QKeySequence::Cancel)) { // don't commit data emit closeEditor(editor, QAbstractItemDelegate::RevertModelCache); return true; } switch (keyEvent->key()) { case Qt::Key_Tab: emit commitData(editor); emit closeEditor(editor, QAbstractItemDelegate::EditNextItem); return true; case Qt::Key_Backtab: emit commitData(editor); emit closeEditor(editor, QAbstractItemDelegate::EditPreviousItem); return true; case Qt::Key_Enter: case Qt::Key_Return: QMetaObject::invokeMethod(this, [editor,this](){commitData(editor); closeEditor(editor, QAbstractItemDelegate::SubmitModelCache);},Qt::QueuedConnection); return false; default: return false; } } return QStyledItemDelegate::eventFilter(QObject *editor, QEvent *event) }
Note: most of this code is copy-pasted from QAbstractItemDelegatePrivate::editorEventFilter
-
@VRonin said in QTableWidgetItem doesn't have multiline edit mode?:
That should be THE solution
if (event->type() == QEvent::KeyPress) {
I agree with you. The trouble is the OP wrote earlier
I am receiving QEvent::KeyRelease but not QEvent::KeyPress.
but I didn't pursue it with him....