Pregunta

Al escribir GUI, con frecuencia me encuentro con el siguiente problema:Suponga que tiene un modelo y un controlador.El controlador tiene un widget. W que se utiliza para mostrar una propiedad X del modelo.

Debido a que el modelo puede cambiarse desde fuera del controlador (puede haber otros controladores usando el mismo modelo, deshacer operaciones, etc.), el controlador escucha los cambios en el modelo.El controlador también escucha los eventos en el widget. W y actualiza la propiedad X respectivamente.

Ahora sucede lo siguiente:

  1. el valor en W está cambiado
  2. Se genera un evento, el controlador en el controlador es invocado
  3. el controlador establece el nuevo valor para X en el modelo
  4. el modelo emite eventos porque ha sido cambiado
  5. el controlador recibe un evento de cambio del modelo
  6. el controlador obtiene el valor de X y lo configura en el widget
  7. ir a 1.

Hay varias soluciones posibles para eso:

  1. Modifique el controlador para establecer un indicador cuando se actualice el modelo y no reaccionar ante ningún evento del modelo si este indicador está configurado.
  2. Desconecte el controlador temporalmente (o dígale al modelo que no envíe ningún evento durante algún tiempo)
  3. Congele cualquier actualización del widget

En el pasado, normalmente optaba por la opción 1, porque es la más sencilla.Tiene el inconveniente de saturar tus clases con banderas, pero los otros métodos también tienen sus inconvenientes.

Solo para que conste, he tenido este problema con varios kits de herramientas GUI, incluidos GTK+, Qt y SWT, así que creo que es bastante independiente del kit de herramientas.

¿Alguna mejor práctica?¿O la arquitectura que uso es simplemente incorrecta?

@Tímido:Esa es una solución para algunos casos, pero aún así obtendrás una ronda de eventos superfluos si X se cambia desde fuera del controlador (por ejemplo, cuando se usa el patrón de comando para deshacer/rehacer), porque entonces el valor ha cambiado, W se actualiza y activa un evento.Para evitar otra actualización (inútil) del modelo, se debe tragar el evento generado por el widget.
En otros casos, el modelo puede ser más complejo y una simple comprobación de qué ha cambiado exactamente puede no ser factible;una vista de árbol compleja.

¿Fue útil?

Solución

Por lo general, debe responder a los eventos de entrada en el widget y no a los eventos de cambio.Esto evita que se produzca este tipo de bucle.

  1. El usuario cambia la entrada en el widget
  2. El widget emite un evento de cambio (desplazamiento realizado/entrar hecho clic/salir del mouse, etc.)
  3. El controlador responde y se traduce en un cambio en el modelo.
  4. El modelo emite evento
  5. El controlador responde, cambia el valor en el widget
  6. Evento de cambio de valor emitido, pero no escuchado por el controlador

Otros consejos

La forma estándar de QT de lidiar con esto y también la sugerida en su útil tutorial es realizar el cambio en el valor en el controlador solo si el nuevo valor es diferente del valor actual.
Así es como las señales tienen la semántica de valueChanged()

ver este tutorial

Banderas para indicar trabajos de actualización.Puede envolverlos en métodos como BeginUpdate y EndUpdate.

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