8

如何检查小部件是否在布局中?我有一个可能包含或不包含小部件的布局。

  • 小部件名称:infoClient
  • 图层名称: verticalLayout_3

需要检查小部件是否存在于布局中,然后不要添加新的。
如果不存在,则添加一个新的。
怎么做?

void MainWindow::slotPush1()
{
    if <there is no infoClient> ui->verticalLayout_3->addWidget(new infoClient(this));
}
4

5 回答 5

3

几点:

  • 布局中小部件的父级是包含顶级布局的小部件
  • 布局可以嵌套。
  • 布局包含项目(QLayoutItem),它们可以是布局(layout()不为空)或小部件(widget()不为空)。最后,您有一个布局项目树。

因此,您需要从父小部件(dfs、bfs)进行搜索。

bool checkWidgetInsideLayout(const QWidget* _someWidget){

return _someWidget != NULL && 
       _someWidget->parent() != NULL && 
       _someWidget->parent()->layout() != NULL && 
       foundItem(_someWidget->parent()->layout(), _someWidget ); 
}

//clumsy dfs
bool foundItem(const QLayout* layout, const QWidget* _someWidget ){

     for(int i = 0; i < layout->count(); i++){
        QLayoutItem* item = layout->itemAt(i);
        if(item->widget() == _someWidget )
            return true;
         if(item->layout() && foundItem(item->layout(), _someWidget)  )
             return true;
     }
     return false;
}
于 2012-10-10T08:09:02.383 回答
2

Qt 中没有机制可以执行您正在寻找的检查。您必须自己实现它:

void MainWindow::slotPush1()
{
   if (doesLayoutContainInfoClient(ui->verticalLayout_3))
   {
      ui->verticalLayout_3->addWidget(new infoClient(this));
   }
}

bool MainWindow::doesLayoutContainInfoClient(QLayout* layout)
{
   const QString infoClientName("infoClient");

   for (int i=0; i<layout->count(); i++)
   {
      QWidget* layoutWidget = layout->itemAt(i)->widget();
      if (layoutWidget)
      {
         if (infoClientName == layoutWidget->metaObject()->className())
         {
            return true;
         }
      }
   }
   return false;
}

尽管我在上面提出了建议,但我并不真正推荐它。将您是否已将 infoClient 添加到布局中作为独立布尔值存储在程序中的某个位置会更有意义。以这种方式查询布局的内容有些不寻常,而且比仅使用bool.

于 2012-10-10T01:04:40.807 回答
2

使用QObject::findChild按名称查找子项。例如:

void MainWindow::slotPush1()
{
    if (ui->verticalLayout_3->findChild<QWidget*>("infoClient")) // your code to add it here
}

注意:findChild 是一个模板函数。如果您不熟悉模板函数,只需知道您传递了您想要查找的对象类型(在您的示例中,看起来您可以使用ui->verticalLayout_3->findChild<infoClient*>("infoClient"))。如果你想找到一个 QWidget,或者任何从 QWidget 继承的东西,你可以使用findChild<QWidget*>()并且你会很安全。

于 2012-10-10T01:06:25.517 回答
1

我同意汤姆潘宁用这种方法找到你的孩子的解决方案QObject::findChild()。但是将 Widget 添加到 QLayout 会将其重新设置为布局的父级。所以你必须通过MainWindow像这样的对象调用它来找到它:

void MainWindow::slotPush1()
{
    if (this->findChild<QWidget*>("infoClient")) {
        // ...
    }
}

如果您的 infoClient 小部件已添加到 QtDesigner 中,您将不会遇到此解决方案的问题。设计者默认设置对象名称。如果 infoClient 被添加到代码中的布局中,则必须显式设置对象名称,否则将无法找到它,因为它的名称为空:(假设 m_client 是 MainWindow 的成员变量)

void MainWindow::createWidgets()
{
    if (infoClientShouldBeAdded) {
        m_client = new infoClient(this);
        m_client->setObjectName("infoClient");
        ui->verticalLayout_3->addWidget(m_infoClient);
    }
}
于 2012-10-10T06:13:09.510 回答
0

另一种可能性是跟踪您创建的小部件的指针(例如,通过将它们存储在 std::vector 或 Qt 等效项中)。这允许使用 indexof(QWidget*)

在此布局中搜索小部件小部件(不包括子布局)。返回小部件的索引,如果未找到小部件,则返回 -1。

于 2017-05-12T05:24:25.923 回答