Help wanted: paintEvent is only called once in a series of datachanged event
-
Hello, everyone:
I want to achieve a continuous text appending effect in the window, like this.
but the window's text only refreshes during the last text update operation, omitting the intermediate process. I debugged the code and found that the
paintEvent
is only called once in a series ofdataChanged
events. I would like to know how to modify my code to achieve this functionality.Here is a link to my github issue
Below is my code:
#include <QListView> #include <QStandardItemModel> #include "ichatitemdelegate.h" #include "ichatitemmodel.h" class IChatList: public QListView { public: using QListView::QListView; public: explicit IChatList(QWidget *parent = nullptr) : QListView(parent) { setModel(new IChatItemModel(this)); setItemDelegate(new IChatItemDelegate(this)); } void paintEvent(QPaintEvent *e) override{ QListView::paintEvent(e); qDebug() << "void paintEvent(QPaintEvent *e)"; } public: void appendText(QString text) { auto model = qobject_cast<QStandardItemModel*>(this->model()); if (!model) { qDebug() << "Chat list model is null."; return; } QStandardItem *lastItem = nullptr; int rowCount = model->rowCount(); if (rowCount > 0) { QModelIndex lastIndex = model->index(rowCount - 1, 0); lastItem = model->itemFromIndex(lastIndex); } if (!lastItem) { // 如果没有最后一行item,创建一个新的item并添加到模型中 lastItem = new QStandardItem(); model->appendRow(lastItem); } // 获取最后一个item的数据,并更新 message 字段 QVariant itemData = lastItem->data(Qt::DisplayRole); QVariantMap chatData1 = itemData.toMap(); // 显式转换为 QVariantMap chatData1["message"] = chatData1["message"].toString() + " " + text; lastItem->setData(chatData1, Qt::DisplayRole); qDebug() << "appendText:" << text; // 发出数据变化信号,通知视图刷新 QModelIndex topLeft = model->index(0, 0); QModelIndex bottomRight = model->index(rowCount - 1, 0); emit model->dataChanged(topLeft, bottomRight); repaint(); } public: };
Waiting for your help.
-
Hi and welcome to devnet,
One possible solution is to buffer the updates and update the content of the model on a regular interval using for example a QTimer.
-
Looks like problem xy...
What is your ultimate goal to achieve? Do you want the list view to be displayed once new line is inserted?Meanwhile, some hints:
- [MOD EDIT] redacted. OP advised not to use Chinese characters in sources, but in a very unfriendly way
- appendText() method is absolutely redundant and ill-placed, as adding new stuff to the model is not responsibility of view class.
- Relating to point 2. you don't even have to reimplement anything, as there is
void QStandardItemModel::appendRow(QStandardItem *item)
I think just by using that proper appendRow() method your sync issues will be gone, as inside there are proper calls to emit dataChanged(), update(), beginInsertRows() etc.
-
@MasterBLB while I also recommend sticking to English in all source code, using wide UTF characters has no influence on this code whatsoever. Firstly, they are used in comments only, and secondly: both Qt and all modern compilers support UTF just fine.
-
@MasterBLB Hello, thanks for your reply.
My ultimate goal is to display byte stream from netport instantly in listview.
Luckily, my problem is solved by replace signal QNetworkAccessManager::finished to QNetworkReply::readyRead in my code.Additionally,
- I also think it's preferable to use English throughout all source code for better communication with others in a friendly manner.But sometimes also tend to be lazy.
- So, I learned adding new stuff to the model is not responsibility of view class. I'll directly write this funtion in mainwindow.
-