【问题标题】:Non-idle alternative to QTimer for periodically called function用于定期调用函数的 QTimer 的非空闲替代品
【发布时间】:2014-02-07 19:28:35
【问题描述】:

我在一个小部件内有一个简单的 3D 渲染框架,它带有一个负责渲染每一帧的 update() 方法。目前我正在使用QTimer 每秒触发 60 次更新,这似乎工作正常:

void RenderingWidget::init()
{
    // ...

    QTimer* timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(16);
}

此解决方案的问题在于,无论渲染多快,帧之间都可能有 16 毫秒的空闲时间。在本机 Windows 应用程序中,如果没有要处理的其他事件,我可以实现自己的消息循环并持续渲染帧。我可以在 Qt 中做类似的事情吗?

这是我想到的,似乎也可以,但是我读到这可能是一种不好的做法(即使用QApplication::processEvents()):

void RenderingWidget::run()
{
    running = true;

   while(running)
   {
        update();
        QApplication::processEvents();
    }
}

【问题讨论】:

  • 我认为 QApplication::processEvents 在你的情况下是可以的。您还可以在小部件的paintEvent 函数中实现渲染,并使用repaint() 立即调用它。您可以使用QElapsedTimer 手动限制帧速率。

标签: c++ qt event-handling


【解决方案1】:

我终于明白了!虽然在 Qt 中无法直接访问消息循环,但有一个 QObject::event() 方法,其作用类似于 Windows API 中的 WndProc()

实现问题中提到的方法是通过子类化QWidgetQApplication 重新实现此方法,然后通过调用update() 方法或在任何其他情况下处理QEvent::UpdateRequest 事件,将事件传递给默认处理程序将处理它的基类(类似于 win api 中的默认 windows 过程)。完成更新后,您将另一个更新请求添加到队列中,除非中间有其他事件,否则控件将返回到 update() 等等。

这是一个示例实现:

class RenderingWidget : public QWidget
{
    Q_OBJECT
public:
    explicit RenderingWidget(QWidget *parent = 0);
    virtual ~RenderingWidget();

public slots:   
    void update() 
    { 
        // do all rendering work
        updateLater();    // queue another update
    }

    void updateLater()
    {
        if (!m_updatePending)
        {
            m_updatePending = true;
            QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest);
        }
    }

protected:        
    bool m_updatePending;    

    bool event(QEvent* event)
    { 
        if (event == QEvent::UpdateRequest)
        {
            m_updagePending = false;
            update();
            return true;
        }
        else
        {
            return QWidget::event(event);
        }
    }
};

【讨论】:

    猜你喜欢
    • 2019-01-19
    • 1970-01-01
    • 2012-08-26
    • 1970-01-01
    • 2017-04-06
    • 2014-03-03
    • 2012-09-28
    • 2010-12-04
    • 1970-01-01
    相关资源
    最近更新 更多