C++ Qt多线程:如何更新两个qlabel?

C++ Qt多线程:如何更新两个qlabel?,c++,multithreading,qt,qthread,C++,Multithreading,Qt,Qthread,我不是多线程专家。 我知道GUI应该由主线程管理,但是我需要主线程同时完成两件事情。 情况如下: 用户点击按钮(进行自拍),倒计时开始(3秒)。用户可以在QLabel中看到数字3-2每秒都在变化。同时,用户可以在同一窗口的另一个QLabel中看到相机数据 换句话说,主线程应该做两件事: 更新QLabel1以始终显示计时器 使用摄像机的实时录像带更新QLabel2 要做到这一点,我有一些困难。有人能帮我吗? 我不一定要求一个简单的技巧/解决方法。我希望通过使用多线程来提高我对这项技术的了解,而

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

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

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

  • 更新QLabel1以始终显示计时器
  • 使用摄像机的实时录像带更新QLabel2
要做到这一点,我有一些困难。有人能帮我吗? 我不一定要求一个简单的技巧/解决方法。我希望通过使用多线程来提高我对这项技术的了解,而不仅仅是使用一次性简单/快速的解决方法

多谢各位

我当前的代码:

我尝试的是:当用户单击名为Btnakesnap的按钮时,一个新线程启动,在该线程中计时器开始倒计时并更新labelTimeSnap(这是一个QLabel,我在其中加载数字为3-0的“fancy”图像)。当计时器达到0时,将拍摄一张照片

但是我没有看到我的QLabel被定时器更新。只有当到达0时,数字0才会突然显示在我的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();

}
MainWindow::MainWindow(QWidget*父项):
QMainWindow(父级),
用户界面(新用户界面::主窗口)
{
用户界面->设置用户界面(此);
snapIndex=1;
QString fileName=“../somePicture.jpg”;
图像框;
连接(ui->btnTakeSnap,信号(单击()),此,插槽(startTimerWorker());
}
void主窗口::startTimerWorker()
{
timerSnapThread=新的QThread(this);
MainWindow*workerTimerSnap=新建MainWindow();
连接(timerSnapThread、&QThread::started、workerTimerSnap、&MainWindow::UpdateTime);
workerTimerSnap->moveToThread(timerSnapThread);
timerSnapThread->start();
}
void MainWindow::updateTimer()
{
int-selectedTimer;
如果(ui->rdBtntimer1s->isChecked())
{selectedTimer=1000;}
如果(ui->rdBtntimer3s->isChecked())
{selectedTimer=3000;}
QString文件名;
图像;
//计时器
如果(selectedTimer==3000)//3秒
{
qedtimer t;
t、 start();
while(t.appeased()labelTimeSnap->height(),Qt::KeepAspectRatio);
ui->labelTimeSnap->setPixmap(QPixmap::fromImage(图像));
}
如果(t.经过()==1000)
{
filename=“../testImages/timer2.png”;qDebug()宽度(),ui->labelTimeSnap->height(),Qt::KeepAspectRatio);
ui->labelTimeSnap->setPixmap(QPixmap::fromImage(图像));
}
如果(t.经过时间()==2000)
{
filename=“../testImages/timer1.png”;qDebug()宽度(),ui->labelTimeSnap->height(),Qt::KeepAspectRatio);
ui->labelTimeSnap->setPixmap(QPixmap::fromImage(图像));
}
}
takeSnap();
}
如果(已选择时间==1000)
{
qedtimer t;
t、 start();
while(t.appeased()labelTimeSnap->height(),Qt::KeepAspectRatio);
ui->labelTimeSnap->setPixmap(QPixmap::fromImage(图像));
}
如果(t.经过()==1000)
{
filename=“../testImages/timer1.png”;
qDebug()width(),ui->labelTimeSnap->height(),Qt::KeepAspectRatio);
ui->labelTimeSnap->setPixmap(QPixmap::fromImage(图像));
}
}
takeSnap();
}
}
void主窗口::takeSnap()
{
静态int i=0;
cv::视频捕获上限(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();
inth=ui->labelSnap1->height();
如果(i==0)
{ui->labelSnap1->setPixmap(pixmap.scaled(w,h,Qt::KeepAspectRatio));}
如果(i==1)
{ui->labelSnap2->setPixmap(pixmap.scaled(w,h,Qt::KeepAspectRatio));}
如果(i==2)
{ui->labelSnap3->setPixmap(pixmap.scaled(w,h,Qt::KeepAspectRatio));}
i++;
如果(i==3){i=0;}
showNextSnap();
}

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

在第二个线程中定义一个信号,如下所示:

signals:
    void changeLabelOnMain(QString text);
在第二个线程中发出信号:

emit changeLabelOnMain("some text");
将您的信号连接到主电源中的插槽:

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

这是一个使线程相互通信的简单示例。

使用信号和插槽在子线程和主线程之间通信。确保使用
connect()
,第5个参数为
Qt::QueuedConnection
,这将确保插槽在主线程中执行。永远不要直接更改子线程中的GUI元素