Pregunta

Para uno de mis proyectos que tengo un árbol de QObject deriva objetos, que utilizan funciones de padre / hijo de QObject para construir el árbol.

Esto es muy útil, ya que hago uso de señales y slots, el uso de punteros guardados de Qt y espero padre se opone a eliminar los niños cuando se eliminan.

Hasta aquí todo bien. Lamentablemente ahora mi proyecto me requiere para gestionar / cambiar el orden de los niños. QObject no proporciona ningún medio para cambiar el orden de sus hijos (excepción: aumento de QWidget función () - pero eso es inútil en este caso). Así que ahora estoy buscando una estrategia de controlar el orden de los niños que tenían algunas ideas, pero no estoy seguro acerca de sus pros y contras:.


Opción A: Custom variable miembro índice de tipo

Usar una variable miembro int m_orderIndex como criterio de ordenación y proporcionar un método sortedChildren() que devuelve una lista de QObjects ordenadas por esta clave.

  • Fácil de implementar en la estructura objeto existente.
  • problemático cuando se overriden método QObject::children() - dará lugar a problemas durante bucles cuando se cambia para artículos, también es más caro que la aplicación por defecto
  • .
  • En caso de caer de nuevo a la orden objeto QObject si todas las claves de clasificación son iguales o 0 / por defecto.

Opción B: lista redundante de los niños

Mantener una lista redundante de los niños en un QList, y añadir a los niños que cuando son creados y destruidos.

  • Requiere seguimiento caro de objetos añadidos / eliminados. Básicamente, esto conduce a un segundo seguimiento hijo / padre y la gran cantidad de señales / ranuras. QObject hace todo esto ya nivel interno, por lo que podría no ser una buena idea para hacerlo de nuevo. También se siente como se le añade una gran cantidad de hinchazón para una cosa tan simple como cambiar el orden de los niños.
  • La buena flexibilidad, ya que un QList de los niños puede ser modificado según sea necesario.
  • Permite que un niño sea en el QList más de una vez, o no del todo (a pesar de que podría ser todavía un niño de la QObject)

Opción C:? ...

Cualquier idea o retroalimentación, especialmente de las personas que ya resolver esto en sus propios proyectos, es muy apreciada. Feliz año nuevo!

¿Fue útil?

Solución

Me pasó mucho tiempo pasando por todas estas opciones en los últimos días y las discutió detenidamente con algunos otros programadores. Nos decidimos por Opción A .

Cada uno de los objetos que están manejando es un hijo de un objeto padre. Desde Qt no proporciona ningún medio de re-ordenar estos objetos, hemos decidido añadir una propiedad int m_orderIndex a cada objeto, que por defecto es 0.

Cada objeto tiene un sortedChildren() función de acceso que devuelve un QObjectList de los niños. Lo que hacemos en esa función es:

  1. Uso de la función QObject::chilren() normal para obtener una lista de todos los objetos disponibles niño.
  2. dynamic_cast todos los objetos de nuestra "clase base", que proporciona la propiedad m_orderIndex.
  3. Si el objeto es moldeable, añadirlo a una lista de objetos temporal.
  4. Uso qSort con una función LessThan encargo de averiguar si qsort tiene que cambiar el orden de los dos objetos.
  5. Vuelta la lista de objetos temporal.

Esto lo hicimos por las siguientes razones:

  • código (especialmente propio código de Qt) puede seguir utilizando children() sin tener que preocuparse por los efectos secundarios existentes.
  • Se puede utilizar la función normal de children() en lugares donde el orden no importa, sin tener ninguna pérdida de rendimiento.
  • En los lugares en los que necesitamos la lista ordenada de los niños, simplemente reemplazar children() por sortedChildren() y obtener el efecto deseado.

Una de las cosas buenas de este enfoque es que el orden de los niños no cambia si todos los índices de clasificación se establece en cero.

Lo siento por responder a mi propia pregunta, la esperanza que ilumina a la gente con el mismo problema. ;)

Otros consejos

¿Qué pasa algo como ...

  1. QList ListChildren = (QList) hijos ();
  2. ListChildren ordenar
  3. foreach ListChildren setParent (TempParent)
  4. foreach ListChildren setParent (OriginalParent)

Un truco desagradable: QObject :: children () devuelve una referencia -to-const. Se podría desecharon la const-dad y así manipular la lista interna directamente.

Esto es bastante malo, sin embargo, y tiene el riesgo de invalidar iteradores, que QObject mantiene internamente.

No tengo una opción C por separado, pero la opción de comparar A y B, que está hablando ~ 4 bytes (puntero de 32 bits, entero de 32 bits) en cualquiera de los casos, por lo que me gustaría ir con la opción B, como puede quedarse con la lista ordenada.

Para evitar la complejidad adicional de los niños de seguimiento, se puede engañar y mantener su lista clasificada y ordenada, pero combinarlo con un método sortedChildren que filtra todos los que no son niños. Complejidad sabia, esta algo para terminar alrededor de O (nlogm) (n = niños, M = lista de entradas, suponiendo que m> = n, se añaden siempre es decir, los niños) a menos que tenga un gran cambio en los niños. Vamos a llamar a esta opción C.

ordenación rápida, en su opción A sugerido, le da O (n2) (wc), sino que también requiere que los punteros retreive, rastrearlos, retreive un entero, etc. El método combinado sólo necesita una lista de los punteros (algo ser O (n)).

Yo tenía el mismo problema y lo resolví por la opción B. El seguimiento no es tan difícil, basta con crear un método de "vacío addChild (Tipo * ptr);" y otro para eliminar un childitem.

No sufre de mal de redundancia si exclusivly almacenar los niños dentro de la deelementos privada / pública (QList) de cada elemento y coloca la base QObject. En realidad es bastante fácil de implementar en la libre auto-free-hijo (a pesar de que requiere un puntero de matriz extra).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top