在 C++ 中刷新组合框?

Refresh a Combobox in C++?

我有一个功能可以检测 3D 切片器中的相机端口,但它似乎只 运行 一次。当我在相机中 unplug/plug 时,端口数量应该在组合框中更新(在 Qt 中设计),但没有任何变化。

我使用的函数检测相机端口何时被点击:

void qSlicerTrackingModuleWidget::onCameraPortClicked(){
  Q_D(qSlicerTrackingModuleWidget);

  // Clear current entries
  d->CameraPortComboBox->clear();

  int n = 0;

  // Loop over camera ports until last one is found. Add all available ports to combo box and exit.
  while(1){ 
    cv::VideoCapture cap = cv::VideoCapture(n);


    if(!cap.isOpened()){ 
      return;
    }
    QString portNum = QString::fromStdString(std::to_string(n++));
    d->CameraPortComboBox->addItem(portNum);
    qSlicerCoreApplication::processEvents();
  }
}

设置函数 运行 最后一个,并将 GUI 分配给实际函数。

connect( d->CameraPortComboBox,   SIGNAL(clicked()),  this, SLOT(onCameraPortClicked()));

每次单击组合框时,我都需要刷新并尝试检测摄像头,但由于界面设置,我不确定是否可行。我不认为不断刷新程序是一个好的选择,所以我没有想法。有什么办法吗?

您可以在另一个线程中生成摄像机列表:

void qSlicerTrackingModuleWidget::onCameraPortClicked() {
  QtConcurrent::run([this]{
    QStringList cameras;
    for (int i = 0; true; ++i) {
      auto cap = cv::VideoCapture(i);
      if (! cap.isOpened()) break;
      cameras << QString::number(i);
    }
    // This is a queued, thread-safe call. It will execute in the
    // GUI thread.
    QMetaObject::invokeMethod(this, "onCameraList", 
                              Q_ARG(QStringList, cameras));
  });
}

// another slot
void qSlicerTrackingModuleWidget::onCameraList(const QStringList & cameras) {
  Q_D(qSlicerTrackingModuleWidget);
  d->CameraPortComboBox->clear();
  for (auto portNum : cameras)
    d->CameraPortComboBox->addItem(portNum);
}

另请注意,组合框没有 clicked() 信号。您需要在组合框上安装事件过滤器以访问您感兴趣的事件。也许您也可以使用 Enter 事件来代替:

class EventSignaller : public QObject {
  Q_OBJECT
  bool eventFilter(QObject * obj, QEvent * event) {
    if (event->type() == QEvent::Enter)
      emit entered(qobject_cast<QWidget*>(obj));
    if (event->type() == QEvent::MouseButtonPress)
      emit clicked(qobject_cast<QWidget*>(obj));
    return QObject::eventFilter(obj, event);
  }
public:
  EventSignaller(QObject* parent = 0) : QObject(parent) {}
  Q_SIGNAL void entered(QWidget*);
  Q_SIGNAL void clicked(QWidget*);
  void track(QWidget * widget) {
    widget->removeEventFilter(this); // ensure we're unique
    widget->installEventFilter(this);
  }
};

qSlicerTrackingModuleWidget::qSlicerTrackingModuleWidget() : ... {
  auto signaller = new EventSignaller(this);
  connect(signaller, SIGNAL(entered(QWidget*)), // or SIGNAL(clicked(QWidget*))
                     SLOT(updateCameraPorts()));
  ...
}

void qSlicerTrackingModuleWidget::updateCameraPorts() {
  ...
}