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

时间:2019-01-14 06:25:36

标签: c++ qt opencv timer

我正在尝试在直线轨迹中的背景图像上方移动一个矩形框。我在QT Creator中使用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
}

2 个答案:

答案 0 :(得分:1)

太好了,您是自己发现错误的! :-)

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

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

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

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

如果您使用new QTimer(this)创建计时器,则该计时器将成为QObject的{​​{1}}子级,并在MainWindow被销毁后自动删除。这样可以防止在定时器尝试调用超时槽MainWindow时发生崩溃,尽管您的generate_video()已被删除。

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

答案 1 :(得分:0)

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

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