Text in QTableView not visible when setting Qt::BackgroundRole
-
@Christian-Ehrlicher said in Text in QTableView not visible when setting Qt::BackgroundRole:
As I saidf in the bug report - such update rates are useless / stupid for a gui showing numbers...
In this case it isn't about the number, it's about the background color. The user will very quickly perceive when the color box moves on the screen and if that's a lot slower than the physical machine which the user can observe simultaneously then the user experience will be suffering. Humans are quite sensitive to time lag in user experience. One could go to 100ms but not 1s.
Anyway, let's say 1s is possible, then the elide delegate from the SO post still prevents the user to edit the value because it repaints the control with the existing value from the model, not the digits the user has entered this far, when a dataChanged() for background color is emitted. Can the delegate detect that user editing is in progress?
-
If user editing of a value is in progress then the display within the cell's region of the view is driven by the editor widget that is created when the cell switch to edit mode. You are going to need to post a complete program that demonstrates the new problem.
-
@ChrisW67 Here you are: https://udokaelectronics.com/files/untitled.zip
Comment out
ui->tableView->setItemDelegate(elideDelegate);
To see the result with and without the delegate.
Without the elide delegate all works fine except the elide. With the elide delegate the background overwrites the text and the existing text is continuously redrawn during editing of cell content.
-
Why are you drawing the text and then on top of it call the style's drawControl method with no text ?
What would make more sense is to change the text and elide value of the option and pass the modified option to the base class paint method.
Also, why nuke the options object you just got by calling init on it ?Note I have just read the delegate's code you provided.
[edit: options must be updated as done, see base class implementation SGaist]
-
I have tried the straightforward implementation
void ElideDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (!index.isValid()) { return; } QStyleOptionViewItem opt = option; initStyleOption(&opt, index); opt.text= opt.fontMetrics.elidedText(opt.text, Qt::ElideRight, opt.rect.width()); opt.textElideMode = Qt::ElideNone; QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter); }
opt.text is for some reason blank until
initStyleOption(&opt, index);
returns. Hence "nuking" opt byinitStyleOption(&opt, index);
is necessary.With the code above and string "1.234567890" the string gets properly elided by opt.fontMetrics.elidedText to for example "1.2345..." but the view still shows "1....". Note that this problem is only present for positive numbers. It works fine without the delegate for negative numbers.
Substituting
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
withQStyledItemDelegate::paint(painter, opt, index);
doesn't help. Perhaps related to that one needs to call initStyleOption() to get the actual text so perhaps QStyledItemDelegate::paint does the same and hence discards all changes to the text. -
I just discovered by exploratory testing that giving opt.fondMetrics.elidedText some margin seems to do the trick, i.e. replace
opt.text = opt.fontMetrics.elidedText(opt.text, Qt::ElideRight,opt.rect.width() );
withopt.text = opt.fontMetrics.elidedText(opt.text, Qt::ElideRight,opt.rect.width() - 10);
.That gives me both background color and elided text. No idea of how portable it is though.
But it doesn't solve the issue with text being overwritten when the model emits dataChanged() with role Backgroundrole when user edit is in progress. Is is possible to somehow detect when user edit is in progress? Override QAbstractItemView:edit() to detect start of user edit, but how detect when user edit is finished? Override closeEditor() and assume there is only one edit active at once?
-
You were right about the use of initStyleOption, I had it at the wrong place.
Can you explain the use case of a user editable value that can be replaced under the hood programmatically while being edited ?
It looks like it should rather be a independent way to input data to avoid collision or an "edit mode" where the other updates are disabled.
-
@SGaist said in Text in QTableView not visible when setting Qt::BackgroundRole:
Can you explain the use case of a user editable value that can be replaced under the hood programmatically while being edited ?
That is not the use case. The desired behavior is to have the background color of the cells in the table view being modified programmatically while one cell is edited. The cell being edit doesn't need to show any background color.
-
I am not sure I am following you. You are modifying the background color of index values that are changed programmatically and this interferes with the manual edition of one of the index. Is that so ?
-
@SGaist Yes, because the way to change background color is to emit dataChanged() from the model with role == BackgroundColor and with the current delegate workaround to the elide bug this causes painting of the current string (painting over the edit-in-progress string)
The best I've found this far is to let the elide delegate keep track of when an edit is in progress and then having the models avoid emitting dataChanged() while an edit is in progress. But's it not very elegant and requires all models to know about this.
-
You could implement the "ignore" part in a proxy model so your core models can happily live ignoring about the édition going on and the proxy would filter that while an edition takes place.
But still, I fail to see how or why, the color of that cell should be changed while you are editing it.