2017-07-22 8 views
2

私はマルチスレッドの専門家ではありません。 GUIはメインスレッドで管理する必要がありますが、私はメインスレッドが同時に実行するには2つのことが必要です。 状況は次のとおりです。Qtマルチスレッド:2つのQLabelsを更新するには?

ユーザがプッシュボタンをクリックすると(セルフタイマーを取る)、カウントダウンタイマーが開始されます(3秒)。ユーザーはQLabelで毎秒変化する数字3-2を見ることができます。一方、ユーザは同じウィンドウの別のQLabelでカメラデータを見ることができます。いつも私はいくつかの困難を持っていたカメラ

からのライブvideostramでタイマー

  • 更新QLabel2を表示する

    • 更新QLabel1:

      つまりmainthreadは、2つのことを行う必要がありますこれを達成する。誰かが私を助けてくれますか? 私は必ずしも簡単なトリック/回避策を求めているわけではありません。

      :私は

      はあなたに

      私の現在のコードをありがとう...私はこの技術についての私の知識を向上させ、一度だけ簡単/迅速な回避策を使用することはできませんそのようにマルチスレッドを使用したいです

      私が試したこと:ユーザーがbtnTakeSnapというボタンをクリックすると、新しいスレッドが開始され、そのスレッドでtimerがカウントダウンを開始し、labelTimeSnapを更新します(これはQLabelで番号3-0の "fancy"画像を読み込みます) 。タイマーが0に達すると、画像が撮影されます。

      しかし、QLabelがタイマーで更新されることはありません。突然0が私のQLabelに表示されるのは0に達したときだけです。

      アドバイスはありますか?

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

    サブスレッドとメインスレッド間の通信に信号とスロットを使用します。 5番目のパラメータが 'Qt :: QueuedConnection'で' connect() 'を使用していることを確認してください。これは、スロットがメインスレッドで実行されることを保証します。直接、サブスレッド内のGUI要素を直接変更することはありません –

    答えて

    1

    スレッドを一緒に通信するために信号を使用できます。

    このような2番目のスレッドで信号を定義:

    signals: 
        void changeLabelOnMain(QString text); 
    

    は、第二のスレッドであなたの信号を発する。

    emit changeLabelOnMain("some text"); 
    

    は、メインのスロットにあなたの信号を接続します

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

    これはスレッドを相互に通信させる簡単な例です。

    関連する問題