Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Help wanted: paintEvent is only called once in a series of datachanged event

Help wanted: paintEvent is only called once in a series of datachanged event

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 4 Posters 492 Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    farley
    wrote on last edited by
    #1

    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 of dataChanged 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.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      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.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • MasterBLBM Offline
        MasterBLBM Offline
        MasterBLB
        wrote on last edited by sierdzio
        #3

        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:

        1. [MOD EDIT] redacted. OP advised not to use Chinese characters in sources, but in a very unfriendly way
        2. appendText() method is absolutely redundant and ill-placed, as adding new stuff to the model is not responsibility of view class.
        3. 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.

        F 1 Reply Last reply
        1
        • sierdzioS Offline
          sierdzioS Offline
          sierdzio
          Moderators
          wrote on last edited by
          #4

          @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.

          (Z(:^

          MasterBLBM 1 Reply Last reply
          1
          • sierdzioS sierdzio

            @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.

            MasterBLBM Offline
            MasterBLBM Offline
            MasterBLB
            wrote on last edited by
            #5

            @sierdzio Sorry, I didn't mean to be unfriendly. It is just that would these comments were in English it might help to understand initial idea of the thread author, and figure out some way to help him, or her.

            1 Reply Last reply
            1
            • MasterBLBM MasterBLB

              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:

              1. [MOD EDIT] redacted. OP advised not to use Chinese characters in sources, but in a very unfriendly way
              2. appendText() method is absolutely redundant and ill-placed, as adding new stuff to the model is not responsibility of view class.
              3. 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.

              F Offline
              F Offline
              farley
              wrote on last edited by
              #6

              @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,

              1. 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.
              2. So, I learned adding new stuff to the model is not responsibility of view class. I'll directly write this funtion in mainwindow.
              1 Reply Last reply
              0
              • F farley has marked this topic as solved on
              • F Offline
                F Offline
                farley
                wrote on last edited by
                #7

                @SGaist Thank you for your suggestion, problemed is solved althought without QTimer. : )

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved