强制更新QListWidget以添加/删除元素

时间:2013-07-05 07:06:39

标签: qt qt5 redraw

我试图围绕现有的管理控制台应用程序包装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)

2 个答案:

答案 0 :(得分:7)

1)您无需直接调用重绘。

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

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

问题是你的“搜索管理器”会阻止Qt的事件循环。这就是为什么listview没有重新绘制的。

答案 1 :(得分: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在另一个帖子中进行搜索。