如何检查小部件是否在布局中?我有一个可能包含或不包含小部件的布局。
- 小部件名称:
infoClient
- 图层名称:
verticalLayout_3
需要检查小部件是否存在于布局中,然后不要添加新的。
如果不存在,则添加一个新的。
怎么做?
void MainWindow::slotPush1()
{
if <there is no infoClient> ui->verticalLayout_3->addWidget(new infoClient(this));
}
如何检查小部件是否在布局中?我有一个可能包含或不包含小部件的布局。
infoClient
verticalLayout_3
需要检查小部件是否存在于布局中,然后不要添加新的。
如果不存在,则添加一个新的。
怎么做?
void MainWindow::slotPush1()
{
if <there is no infoClient> ui->verticalLayout_3->addWidget(new infoClient(this));
}
几点:
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;
}
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
.
使用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*>()
并且你会很安全。
我同意汤姆潘宁用这种方法找到你的孩子的解决方案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);
}
}
另一种可能性是跟踪您创建的小部件的指针(例如,通过将它们存储在 std::vector 或 Qt 等效项中)。这允许使用 indexof(QWidget*):
在此布局中搜索小部件小部件(不包括子布局)。返回小部件的索引,如果未找到小部件,则返回 -1。