Pergunta

Para um dos meus projetos, tenho uma árvore de objetos derivados de Qobject, que utiliza a funcionalidade pai/filho de Qobject para construir a árvore.

Isso é muito útil, pois faço uso de sinais e slots, uso os ponteiros guardados do QT e espero que os objetos pais excluam filhos quando forem excluídos.

Até agora tudo bem. Infelizmente agora meu projeto exige que eu gerencie/altere a ordem das crianças. O QObject não fornece nenhum meio de alterar a ordem de seus filhos (exceção: a função Raise () do Qwidget - mas isso é inútil neste caso). Então agora estou procurando uma estratégia de controlar a ordem das crianças. Eu tinha algumas idéias, mas não tenho certeza sobre seus prós e contras:



Opção A: Variável de membro do índice de classificação personalizado

Use um int m_orderIndex variável de membro como uma chave de classificação e fornecer um sortedChildren() Método que retorna uma lista de QObjects classificados por esta chave.

  • Fácil de implementar na estrutura de objeto existente.
  • Problemático quando QObject::children() O método é substituído - levará a problemas durante os loops quando a ordem dos itens for alterada, também é mais cara que a implementação padrão.
  • Deve voltar à ordem do objeto QObject se todas as teclas de classificação forem iguais ou 0/Padrão.

Opção B: Lista redundante de crianças

Manter uma lista redundante de crianças em um QList, e adicione crianças quando forem criados e destruídos.

  • Requer rastreamento caro de objetos adicionados/excluídos. Isso basicamente leva a um segundo rastreamento de filho/pai e muitos sinais/slots. O QObject já faz tudo isso internamente, por isso pode não ser uma boa ideia fazê -lo novamente. Também parece que muito inchaço é adicionado para algo simples, como mudar a ordem das crianças.
  • Boa flexibilidade, uma vez que uma lista de crianças pode ser modificada conforme necessário.
  • Permite que uma criança esteja no QLIST mais de uma vez, ou não (mesmo que ainda seja um filho do QOBject)

Opção C: ...?

Quaisquer idéias ou feedback, especialmente de pessoas que já resolveram isso em seus próprios projetos, são muito apreciadas. Feliz Ano Novo!

Foi útil?

Solução

Passei muito tempo passando por todas essas opções nos últimos dias e as discuti com cuidado com outros programadores. Decidimos ir para Opção a.

Cada um dos objetos que estamos gerenciando é filho de um objeto pai. Como o QT não fornece nenhum meio de reordenar esses objetos, decidimos adicionar um int m_orderIndex Propriedade para cada objeto, que padroniza para 0.

Cada objeto tem uma função de acessador sortedChildren() que retorna a QObjectList das crianças. O que fazemos nessa função é:

  1. Use o normal QObject::chilren() função para obter uma lista de todos os objetos infantis disponíveis.
  2. dynamic_cast todos os objetos para a nossa "classe base", que fornece o m_orderIndex propriedade.
  3. Se o objeto for fundível, adicione -o a uma lista de objetos temporários.
  4. usar qSort com um costume LessThan Função para descobrir se o QSORT precisa alterar a ordem de dois objetos.
  5. Retorne a lista de objetos temporários.

Fizemos isso pelos seguintes motivos:

  • O código existente (especialmente o código do QT) pode continuar usando children() sem ter que se preocupar com os efeitos colaterais.
  • Podemos usar o normal children() Função em locais onde o pedido não importa, sem ter nenhuma perda de desempenho.
  • Nos lugares onde precisamos da lista ordenada de crianças, simplesmente substituímos children() por sortedChildren() e obtenha o efeito desejado.

Uma das coisas boas sobre essa abordagem é que a ordem das crianças não muda se todos os índices de classificação forem definidos como zero.

Desculpe por responder minha própria pergunta, espero que esclareça as pessoas com o mesmo problema. ;)

Outras dicas

Que tal algo como ...

  1. Qlist listchildren = (qlist) crianças ();
  2. classificar listchildren
  3. foreach listchildren setParent (tempparent)
  4. foreach listchildren setParent (OriginalParent)

Um hack desagradável: QObject :: filhos () Retorna uma referência para cons-consclar. Você pode afastar a constência e, assim, manipular diretamente a lista interna.

Isso é muito mau, e tem o risco de invalidar iteradores que o QObject mantém internamente.

Eu não tenho uma opção C separada, mas comparando a opção A e B, você está falando ~ 4 bytes (ponteiro de 32 bits, número inteiro de 32 bits) em ambos os casos, então eu iria com a opção B, como você pode manter Essa lista classificada.

Para evitar a complexidade adicional de rastrear crianças, você pode trapacear e manter sua lista classificada e arrumada, mas combine-a com um método classificado que filtra todos os não-filhos. Complexidade em termos, isso foi para acabar em torno de O (nlogm) (n = crianças, M = entradas da lista, assumindo que m> = n, ou seja, as crianças sempre são adicionadas), a menos que você tenha uma grande reviravolta nas crianças. Vamos chamar esta opção C.

O Quicksort, na sua opção sugerido A, fornece O (n2) (WC), mas também exige que você recupere os ponteiros, rastreá -los, recuperar um número inteiro, etc. O método combinado só precisa de uma lista dos ponteiros (Aught para ser o (n)).

Eu tive o mesmo problema e resolvi por opção B. O rastreamento não é tão difícil, basta criar um método "Void Addchild (tipo *ptr);" e outro para excluir um filho.

Você não sofre de redundância maligna se armazenar exclusivamente as crianças dentro da lista de crianças privadas/públicas (qlist) de cada item e soltar a base do QOBject. Na verdade, é muito fácil implementar livremente a criança livre (embora isso exija um ponteiro pai extra).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top