在调用exec之前,更新Qt映像不起作用

Updating Qt Images does not work until exec is called

本文关键字:Qt 映像 不起作用 更新 调用 exec 之前      更新时间:2023-10-16

我需要创建一个显示图像的简单GUI,本例中的图像可能会更改,GUI需要更新其内容。

我在小部件类中编写了以下更新函数:

void myClass::updatePic() {
  QPixmap pix("./pic.png");
  int width = ui->picLabel->width();
  int height = ui->picLabel->height();
  ui->picLabel->setPixmap(pix.scaled(width,height,Qt::KeepAspectRatio));}

我尝试以以下方式使用它:

int main(int argc, char *argv[]) {
QApplication a(argc, argv);
myClass w;
w.show();
sleep(3);
w.updatePic();
sleep(3);
w.updatePic();
sleep(3);
return a.exec();}

但是窗口只是打开,直到我们到达a.exec()行时才显示图像,然后它打开最后一个图像。我做错了什么?


编辑:

澄清一下,更改图像的触发器来自外部程序(具体来说,gui将是ros中的一个节点,并将由另一个节点触发)。有没有一种方法可以通过外部程序而不是从gui中按下按钮?计时器会工作,但我不喜欢这种"忙碌等待"式的解决方案。

感谢迄今为止的建议

exec运行QT事件循环,其中包括渲染小部件。

因此,将您的updatePic调用移动到您的小部件中,并通过例如按钮或显示事件来激活它

首先了解有关事件循环的更多信息。特别是,您必须知道,像paintEventresizeEvent这样的所有事件通常都是在相应的事件句柄上调用的。事件句柄通常由事件循环调用,即在exec函数内部。

让我们把@MohaBou和@RvdK的答案结合起来。您需要在exec调用之后处理计时器快照。使用QObject::timerEvent

myClass::myClass()
{
    <...>
    // This two variables are members of myClass.
    _timerId = startTimer(3000);
    _updatesCount = 0;
}
myClass::~myClass()
{
    <...>
    // For any case. As far as I remember, otherwise the late event
    // may be handled after the destructor. Maybe it is false, do
    // not remember...
    if (_timerId >= 0) {
        killTimer(_timerId);
        _timerId = - 1;
    }
}
myClass::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == _timerId) {
        if (_updatesCount < 2) {
            updatePic();
            ++_updatesCount;
        } else {
            killTimer(_timerId);
            _timerId = - 1;
        }
    }
}

这里的startTimer方法每3秒向事件查询中添加一个特殊的计时器事件。与所有事件一样,只有当事件循环将获得控制并且所有早期事件都得到处理时,才可以对其进行处理。正因为如此,如果处理了许多"重"事件,您可以有一个持续时间。

编辑:对不起,我一开始读不懂@MohaBou。他用明确的QTimer回答也足够好(但我仍然不理解关于情态的部分)。

函数exec还呈现子窗口小部件。exec()会阻塞应用程序流,而show()不会。因此,exec主要用于模态对话框。

我建议使用刷新计时器在您的自定义witget中更新它。使用QTimer每3秒更新一次图像:

QTimer* timer = new QTimer(this);
timer->setInterval(3000);
connect(timer, SINGAL(timeout()), this, SLOT(updatPicture()));

在您的自定义插槽中更新您的图片:

MainWindow::updatePicture() {
    updatePic()
}

如果你愿意,你可以使用lambda函数:

connect(timer, &QTimer::timeout, this,  [&w]() {
    updatePic()
});