【问题标题】:Qt 5.2 calling QTableWidget::update does not result in QTableWidget::paintEventQt 5.2 调用 QTableWidget::update 不会导致 QTableWidget::paintEvent
【发布时间】:2014-04-10 18:30:28
【问题描述】:

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

简要说明: - QTableWidgetEx - 一个从 QTableWidget 派生的类,重写了 paintEvent。 - 一些代码创建 QTableWidgetEx 和两个菜单项 'call_update' 和 '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 - 完整源代码。)

我测试了 'repaint' 而不是 'update' - 结果相同。

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

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

  • 更新(矩形)
  • 重绘,重绘(矩形)
  • updateGeometry()
  • w->resize(w->width(), w->height());

好的解决方法是:

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 项目: Link to bugtracker

完整来源:

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

【问题讨论】:

  • QWidget::setUpdatesEnabled() 默认为真,不是吗?
  • 确保您已在小部件上调用了 show(),并且您在 QApplication::exec() 事件循环中。如果你点击 check_paint_cnt() 动作,你可能就是所有这些东西。
  • 此处或其他地方可能存在复制粘贴错误。确保在 C++11 编译器下编译它,在 .pro 文件中添加 CONFIG += c++11,并将事件处理程序声明为 void paintEvent(QPaintEvent*) override;。确保它仍然可以编译 - 如果没有,你没有覆盖你认为你是的函数:)
  • 此外,您想要做什么?为什么要覆盖这样一个非常复杂的类的绘制事件?
  • - 小部件可见 - 我可以在屏幕上看到它。

标签: c++ qt qtablewidget paintevent


【解决方案1】:

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

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

更多信息请访问:update() or repaint() fails to trigger paintEvent()

【讨论】:

  • 关于它的部分来自QAbstractScrollArea 解决了我的问题。我以这种方式实例化QPainter QPainter painter(viewport());,取自stackoverflow.com/questions/6515695/…。谢谢史蒂芬!
猜你喜欢
  • 1970-01-01
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多