Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check whether a widget is in the layout Qt

Tags:

qt

How to check whether a widget is in a layout? I have a layout that may contain the widget or not.

  • Widget name: infoClient
  • Layer name: verticalLayout_3

Need to check if the widget exists in the layout, then do not add a new one.
And if does not exist, add a new one.
How to do it?

void MainWindow::slotPush1()
{
    if <there is no infoClient> ui->verticalLayout_3->addWidget(new infoClient(this));
}
like image 465
SerJS Avatar asked Oct 09 '12 23:10

SerJS


People also ask

How do I see widgets in Qt?

Just add all your widgets into the layout and use QWidget::hide() , QWidget::show() when needed. For more complex situations you can use The State Machine Framework.

What is layout in Qt?

Qt uses a layout-based approach to widget management. Widgets are arranged in the optimal positions in windows based on simple layout rules, leading to a consistent look and feel. Custom layouts provide more control over the positions and sizes of child widgets.

What is input widget Qt Designer?

Widgets are the primary elements for creating user interfaces in Qt. Widgets can display data and status information, receive user input, and provide a container for other widgets that should be grouped together. A widget that is not embedded in a parent widget is called a window.


4 Answers

Few points:

  • The parent of a widget in a layout is the widget containing the top-level layout
  • Layouts can be nested.
  • A layout contains items (QLayoutItem), which are either layouts (layout() is not null) or widgets (widget() is not null). In the end you have a tree of layout items.

So You need to do a search from the parent 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;
}
like image 146
UmNyobe Avatar answered Oct 03 '22 21:10

UmNyobe


Use QObject::findChild to find a child by its name. For instance:

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

Note: findChild is a template function. If you're not familiar with template functions, just know that you pass the type of object you want to find (in your example, it looks like you could use ui->verticalLayout_3->findChild<infoClient*>("infoClient")). If you want to find a QWidget, or anything that inherits from QWidget, you can just use findChild<QWidget*>() and you'll be safe.

like image 35
Tom Panning Avatar answered Sep 29 '22 21:09

Tom Panning


There is no mechanism within Qt that will perform the check that you are looking for. You will have to implement it yourself:

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;
}

Despite what I've suggested above, I don't really recommend it. It makes more sense to store whether or not you've added infoClient to your layout as an independent boolean within your program somewhere. Querying the contents of layouts in this manner is somewhat unusual, and is messier than just using a bool.

like image 20
RA. Avatar answered Oct 01 '22 21:10

RA.


I agree with Tom Panning's solution to find your child with the QObject::findChild() method. But adding a Widget to QLayout will reparent it to the layout's parent. So you'll have to find it by calling it with the MainWindow object like that:

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

If your infoClient widget was added in the QtDesigner, you won't have problems with this solution. The designer sets per default the object name. If the infoClient was added to the layout in your code, you have to set the object name explicitly, otherwise you won't be able to find it because its name is empty: (Assuming, m_client is a member variable of MainWindow)

void MainWindow::createWidgets()
{
    if (infoClientShouldBeAdded) {
        m_client = new infoClient(this);
        m_client->setObjectName("infoClient");
        ui->verticalLayout_3->addWidget(m_infoClient);
    }
}
like image 45
tomvodi Avatar answered Oct 02 '22 21:10

tomvodi