#include "Widget.h" #include "ui_Widget.h" #include #include #include #include #include #include /// \~chinese 用于限制显示帧率的时间戳 \~english Time stamp to limit the rate of display QMap gLastDisplay; Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); ui->tableWidget_cameras->setSelectionBehavior(QAbstractItemView::SelectRows); mCtrlThread = DeviceControlThread::instance(); connect(mCtrlThread, &DeviceControlThread::signalControlFinish, this, &Widget::onControlFinish); connect(mCtrlThread, &DeviceControlThread::signalSelectGrabConfig, this, &Widget::onSelectGrabConfig, Qt::BlockingQueuedConnection); /// \~chinese 连接采图回调到主线程,需要等待显示完成后再释放缓冲区数据。主线程的耗时操作影响界面刷新时,会对采集速度造成影响 connect(mCtrlThread, &DeviceControlThread::signalImageGrabbed, this, &Widget::onImageGrabbed, Qt::BlockingQueuedConnection); ui->tableWidget_cameras->setColumnCount(3); ui->tableWidget_cameras->setHorizontalHeaderLabels({"Name", "Open Status", "Grab Status"}); ui->tableWidget_cameras->setEditTriggers(QTableWidget::NoEditTriggers); } Widget::~Widget() { delete ui; } /// \~chinese 扫描相机按钮的槽函数 \~english Slot function of probe push button void Widget::on_pushButton_probe_clicked() { mCtrlThread->StartProbe(); } /// \~chinese 打开相机按钮的槽函数 \~english Slot function of open camera push button void Widget::on_pushButton_openCamera_clicked() { QList select_index; for (int i = 0; i < ui->tableWidget_cameras->rowCount(); ++i) { if (ui->tableWidget_cameras->item(i,0)->checkState() != Qt::Checked) continue; select_index << i; mCtrlThread->StartOpen(i); } if (select_index.isEmpty()) { QMessageBox::critical(this, "Critical", "Please select the camera to operate"); return; } } /// \~chinese 开始采集按钮的槽函数 \~english Slot function of start acquisitio push button void Widget::on_pushButton_startGrab_clicked() { QList select_index; for (int i = 0; i < ui->tableWidget_cameras->rowCount(); ++i) { if (ui->tableWidget_cameras->item(i, 0)->checkState() != Qt::Checked) continue; select_index << i; mCtrlThread->StartGrab(i); } if (select_index.isEmpty()) { QMessageBox::critical(this, "Critical", "Please select the camera to operate"); return; } } /// \~chinese 关闭相机按钮的槽函数 \~english Slot function of close camera push button void Widget::on_pushButton_closeCamera_clicked() { QList select_index; for (int i = 0; i < ui->tableWidget_cameras->rowCount(); ++i) { if (ui->tableWidget_cameras->item(i, 0)->checkState() != Qt::Checked) continue; select_index << i; mCtrlThread->StartClose(i); } if (select_index.isEmpty()) { QMessageBox::critical(this, "Critical", "Please select the camera to operate"); return; } } /// \~chinese 停止采集按钮的槽函数 \~english Slot function of stop acquisitio push button void Widget::on_pushButton_stopGrab_clicked() { QList select_index; for (int i = 0; i < ui->tableWidget_cameras->rowCount(); ++i) { if (ui->tableWidget_cameras->item(i, 0)->checkState() != Qt::Checked) continue; select_index << i; mCtrlThread->StartStopGrab(i); } if (select_index.isEmpty()) { QMessageBox::critical(this, "Critical", "Please select the camera to operate"); return; } } void Widget::onControlFinish(int nIndex, ITK_DEVICE_CONTROL_TYPE nType, bool bSuccess) { QString devName; if (nType != ITK_DEVICE_CONTROL_PROBE) devName = ui->tableWidget_cameras->item(nIndex, 0)->text(); switch (nType) { case ITK_DEVICE_CONTROL_PROBE: { if (!bSuccess) { QMessageBox::critical(this, "Critical", "Probe failed!"); return; } QStringList camList = mCtrlThread->GetDeviceList(); ui->tableWidget_cameras->clearContents(); ui->tableWidget_cameras->setRowCount(camList.size()); for (int i = 0; i < camList.size(); ++i) { ui->tableWidget_cameras->setItem(i, 0, new QTableWidgetItem(camList[i])); ui->tableWidget_cameras->setItem(i, 1, new QTableWidgetItem("0")); ui->tableWidget_cameras->setItem(i, 2, new QTableWidgetItem("0")); ui->tableWidget_cameras->item(i, 0)->setCheckState(Qt::Checked); } } break; case ITK_DEVICE_CONTROL_OPEN: { if (!bSuccess) { QMessageBox::critical(this, "Critical", tr("Failed to open camera: %1!").arg(devName)); return; } ui->pushButton_probe->setEnabled(!mCtrlThread->IsCamOpened()); ui->tableWidget_cameras->item(nIndex, 1)->setText("1"); // check if exist a sub-window bool exist = false; auto list = ui->mdiArea_image->subWindowList(); for (int i = 0; i < list.size(); ++i) { if (list[i]->windowTitle() != devName) continue; exist = true; break; } if (exist) break; QLabel* label = new QLabel(ui->mdiArea_image); label->setWindowTitle(devName); label->setAttribute(Qt::WA_DeleteOnClose); label->setMinimumSize(240, 160); ui->mdiArea_image->addSubWindow(label, Qt::WindowMinMaxButtonsHint); // disable close manually label->show(); } break; case ITK_DEVICE_CONTROL_CLOSE: { if (!bSuccess) { QMessageBox::critical(this, "Critical", tr("Failed to close camera: %1!").arg(devName)); return; } ui->pushButton_probe->setEnabled(!mCtrlThread->IsCamOpened()); ui->tableWidget_cameras->item(nIndex, 1)->setText("0"); ui->tableWidget_cameras->item(nIndex, 2)->setText("0"); auto list = ui->mdiArea_image->subWindowList(); for (int i = 0; i < list.size(); ++i) { if (list[i]->windowTitle() != devName) continue; list[i]->close(); break; } } break; case ITK_DEVICE_CONTROL_GRAB: if (!bSuccess) { QMessageBox::critical(this, "Critical", tr("Failed to start grab: %1!").arg(devName)); return; } ui->tableWidget_cameras->item(nIndex, 2)->setText("1"); break; case ITK_DEVICE_CONTROL_STOP: if (!bSuccess) { QMessageBox::critical(this, "Critical", tr("Failed to stop grab: %1!").arg(devName)); return; } ui->tableWidget_cameras->item(nIndex, 2)->setText("0"); break; } } QString Widget::onSelectGrabConfig(const QString &devName) { QString fileName = QFileDialog::getOpenFileName(this, tr("Select Vlcf for %1").arg(devName), "", "*.vlcf"); if (fileName.isEmpty()) { QMessageBox::information(this, "Info", tr("No config file selected, %1 will grab with default paramter").arg(devName)); } return fileName; } void Widget::onImageGrabbed(const QString& devName, const QImage &img) { QDateTime now = QDateTime::currentDateTime(); /// \~chinese 控制刷新帧率小于5 \~english Limit the rate of diaply less than 5 if (gLastDisplay[devName].isValid() && gLastDisplay[devName].msecsTo(now) < 200) return; gLastDisplay[devName] = now; QLabel* label = nullptr; auto list = ui->mdiArea_image->subWindowList(); for (int i = 0; i < list.size(); ++i) { if (list[i]->windowTitle() != devName) continue; label = qobject_cast(list[i]->widget()); } if (label == nullptr) return; label->setPixmap(QPixmap::fromImage(img).scaled(label->size())); }