2012-10-09 29 views
7

¿Cómo comprobar si un widget está en un diseño? Tengo un diseño que puede contener el widget o no.
Comprobar si un widget está en el diseño Qt

  • nombre Widget: infoClient
  • Nombre de capa: verticalLayout_3

necesario comprobar si existe el widget en el diseño, entonces no añadir una nueva.
Y si no existe, agregue uno nuevo.
¿Cómo hacerlo?

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

Respuesta

1

Usa QObject::findChild para encontrar un niño por su nombre. Por ejemplo:

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

Nota: findChild es una función de plantilla. Si no está familiarizado con las funciones de la plantilla, simplemente sepa que pasa el tipo de objeto que desea buscar (en su ejemplo, parece que podría usar ui->verticalLayout_3->findChild<infoClient*>("infoClient")). Si desea encontrar un QWidget, o cualquier cosa que herede de QWidget, puede simplemente usar findChild<QWidget*>() y estará seguro.

+3

Como se señala en otras respuestas, el widget no es un elemento secundario del diseño, pero es secundario del widget padre, ya sea en un diseño o no. – hyde

+0

¡Gracias por la idea! Pero tu camino no está funcionando. El niño debe buscar en el widget padre. Estoy haciendo lo siguiente: 'if (! (Ui-> centralWidget-> findChild (" infoClient "))) ui-> verticalLayout_3-> addWidget (nuevo infoClient (this));' – SerJS

+0

@SerJS "funciona !! " no significa que sea correcto. Te vas a encontrar con problemas tan pronto como andes en los diseños o hagas algo más que trivial con tus widgets. – UmNyobe

2

No hay ningún mecanismo dentro de Qt que realice la comprobación que usted está buscando. Tendrá que implementarlo usted mismo:

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

A pesar de lo que he sugerido anteriormente, realmente no lo recomiendo. Tiene más sentido almacenar si ha agregado infoClient a su diseño como un booleano independiente dentro de su programa en alguna parte. Consultar el contenido de los diseños de esta manera es algo inusual, y es más complicado que simplemente usar un bool.

+0

es un poco más sutil que eso. Su solución funciona para su caso localizado ... no el 'Compruebe si un artilugio está en el diseño Qt'one ... – UmNyobe

+0

@UmNyobe Es cierto, pero la pregunta solo parece estar preguntando por el caso localizado. Lo que también parece perderse en muchas otras respuestas es que "infoClient" no es, de hecho, el widget NAME; es el TIPO de artilugio (a pesar de lo que se dice en la pregunta). –

+0

sí usas 'infoClient' como nombre de clase porque lo que él quiere es" un comportamiento singleton "dentro del diseño que yo obtengo. – UmNyobe

0

Estoy de acuerdo con la solución de Tom Panning para encontrar a su hijo con el método QObject::findChild(). Pero agregar un widget a QLayout lo reparará al padre del diseño. Por lo que tendrá que encontrar llamándolo con el objeto MainWindow así:

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

Si tu widget infoClient se añadió en el QtDesigner, que no tendrá problemas con esta solución. El diseñador establece por defecto el nombre del objeto. Si el infoClient se agregó al diseño en su código, debe establecer el nombre del objeto explícitamente; de ​​lo contrario, no podrá encontrarlo porque su nombre está vacío: (Asumiendo, m_client es una variable miembro de MainWindow)

void MainWindow::createWidgets() 
{ 
    if (infoClientShouldBeAdded) { 
     m_client = new infoClient(this); 
     m_client->setObjectName("infoClient"); 
     ui->verticalLayout_3->addWidget(m_infoClient); 
    } 
} 
3

pocos puntos:

  • el padre de un widget en un diseño es el widget que contiene el diseño de nivel superior
  • diseños se pueden anidar.
  • Un diseño contiene elementos (QLayoutItem), que son diseños (layout() no son nulos) o widgets (widget() no es nulo). Al final, tienes un árbol de elementos de diseño.

Por lo tanto, debe realizar una búsqueda desde el widget principal (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; 
} 
0

Otra posibilidad sería la de llevar un registro de los punteros de sus widgets creados (por ejemplo, almacenándolos en un std :: vector o Qt equivalente). Esto permite usar indexof(QWidget*):

Busca widget de widget en este diseño (sin incluir diseños secundarios). Devuelve el índice del widget, o -1 si no se encuentra el widget.

Cuestiones relacionadas