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. Qt 5.2 calling QTableWidget::update does not result in QTableWidget::paintEvent
Forum Updated to NodeBB v4.3 + New Features

Qt 5.2 calling QTableWidget::update does not result in QTableWidget::paintEvent

Scheduled Pinned Locked Moved General and Desktop
10 Posts 2 Posters 4.7k Views 1 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.
  • Y Offline
    Y Offline
    Yuri Yaryshev
    wrote on last edited by
    #1

    This Topic is simmilar to
    https://qt-project.org/forums/viewthread/21263
    and
    https://qt-project.org/forums/viewthread/28124,
    but there is no suitable answer: update and repaint isn't working.


    I have a problem: calling QTableWidget::update does not result in QTableWidget::paintEvent.

    Brief description:

    • QTableWidgetEx - a class derived from QTableWidget, with paintEvent overriden
    • Some code creating QTableWidgetEx and two menu items 'call_update' and 'check_paint_cnt'

    Testing sequence

    1. Click 'check_paint_cnt' - status bar shows "paint_cnt = 1" (so paintEvent is called)
    2. Click 'call_update'
    3. Click 'check_paint_cnt' again - status bar shows "paint_cnt = 1", but should be 2... (no call to paintEvent happen)
      Resizing the window do increase paint_cnt counter.

    (Small test app - below, full sources.
    Another test project as an empty Qt project, created by wizard (Qt 5.2): http://s000.tinyupload.com/index.php?file_id=57865294773039719910 - full source code.)

    I also tested, and have the same result (not working):

    • update(rect)
    • repaint, repaint(rect)
    • updateGeometry()
    • w->resize(w->width(), w->height());

    Workaround I found is:
    @inline void wa_widget_update(QWidget* w)
    {
    if(auto a = dynamic_cast<QAbstractScrollArea*>(w))
    a->viewport()->update();
    else
    w->update();
    };
    // Use wa_widget_update(widget) every time you'd use widget->update();
    @
    a bit ugly but works fine.

    Related bugtracker issue: https://bugreports.qt-project.org/browse/QTBUG-38286

    Question: Documentation says QTableWidget::update should trigger QTableWidget::paintEvent, but it doesn't. What am I doing wrong?
    Is there a correct way to toggle paintEvent?

    @ #--------------------------------------------------
    # Qt_Update_Test.pro contents
    #--------------------------------------------------
    QT += core gui
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    TARGET = Qt_Update_Test
    TEMPLATE = app
    SOURCES += main.cpp
    HEADERS += main.h

    //--------------------------------------------------
    // main.h contents
    //--------------------------------------------------
    
    #ifndef MAIN_H
    #define MAIN_H
    
    #include <QApplication>
    #include <QMainWindow>
    #include <QTableWidget>
    #include <QPaintEvent>
    #include <QStatusBar>
    #include <QMenuBar>
    
    extern int paints_cnt;    // Global variable - paintEvent calls counter
    
    class QTableWidgetEx : public QTableWidget
        {
        Q_OBJECT
        public:
            inline explicit QTableWidgetEx(QWidget *parent = 0) : QTableWidget(parent) {};
        protected:
            virtual void paintEvent(QPaintEvent* e) override;
        };
    
    
    class MainWindow : public QMainWindow
        {
        Q_OBJECT
        public:
            QTableWidgetEx*        table_widget_ex;
            QMenuBar*              menuBar;
            QStatusBar*            statusBar;
    
            explicit MainWindow(QWidget *parent = 0);
            inline ~MainWindow(){};
        protected slots:
            void on_call_update();
            void on_check_paint_cnt();
        };
    
    #endif
    
    //--------------------------------------------------
    // main.cpp contents
    //--------------------------------------------------
    
    #include "main.h"
    int paints_cnt = 0;    // Global variable - paintEvent calls counter
    
    void QTableWidgetEx::paintEvent(QPaintEvent* e)
        {
        ++paints_cnt;
        QTableWidget::paintEvent(e);
        }
    
    void MainWindow::on_call_update()
        {
        table_widget_ex->update();
        };
    
    void MainWindow::on_check_paint_cnt()
        {
        statusBar->showMessage("paints_cnt = " + QString::number(paints_cnt));
        };
    

    // Below - Layout code, signal-slots, entry point, etc...
    MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
    {
    resize(400, 300);

        menuBar = new QMenuBar(this);
        setMenuBar(menuBar);
    
        table_widget_ex = new QTableWidgetEx(this);
        table_widget_ex->setUpdatesEnabled(true);
        setCentralWidget(table_widget_ex);
    
        statusBar = new QStatusBar(this);
        setStatusBar(statusBar);
    
        auto call_update = new QAction("call_update", this);
        connect(call_update, SIGNAL(triggered()), this, SLOT(on_call_update()));
        menuBar->addAction(call_update);
    
        auto check_paint_cnt = new QAction("check_paint_cnt", this);
        connect(check_paint_cnt, SIGNAL(triggered()), this, SLOT(on_check_paint_cnt()));
        menuBar->addAction(check_paint_cnt);
        };
    
    int main(int argc, char *argv[])
        {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();    
        return a.exec(&#41;;
        };
    @
    
    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      AFAIK, if there was no changes (window move/notification from model etc…), Qt tries to avoid unneeded painting especially with update they are "compressed" to minimize the load

      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
      • Y Offline
        Y Offline
        Yuri Yaryshev
        wrote on last edited by
        #3

        What is "a change"?
        I'd like to notify Qt that "I have a change here, please update my widget" - how do I do that?

        Also there is not a word about it in docs. Docs says "call update" it will notify about a change.
        Of cource I can resize a widget, or even recreate it to make "a change" for sure, but this causes other widgets to repaint due to layout changes. What I want is simply notify that some data under my widget is changed and it needs to be repainted. Also I'm not using Qt's model for some reason.

        So I'm asking what is "a change" not for fun, but to know how can I emit this "change".

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

          So you have a custom data structure that you use to feed the content of the QTableWidget ?

          Then add a signal to your "model" that will notify the change when it occurs and a slot in your MainWindow where you will update the content of the corresponding item. The the update of the QTableWidget will then be done for you.

          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
          • Y Offline
            Y Offline
            Yuri Yaryshev
            wrote on last edited by
            #5

            The real case is a bit more complicated:
            I have dynamicaly changing data
            and 10 tables on 10 tabs,
            user can see only 1 table at a time.

            When data changes I don't want to instantly compute new representation for all 10 tables, instead I want to update only one visible, and mark other 9 as stale (marking stale using QWidget::update).

            Later, when the user goes to the other tab - the table will be updated (paintEvent should be called).

            Also I don't want the widget to be repainted if the user uses another app (so the widget is overlayed by it and no painting is requred).

            Also I'd like to make no updates if the data isn't changed.
            Please also note that some computation is requred to show this table, not just painting.
            For now I trigger this computation in paintEvent and cache it till next data change, so painting itself is fast.
            When the data is changed I use my workaround above to mark widget as stale, so if it is visible, then paintEvent is called and computation is done, if it's overlayed (by other tab or other app) recomputing is suspended till it's painted next time.

            Due to this complexity I've decided to make this simple test app to show my problem on a simple case.

            1 Reply Last reply
            0
            • Y Offline
              Y Offline
              Yuri Yaryshev
              wrote on last edited by
              #6

              For now I have a problem with this topic, it is shown that this topic has 4 replies, but among this replies there is no solution.

              So when the other members will try to find unanswered topics, they'll see this one is answered, but it's really not.

              What should I do now? Make a new topic?

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

                It's correct, I've answered twice an you also so it was four. Now it should be 6. The number of replies has nothing to do with the solved/unsolved state. So no, please don't open a new thread with the same question.

                To make it short: you don't need to worry about repainting. Just update the value of the item you need to. Qt will handle the rest for your.

                What you must change however is the computation part. It should not be done in the paintEvent. paintEvent is for all things painting not for data grinding. If you need some computation, do it in the slot I suggested to use earlier and then set the result value on the item.

                Unless you have some heavy computation (or a high data rate transmission between your model and the QTableWidget) you should be fine. Otherwise other techniques can be used.

                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
                • Y Offline
                  Y Offline
                  Yuri Yaryshev
                  wrote on last edited by
                  #8

                  I use paintEvent to check out if I need to do this computation: if the widget is not visible (overlayed by other) - I don't need to do computation.

                  The approach is:

                  • User opens the table
                  • Than he goes to MS Word for example
                  • My app refreshes the data, and it is changed
                  • My app calls update() on table
                  • There can be 100 more data changes while user is still in MS Word, I don't want any computation at this time
                  • User goes back to my app and looks on the table
                  • paintEvent is called and computation is triggered and cached
                  • User resizes the window paintEvent is call, but no data changes, so use cached computation

                  As you can see my main goal why I use paintEvent is to find out when I need to do some computation.

                  when = (widget is not overlayed && data is changed);

                  The best place for it is paintEvent.


                  Anyway for now I've found a suitable workaround, and I found put why that happens:
                  that's because QTableWidget is derived from QAbstractScrollView.
                  There is some kind of bug or it's a feature, anyway to emit paint event I should call w->viewport()->update() instead of just w->update(). This works great, so I added this workaround to my post above.

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

                    It's still not a good idea to have computations done in paintEvent.

                    Why not just check the widget visibility with isVisible when you are getting new data ?

                    You can also act on the showEvent and trigger the computation.

                    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
                    • Y Offline
                      Y Offline
                      Yuri Yaryshev
                      wrote on last edited by
                      #10

                      Will "showEvent " or "isVisible" show anything if a widget is overlayed by another window, but not hidden explicitly by hide()? - No!
                      As the docs say: "A widget that happens to be obscured by other windows on the screen is considered to be visible. "

                      In paintEvent i have something like:
                      if(m_is_changed) compute();

                      "It’s still not a good idea to have computations done in paintEvent." - I'd like not to diskuss this, because this will take lots of time (too much details) and also my english isn't good enough to describe all of them well and quick.
                      In my task it's ok.

                      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