Qt 多线程:如何更新两个 QLabel? [英] Qt multithreading: How to update two QLabels?

查看:116
本文介绍了Qt 多线程:如何更新两个 QLabel?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不是多线程专家.我知道 GUI 应该由主线程管理,但是我需要主线程同时完成两件事.情况如下:

I am not a multithreading expert. I know that the GUI should be managed by the main thread, however I'd need 2 things to be done by the mainthread simultanuously. The situation is the following:

用户点击按钮(自拍),倒计时开始(3 秒).用户可以在 QLabel 中看到每秒变化的数字 3-2.同时用户可以在同一个窗口的另一个 QLabel 中看到摄像头数据.

The user clicks on a pushbutton (to take a selfie), a count down timer starts (3 seconds). The user can see in a QLabel the numbers 3-2 changing every second. Meanwhile the user can see the camera data in another QLabel of the same window.

换句话说,主线程应该做两件事:

In other words the mainthread should do 2 things:

  • 更新 QLabel1 以始终显示计时器
  • 使用来自相机的实时视频流更新 QLabel2

我在实现这一目标时遇到了一些困难.有人可以帮我吗?我不一定要求一个简单的技巧/解决方法.我想使用多线程,这样我可以提高我对这项技术的了解,而不仅仅是使用一次简单/快速的解决方法......

I am having some difficulties to achieve this. Could someone help me out? I am not necessarily asking for an easy trick/work around. I'd like to use multithreading that way I can improve my knowledge about this technique and not just use a one time easy/quick workaround...

谢谢

我当前的代码:

我尝试过的:当用户单击名为 btnTakeSnap 的按钮时,一个新线程启动,在该线程中,计时器开始倒计时并更新 labelTimeSnap(这是一个 QLabel,我在其中加载带有数字 3-0).一旦计时器达到 0,就会拍摄一张照片.

What I tried: when the user clicks the button called btnTakeSnap a new thread is started and in that thread the timer starts counting down and updating the labelTimeSnap (this is a QLabel in which I load "fancy" images with numbers 3-0). Once the timer reaches 0 a picture is taken.

但我没有看到我的 QLabel 被计时器更新.只有当达到 0 时,我的 QLabel 中才会突然显示数字 0.

But I don't see my QLabel being updated with the timer. It is only when 0 is reached that suddenly the number 0 gets displayed in my QLabel.

有什么建议吗?

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    snapIndex=1;

    QString fileName = "../somePicture.jpg";
    QImage imageFrame;

    connect(ui->btnTakeSnap, SIGNAL(clicked()), this, SLOT(startTimerWorker()) );
}


void MainWindow::startTimerWorker()
{
    timerSnapThread = new QThread(this);
    MainWindow *workerTimerSnap = new MainWindow();

    connect(timerSnapThread, &QThread::started, workerTimerSnap, &MainWindow::updateTimer);
    workerTimerSnap->moveToThread(timerSnapThread);
    timerSnapThread->start();

}

void MainWindow::updateTimer()
{
    int selectedTimer;

    if(ui->rdBtntimer1s->isChecked())
    {selectedTimer = 1000;}
    if(ui->rdBtntimer3s->isChecked())
    {selectedTimer = 3000;}

    QString filename;
    QImage image;

    //timer
      if(selectedTimer == 3000) //3 seconds
      {
         QElapsedTimer t;
         t.start();
         while (t.elapsed() < selectedTimer)
         {
             if(t.elapsed()==0)
             {
                filename = "../../testImages/timer3.png";qDebug()<<"3";
                image.load(filename);
                image= image.scaled(ui->labelTimeSnap->width(), ui->labelTimeSnap->height(),Qt::KeepAspectRatio);
                ui->labelTimeSnap->setPixmap(QPixmap::fromImage(image));
              }

             if(t.elapsed()==1000)
             {
                filename = "../../testImages/timer2.png";qDebug()<<"2";
                image.load(filename);
                image= image.scaled(ui->labelTimeSnap->width(), ui->labelTimeSnap->height(),Qt::KeepAspectRatio);
                ui->labelTimeSnap->setPixmap(QPixmap::fromImage(image));
             }

            if(t.elapsed()==2000)
            {
                filename = "../../testImages/timer1.png";qDebug()<<"1";
                image.load(filename);
                image= image.scaled(ui->labelTimeSnap->width(), ui->labelTimeSnap->height(),Qt::KeepAspectRatio);
                ui->labelTimeSnap->setPixmap(QPixmap::fromImage(image));
            }

         }
            takeSnap();
       }

       if(selectedTimer == 1000)
       {
           QElapsedTimer t;
           t.start();
           while (t.elapsed() < selectedTimer)
           {
                if(t.elapsed()==0)
                {
                    filename = "../../testImages/timer1.png";
                    qDebug()<<"1";
                    image.load(filename);
                    image= image.scaled(ui->labelTimeSnap->width(), ui->labelTimeSnap->height(),Qt::KeepAspectRatio);
                    ui->labelTimeSnap->setPixmap(QPixmap::fromImage(image));
                }

                if(t.elapsed()==1000)
                {
                    filename = "../../testImages/timer1.png";
                    qDebug()<<"0";
                    image.load(filename);
                    image= image.scaled(ui->labelTimeSnap->width(), ui->labelTimeSnap->height(),Qt::KeepAspectRatio);
                    ui->labelTimeSnap->setPixmap(QPixmap::fromImage(image));
                }
            }
            takeSnap();
       }
}


void MainWindow::takeSnap()
{
    static int i=0;

    cv::VideoCapture cap(CV_CAP_ANY);
    cv::Mat imgFrame;
    cap >> imgFrame;

    //BGR-> RGB
    cv::cvtColor(imgFrame, imgFrame, CV_BGR2RGB);

    //Mat -> QPixMap
    QImage img;
    img = QImage((uchar*)imgFrame.data, imgFrame.cols, imgFrame.rows, QImage::Format_RGB888);
    QPixmap pixmap = QPixmap::fromImage(img);

    int w = ui->labelSnap1->width();
    int h = ui->labelSnap1->height();
    if(i==0)
    {ui->labelSnap1->setPixmap(pixmap.scaled(w,h,Qt::KeepAspectRatio));}
    if(i==1)
    {ui->labelSnap2->setPixmap(pixmap.scaled(w,h,Qt::KeepAspectRatio));}
    if(i==2)
    {ui->labelSnap3->setPixmap(pixmap.scaled(w,h,Qt::KeepAspectRatio));}

    i++;
    if(i==3){i=0;}

    showNextSnap();

}

推荐答案

您可以使用信号将线程通信在一起.

You can use signals to communicate threads together.

像这样在你的第二个线程中定义一个信号:

define a signal in your second thread like this:

signals:
    void changeLabelOnMain(QString text);

在第二个线程中发出你的信号:

emit your signal in second thread:

emit changeLabelOnMain("some text");

将您的信号连接到您的主插槽中:

connect your signal to a slot in your main :

 SecondClassName secondObject= new SecondClassName();
 connect(secondObject, &SecondClassName::changeLabelOnMain, this, &MainClassName::YourSlotName);

这是一个让线程一起通信的简单示例.

this is a simple example of making threads communicate together.

这篇关于Qt 多线程:如何更新两个 QLabel?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆