使用 QT 创建器中的计时器更改速度

Change speed using timer in QT creator

本文关键字:计时器 速度 QT 创建 使用      更新时间:2023-10-16

我正在尝试在线条轨迹中将背景图像顶部的矩形框移动。我在QT创建器中使用Qtimer。我正在使用openCV与图像进行交互。为了移动它,我正在按时间间隔调用generate_video()函数。

1.) 我想更改矩形的移动速度。为此,我在QT中使用了一个名为horizontalSlider_speed的水平滑块。基本上,我正在降低我打电话的间隔 generate_video() .当我增加滑块时,我能够提高速度,但即使我将滑块移动到最低,我也可以从更高的速度降低速度。

2.)我也在用VideoWriter录制它。但即使我将 FPS 设置为 120,它也会跳过帧。

#include <QTimer>
MainWindow *MainWindowPtr;
using namespace cv;
int heightImg,widthImg,intensity,initialX,initialY,xSin;
int velocity=1;
Mat imageBack,imageObject,frame;
extern void generate_video();
QTimer *timer;
VideoWriter outputVideo;
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
 ui->setupUi(this);
    imageBack= imread(filenameImg);
    outputVideo.open("outcpp.avi",CV_FOURCC('M','J','P','G'),24, 
    Size(imageBack.cols,imageBack.rows));
}
void MainWindow::on_pushButton_Generate_clicked()
{
    QTimer *timer = new QTimer;
    // make the connection using the timer variable
    connect(timer, &QTimer::timeout, this, &generate_video);
    // start the timer object by first dereferencing that object first
    timer->setInterval(100-MainWindowPtr->ui->horizontalSlider_speed->value());
    timer->start();
}
void generate_video()
{
    heightImg = MainWindowPtr->ui->lineEdit_Height->text().toInt();
    widthImg = MainWindowPtr->ui->lineEdit_Width->text().toInt();
imageBack= imread(filenameImg);
    cvtColor(imageBack, imageBack, cv::COLOR_RGB2GRAY);
    //draw rectangular object
    rectangle(imageBack,Point(initialX,initialY),Point(initialX+widthImg,initialY+heightImg),Scalar(intensity),-1,8,0);
    imshow("image",imageBack);
    //line trajectory
    if(initialX>640)
    initialX=0;
    else
    initialX+=2;
    //start recording
    if(recordFlag==1)
    {
        cv::cvtColor(imageBack, frame, cv::COLOR_GRAY2BGR);
        outputVideo.write(frame);
    }
}
void MainWindow::on_pushButton_Record_clicked()
{
 recordFlag=1; //start recording
}

太好了,你自己发现了这个错误! :-)

每次单击"生成"时,您都在创建一个新QTimer。所有这些计时器都在不断发射,因为没有一个被停止。

解决方案确实是使用单个计时器,但您可以比答案更进一步:

你只需要连接它一次(在你的MainWindow构造函数中)。

然后,在 on_pushButton_Generate_clicked 中,只需将间隔设置为当前所需的值并启动计时器。

如果您使用 new QTimer(this) 创建计时器,它将成为您MainWindowQObject子级,并在销毁MainWindow时自动删除。这可以防止计时器尝试调用超时槽时可能generate_video()时崩溃,尽管您的MainWindow已被删除。

此外,如果您只想播放一次动画,则可以在initialX达到 640 时停止计时器。

我通过使用Qtimer disconnect找到了解决方案。此外,我们不需要每次按下按钮时都声明它。所以QTimer *timer = new QTimer ;应该作为计时器 = 新的 QTimer 移动到MainWindow::MainWindow(),因为我们已经将其声明为全局。所以新代码应该是这样的。

void MainWindow::on_pushButton_Generate_clicked()
{
    timer->disconnect();
    // make the connection using the timer variable
    connect(timer, &QTimer::timeout, this, &generate_video);
    // start the timer object by first dereferencing that object first
    timer->setInterval(100-MainWindowPtr->ui->horizontalSlider_speed->value());
    timer->start();
}