一个QDialog在Windows上无法退出,但在MacOS上可以。

huangapple go评论110阅读模式
英文:

A QDialog can't be exited on Windows, but not on MacOS/

问题

我在Qt5(C ++)中有一个对话框。您可以看到,该对话框只是创建了一些小部件(来自QOpenGLWidget的VisGLWidget),并不断更新它。

问题是,我可以在MacOS上点击交叉按钮退出此对话框,但在Windows上却不能。出了什么问题?

#include "visualizationdlg.h"
#include "ui_visualizationdlg.h"

VisualizationDlg::VisualizationDlg(QWidget *parent, NewtonSpace *data) :
    QDialog(parent),
    ui(new Ui::VisualizationDlg)
{
    ui->setupUi(this);
    this->setFixedSize(600, 600);

    this->data = data;
    this->visualizationGL = new VisGLWidget(this, this->data);
    this->visualizationGL->setObjectName(QString::fromUtf8("visualizationGL"));
    this->visualizationGL->setGeometry(QRect(10, 50, 581, 541));
    this->visualizationGL->repaint();

    this->rePaintTimer = startTimer(1);
}

VisualizationDlg::~VisualizationDlg()
{
    delete ui;
}

void VisualizationDlg::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == this->rePaintTimer) {
        this->data->update(ui->GInput->value(), ui->updateSpdInput->value());
        this->visualizationGL->repaint();

        this->rePaintTimer = startTimer(1);
    }
}

问题是,我可以在MacOS上通过单击关闭按钮退出此对话框,但在Windows上却不能。有什么问题?

英文:

I have a dialog in Qt5(C++). You can see that the dialog just creates some widgets (VisGLWidget from QOpenGLWidget) and keeps updating it.

#include "visualizationdlg.h"
#include "ui_visualizationdlg.h"

VisualizationDlg::VisualizationDlg(QWidget *parent, NewtonSpace *data) :
    QDialog(parent),
    ui(new Ui::VisualizationDlg)
{
    ui->setupUi(this);
    this->setFixedSize(600,600);

    this->data = data;
    this->visualizationGL = new VisGLWidget(this, this->data);
    this->visualizationGL->setObjectName(QString::fromUtf8("visualizationGL"));
    this->visualizationGL->setGeometry(QRect(10, 50, 581, 541));
    this->visualizationGL->repaint();

    this->rePaintTimer = startTimer(1);
}

VisualizationDlg::~VisualizationDlg()
{
    delete ui;
}

void VisualizationDlg::timerEvent(QTimerEvent *event)
{
    if(event->timerId() == this->rePaintTimer) {
        this->data->update(ui->GInput->value(), ui->updateSpdInput->value());
        this->visualizationGL->repaint();

        this->rePaintTimer = startTimer(1);
    }
}

The question is, I can quit this dialog by clicking the cross on MacOS, but not on Windows. What's wrong with it?

答案1

得分: 0

在你的VisualizationDlg构造函数中有如下代码:

this->rePaintTimer = startTimer(1);

这将导致一个QTimerEvent被发送到你的VisualizationDlg实例,每毫秒一次(可能)。

现在考虑处理定时器事件的代码:

void VisualizationDlg::timerEvent(QTimerEvent *event)
{
    if(event->timerId() == this->rePaintTimer) {
        this->data->update(ui->GInput->value(), ui->updateSpdInput->value());
        this->visualizationGL->repaint();

        this->rePaintTimer = startTimer(1);
    }
}

第一次调用此函数时,与定时器事件关联的id将匹配rePaintTimer。因此,repaint将被调用。但是然后你启动了一个新的定时器并将其id分配给rePaintTimer,而不停止原始定时器。现在你有两个定时器,每个都以1KHz生成事件,但你的事件处理程序只对最新创建的定时器生成的事件做出反应。

现在考虑一下这个问题在几秒钟后会变成什么样。你可能会有成千上万个定时器,每个都以1KHz生成事件。

从你的事件处理程序中移除以下代码:

this->rePaintTimer = startTimer(1);

使其变成:

void VisualizationDlg::timerEvent(QTimerEvent *event)
{
    if(event->timerId() == this->rePaintTimer) {
        this->data->update(ui->GInput->value(), ui->updateSpdInput->value());
        this->visualizationGL->repaint();
    }
}
英文:

In your VisualizationDlg constructor you have...

this->rePaintTimer = startTimer(1);

That will result in a QTimerEvent being sent to your VisualizationDlg instance once every millisecond (potentially).

Now consider the code that handles timer events...

void VisualizationDlg::timerEvent (QTimerEvent *event)
{
    if(event->timerId() == this->rePaintTimer) {
        this->data->update(ui->GInput->value(), ui->updateSpdInput->value());
        this->visualizationGL->repaint();

        this->rePaintTimer = startTimer(1);
    }
}

The first time this is invoked the id associated with the timer event will match rePaintTimer. Hence repaint will be called. But you then start a new timer and assign its id to rePaintTimer without stopping the original timer. You now have two timers each generating events at 1KHz but your event handler only ever acts on events from the most recently created timer.

Now think what this will become after even a few seconds. You could potentially have thousands of timers each generating events at 1KHz.

Remove the line...

this->rePaintTimer = startTimer(1);

from your event handler to make it...

void VisualizationDlg::timerEvent (QTimerEvent *event)
{
    if(event->timerId() == this->rePaintTimer) {
        this->data->update(ui->GInput->value(), ui->updateSpdInput->value());
        this->visualizationGL->repaint();
    }
}

huangapple
  • 本文由 发表于 2020年1月6日 19:47:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/59611577.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定