2008-09-24 13 views
17

Al escribir GUI, con frecuencia me he encontrado con el siguiente problema: Supongamos que tiene un modelo y un controlador. El controlador tiene un widget W que se utiliza para mostrar una propiedad X del modelo.Ciclos de evento de interrupción en GUI

Como el modelo puede cambiarse desde el exterior del controlador (puede haber otros controladores que utilicen el mismo modelo, operaciones de deshacer, 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 en consecuencia.

Ahora, ocurre lo siguiente:

  1. se cambia el valor en W
  2. se genera un evento, el controlador en el controlador se invoca
  3. el controlador establece el nuevo valor para X en el modelo
  4. m Odel emite eventos porque se ha cambiado
  5. la controlador recibe un evento de cambio a partir del modelo
  6. el controladorobtiene el valor de X y lo establece en el widget
  7. Goto 1.

Hay varias soluciones posibles para ello:

  1. Modifique el controlador para establecer un indicador cuando se actualice el modelo, y no reaccione ante ningún evento del modelo si se establece este indicador.
  2. Desconectar el controlador de forma temporal (o dice el modelo de no enviar ningún evento para algún tiempo)
  3. congelación de las actualizaciones desde el widget

En el pasado, yo solía ir a la opción 1., porque es la cosa más simple. Tiene el inconveniente de saturar sus clases con banderas, pero los otros métodos también tienen sus inconvenientes.

Solo para el registro, he tenido este problema con varios kits de herramientas GUI, incluyendo GTK +, Qt y SWT, por lo que creo que es bastante agotadora.

¿Alguna de las mejores prácticas? ¿O la arquitectura que uso simplemente está mal?

@Shy: Esa es una solución para algunos casos, pero aún se obtiene 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 el valor ha cambiado, W se ha actualizado y activa un evento. Para evitar otra actualización (inútil) del modelo, el evento generado por el widget debe ser eliminado.
En otros casos, el modelo podría ser más complejo y un simple control de lo que exactamente ha cambiado podría no ser factible, por ej. una vista de árbol compleja.

+0

Tengo este problema con los cuadros de lista en MFC todo el tiempo. –

Respuesta

3

Normalmente debería responder a eventos de entrada en el widget y no cambiar eventos. Esto evita que ocurra este tipo de bucle.

  1. usuario cambia de entrada en el widget
  2. Widget emite evento de cambio (desplazarse hecho/introducir la licencia de clic/ratón, etc.)
  3. controlador responde, se traduce en un cambio del modelo
  4. emite modelo de eventos
  5. controlador responde, los cambios de valor en widget de
  6. evento de cambio de
  7. valor emitido, pero no escuchó por el controlador
+0

Gracias por la sugerencia. Lamentablemente, esto no siempre es posible, según el kit de herramientas de GUI. –

5

La forma estándar de QT de manejar esto y también la sugerida en su útil tutorial es hacer el cambio al valor en el controlador solo si el nuevo valor es diferente del valor actual.
Este es el camino de ellos señales de la semántica de valueChanged()

see this tutorial

1

banderas para indicar el trabajo updaing. Puede envolverlos en métodos como BeginUpdate y EndUpdate.

+0

¿Es esta una práctica común o solo estás haciendo una conjetura? – Statement

+0

He utilizado indicadores para indicar el estado de actualización en el desarrollo de Windows de MFC que tenía un documento con arquitectura de vista múltiple. Más recientemente, en el desarrollo de .NET Windows utilicé indicadores para indicar si el evento de cambio de selección se activó durante el inicio y podría ignorarse. – Leah

Cuestiones relacionadas