Reputation: 85
How to check whether a widget is in a layout? I have a layout that may contain the widget or not.
infoClient
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));
}
Upvotes: 8
Views: 10657
Reputation: 4777
Another possibility would be to keep track of the pointers of your created widgets (e.g., by storing them in a std::vector or Qt equivalent). This allows to use indexof(QWidget*):
Searches for widget widget in this layout (not including child layouts). Returns the index of widget, or -1 if widget is not found.
Upvotes: 0
Reputation: 22920
Few points:
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;
}
Upvotes: 3
Reputation: 5897
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);
}
}
Upvotes: 1
Reputation: 4772
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.
Upvotes: 2
Reputation: 7777
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
.
Upvotes: 3