检查小部件是否在布局Qt中

时间:2012-10-09 23:56:32

标签: qt

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

  • 小工具名称:infoClient
  • 图层名称:verticalLayout_3

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

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

5 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分: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更麻烦。

答案 2 :(得分:1)

使用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*>(),这样你就会安全。

答案 3 :(得分:0)

我同意Tom Panning使用QObject::findChild()方法找到您孩子的解决方案。 但是向QLayout添加一个Widget会将其重新显示给布局的父级。所以你必须通过这样的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);
    }
}

答案 4 :(得分:0)

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

  

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