Qt 5.2调用QTableWidget::update不会导致QTableWidget:paintEvent

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

本文关键字:QTableWidget paintEvent update 调用 Qt      更新时间:2023-10-16

我有一个问题:调用QTableWidget::update不会导致QTableWidget:paintEvent。

简要说明:-QTableWidgetEx-从QTableWidget派生的类,覆盖paintEvent。-一些代码创建QTableWidgetEx和两个菜单项"call_update"answers"check_paint_cnt"

测试顺序

  • 单击"check_paint_cnt"-状态栏显示"paint_cnt=1"(因此paintEvent被调用
  • 单击"call_update"
  • 再次单击"check_paint_cnt"-状态栏显示"paint_cnt=1",但是应该是2…(没有调用paintEvent)
  • 调整窗口的大小确实会增加paint_cnt,因此该函数会被成功覆盖,有时会被调用,但不会被更新或重新绘制

(下面是小型测试应用程序。测试项目是一个空的Qt项目,由向导创建(Qt 5.2):http://s000.tinyupload.com/index.php?file_id=57865294773039719910-完整的源代码。)

我测试了"重新绘制"而不是"更新"——它给出了相同的结果。

问题:文档说QTableWidget::update应该触发QTableWidget::paintEvent,但它没有我做错了什么?

我也测试过,结果相同(不起作用):

  • 更新(rect)
  • 重新绘制,重新绘制(rect)
  • updateGeometry()
  • w->调整大小(w->宽度(),w->高度())

好的解决方法是:

inline void wa_widget_update(QWidget* w)
    {
    if(auto a = dynamic_cast<QAbstractScrollArea*>(w))
            a->viewport()->update();
    else
            w->update();
    };

使用wa_widget_update(w)代替w->update()。有点丑,但很管用。向qt项目报告了此错误:错误跟踪器的链接

完整来源:

#--------------------------------------------------
# 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();
    };   

QTableWidget源自QAbstractScrollArea,并使用视口小部件。如果调用viewport小部件的update()方法,paintEvent将被触发:

void MainWindow::on_call_update()
{
    table_widget_ex->viewport()->update();
}

更多信息,请访问:update()或repaint()无法触发paintEvent()