1

我正在尝试围绕现有的管理控制台应用程序包装 GUI。主要功能是搜索网络设备,给它一个超时,本质上是一个阻塞调用,直到超时到期(使用sleep来做阻塞)。在此示例中,调用是this->Manager->Search(...).

我的问题是我希望 QListWidget 在搜索发生时显示“正在搜索...”,然后在搜索完成时更新结果。我的按钮点击代码Search如下:

void ManagerGUI::on_searchButton_clicked()
{
  ui->IPList->clear();
  new QListWidgetItem(tr("Searching..."), ui->IPList);
  ui->IPList->repaint();
  this->Manager->Search(static_cast<unsigned int>(this->ui->searchTime->value()*1000.0));
  ui->IPList->clear();
  if(this->Manager->GetNumInList() != 0)
    this->displayFoundInList(this->Manager->GetFoundList());
  else
    new QListWidgetItem(tr("No Eyes Found"), ui->IPList);
  ui->IPList->repaint();
}

当我点击按钮时,QListWidget IPList直到发生超时之后才会更新(我假设直到这个回调终止之后)。有没有人有什么建议?我的印象是调用ui->IPList->repaint()会导致列表立即重绘。

附加信息:

  • QT 版本 5.1.0 32 位
  • 使用VS2012编译
  • 在 Win7 Pro 64 位上运行(但要移植到 OSX 和 Linux,所以请不要特定于 win)
4

2 回答 2

7

1)您不需要直接调用repaint。

2)您应该异步进行搜索。这是个大话题——你应该先学习 Qt 的基础知识。

从信号和槽开始,然后了解 QThread 或 QtConcurrent。然后实现一个将进行搜索并发送必要信号的类:搜索开始时的第一个信号,搜索停止时的第二个信号。然后将插槽连接到此信号并在此插槽内使用您的列表视图。

问题是您的“搜索管理器”阻止了 Qt 的事件循环。这就是为什么 listview 不重绘的原因。

于 2013-07-05T08:19:20.130 回答
1

你需要一个信号槽系统,因为你的搜索被阻塞了。理想情况下,您应该在新线程中进行搜索。但是,您可以使用 processEvents() 作弊

void ManagerGUI::on_searchButton_clicked()
{
  ui->IPList->clear();
  new QListWidgetItem(tr("Searching..."), ui->IPList);
  emit signalStartSearch();
}

void ManageGUI::slotStartSearch()
{
  // Process any outstanding events (such as repainting)
  QCoreApplication::processEvents();
  this->Manager->Search(static_cast<unsigned int>(this->ui->searchTime->value()*1000.0));
  emit signalSearchCompleted();
}

void ManagerGUI::slotSeachCompleted()
{
  ui->IPList->clear();
  if(this->Manager->GetNumInList() != 0) {
    ui->IPList->setUpdatesEnabled(false);
    this->displayFoundInList(this->Manager->GetFoundList());
    ui->IPList->setUpdatesEnabled(true);
  } else {
    new QListWidgetItem(tr("No Eyes Found"), ui->IPList);
  }
}

理想情况下,您希望Manager->Search发出信号,然后用于QtConcurrent::run在另一个线程中进行搜索。

于 2013-07-05T09:35:57.080 回答