Pergunta

Ao escrever GUIs, eu freqüentemente vêm sobre o seguinte problema: Suponha que você tenha um modelo e um controlador. O controlador tem um W widget que é usado para mostrar uma X propriedade do modelo.

Porque o modelo pode ser alterada a partir do lado de fora do controlador (pode haver outros controladores utilizando o mesmo modelo, desfazer operações, etc), as escutas controlador para alterações no modelo. O controlador também escuta eventos no W widget e atualiza o X propriedade em conformidade.

Agora, acontece o seguinte:

  1. o valor em W é alterado
  2. um evento é gerado, o manipulador na controller é invocado
  3. controller define o novo valor para X na modelo
  4. modelo emite eventos porque foi alterado
  5. controller recebe um evento de alteração do modelo
  6. controller obtém o valor X e define-o no widget
  7. Goto 1.

Existem várias soluções possíveis para isso:

  1. Modificar o controlador para definir um sinalizador quando o modelo é atualizado, e não reagir a eventos do modelo se este sinalizador está definido.
  2. Desligue o controlador temporariamente (ou dizer o modelo não enviar quaisquer eventos durante algum tempo)
  3. Congelar nenhuma atualização do widget

No passado, eu costumava ir para a opção 1., porque é a coisa mais simples. Tem o inconveniente de desordenar suas aulas com bandeiras, mas os outros métodos têm suas desvantagens também.

Apenas para o registro, eu tive esse problema com vários kits de ferramentas GUI, incluindo GTK +, Qt e SWT, então eu acho que é bastante kit de ferramentas agnóstica.

Qualquer melhores práticas? Ou é a arquitetura que eu uso simplesmente errado?

@Shy: Essa é uma solução para alguns casos, mas você ainda obter uma rodada de eventos supérfluos se X é alterada de fora do controlador (por exemplo, quando se utiliza o padrão de comando para undo / redo), porque, então, o valor tem mudado, W é atualizado e dispara um evento. A fim de evitar uma outra atualização (inútil) para o modelo, o evento gerado pelo widget tem de ser ingerido.
Em outros casos, o modelo pode ser mais complexa e uma verificação simples sobre o que exatamente mudou pode não ser viável, por exemplo, uma exibição em árvore complexa.

Foi útil?

Solução

Normalmente, você deve responder a eventos de entrada no widget e não a eventos de mudança. Isso impede que este tipo de circuito do que ocorrem.

  1. usuário muda a entrada no widget
  2. Widget emite evento de alteração (rolagem feito / Enter clicado licença / rato, etc.)
  3. responde controlador, traduz a mudança no modelo
  4. Modelo emite evento
  5. responde controlador, altera o valor em Widget
  6. evento de alteração
  7. Valor emitido, mas não ouviu pelo controlador

Outras dicas

A forma padrão QT de lidar com isso e também o sugerido em seu tutorial muito útil é para fazer a mudança para o valor no controlador somente se o novo valor é diferente do valor atual.
Esta é sinais maneira tem a semântica de valueChanged()

ver este tutorial

Bandeiras para indicar o trabalho de atualização. Você pode envolvê-los em métodos como BeginUpdate e EndUpdate.

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