objetos interfaz español creator c++ design-patterns signals-slots

c++ - interfaz - ¿Qué son señales y ranuras?



objetos en qt (6)

Imagine tener una GUI en su aplicación. La mayoría de las veces, el flujo de control no sería muy lineal, es decir, en lugar de tener una secuencia clara de acciones, tendríamos un usuario que interactúa con la GUI (como botones, menús, etc.).

Este es esencialmente un modelo impulsado por eventos que se puede implementar bastante bien con el patrón de señales y ranuras. las señales son eventos que son generados por objetos (piensen en componentes de la GUI) y las ranuras son los receptores de esos eventos.

Aquí hay un ejemplo: imagine que tiene una casilla de verificación, representada como un objeto en su lenguaje de programación. Pueden suceder varias cosas en esa casilla de verificación: se puede alternar, lo que a su vez también significa que está configurada o no. Esas son las señales que puede emitir. Los denominaremos checkboxToggled, checkboxSet y checkboxUnset. Como puede ver, en este ejemplo, la casilla de verificación emitirá siempre la casilla de verificación Señal desactivada cuando se alterna, pero también exactamente una de las otras dos señales, según cómo cambie el estado.

Ahora imagine tener algunos otros objetos, a saber, una etiqueta, que por el bien de este ejemplo siempre existe como un objeto pero puede "aparecer" y "desaparecer" y un pitido del sistema (también representado por un objeto), que simplemente puede emitir un pitido. Esas son las ranuras que tienen esos objetos. Los llamaremos "messageAppear", "messageDisappear" y "beep".

Supongamos que desea que el pitido del sistema emita un pitido cada vez que se active la casilla de verificación, y que la etiqueta aparezca o desaparezca según si el usuario marcó o desactivó la casilla de verificación.

De este modo, conectará las siguientes señales a las siguientes ranuras (señales a la izquierda, ranuras a la derecha):

checkboxToggled -> beep checkboxSet -> messageAppear checkboxUnset -> messageDisappear

Eso es básicamente eso.

las señales y las ranuras también pueden tener argumentos. Por ejemplo, utilizando un deslizador que establece un valor numérico, le gustaría enviar el valor modificado junto con la señal emitida tan pronto como el usuario mueva el control deslizante: sliderChanged (int).

Por supuesto, para hacer algo realmente útil, escribiría algunas clases propias que contendrían algunas señales propias y ranuras. Esto se hace con bastante facilidad y, al usar estas señales y ranuras, tiene una forma agradable de interactuar con la GUI u otras partes de su código de una manera orientada a eventos.

Tenga en cuenta que las señales y las ranuras son a menudo simétricas en el sentido de que a menudo puede haber una señal correspondiente a una ranura. Por ejemplo, una casilla de verificación puede emitir una señal cuando se alterna, pero también puede contener una ranura que activa la casilla de verificación. Sería fácil de implementar para separar las casillas de verificación que siempre están configuradas de forma opuesta entre sí.

¿Alguien puede explicar en términos simples el patrón de "señales y ranuras"?


Las señales y las ranuras son una manera de desacoplar un emisor (la señal) y cero o más receptores (las ranuras). Digamos que es un sistema que tiene eventos que desea poner a disposición de cualquier otra parte del sistema interesada en esos eventos. En lugar de cablear el código que genera eventos para el código que quiere saber sobre esos eventos, usaría un patrón de señales y ranuras.

Cuando el emisor señala un evento (generalmente llamando a la función asociada con ese evento / señal), todos los receptores de ese evento se llaman automáticamente. Esto le permite conectar y desconectar los receptores según sea necesario durante la vida útil del programa.

Dado que esta pregunta fue etiquetada C ++, aquí hay un enlace a la biblioteca Boost.Signals que tiene una explicación mucho más completa.


Supongo que estás hablando de las señales y ranuras de QT.
Es muy sencillo.

Una instancia de una clase puede disparar una señal y otra instancia de tal vez otra clase puede captar esa señal en una ranura. Es como una llamada de función solo que el tipo que llama a la función no necesita saber quién quiere recibir la llamada.

La mejor manera de ilustrar es con un ejemplo.
La clase QPushButton tiene una señal QPushButton :: clicked (). Esa señal se dispara cada vez que se hace clic en el botón. El botón no necesita saber a quién le interesa saber que se produjo un clic. simplemente dispara la señal y quien esté interesado puede conectarse a ella.
El QDialog en el que se coloca el botón está de hecho interesado en saber cuándo se hizo clic en el botón. Tiene la ranura MyDialog :: buttonClicked (). En el cuadro de MyDialog, debe conectar () la señal de clic de los botones () al botón del cuadro de diálogo Con el botón () ranura para que se llame a la ranura cuando se dispara la señal.

Un montón de cosas más avanzadas:

  • Argumentos, una señal puede tener argumentos y estos argumentos también pueden pasarse a la ranura.
  • llamadas de subprocesos cruzados: si está haciendo una conexión de ranura de señal que necesita ser una secuencia cruzada, QT almacenará automáticamente las señales y las pondrá en la fila correcta. Esto sucede automáticamente, por ejemplo, cuando un hilo de GUI necesita comunicarse con un hilo de trabajo.

Aquí hay más información en la documentación de QT.


Creo que uno puede describir mejor las señales y las ranuras cuando las ve como un posible vehículo de implementación para el patrón de observador o el patrón de publicación / suscripción . Hay una signal , por ejemplo buttonPressed(IdType) en el lado del editor. Cada vez que se presiona el botón, se llaman todas las ranuras que están conectadas a esa señal. Las máquinas tragamonedas están en el lado del suscriptor. Una ranura podría ser, por ejemplo, sendMail(IdType) .

Junto con el evento "botón presionado", la ranura sabría qué botón se presionó, ya que la identificación se habría entregado. IdType representa el tipo de datos enviados a través de la conexión entre el publicador y el suscriptor. Una operación posible para el suscriptor sería connect(signal, slot) que podría conectar buttonPressed(IdType) con sendMail(IdType) , de modo que si se presiona el botón, se sendMail(IdType) esa ranura en particular.

Lo bueno de esto es que el suscriptor (el lado de la ranura) no necesita preocuparse por los detalles de la señal. Solo necesita conectarse. Por lo tanto, aquí tenemos una gran cantidad de acoplamiento flexible . Puede cambiar la implementación de los botones, pero la interfaz para las ranuras seguirá siendo la misma.

Mire Qt Signals / Slots o Boost Signals para obtener más información.



Existe un malentendido común de que las clases son sustantivos como Person, Dog, Bicycle y tal. Entonces tiene sentido pensar que una persona (instancia) tiene un perro y una bicicleta.

Comencemos con qué objetos son (se supone que son). Los objetos son datos y procedimientos. ¿Qué son los programas? Datos y procedimientos. Se supone que los objetos son (relativamente) subprogramas independientes "pequeños". Debido a que la programación se enseña de manera muy vaga y mal utilizada (cita requerida), las personas piensan que todo tiene que ser una clase o un objeto. Esto no es así, los objetos son programas independientes "pequeños" con una API "pequeña" (subrutinas públicas). Algunos programadores ni siquiera dividen sus proyectos en subprogramas y simplemente usan objetos donde los datos y los procedimientos son más adecuados.

Ahora, asumiendo que estamos de acuerdo en que los objetos son programas, podemos estar de acuerdo en que, en la mayoría de los casos, los programas no necesitan tener copias de otros programas de un tamaño y complejidad similar (es decir, un objeto no apunta a otro objeto), puede necesitar programas más pequeños para administrar datos (como estructuras de datos) pero yo no necesito otro objeto.

¿Por qué? Porque el acoplamiento de objetos los hace dependientes. ¿Por qué es eso malo? Porque cuando los objetos son independientes puede probarlos y también prometer a otros programadores y clientes que el objeto (un pequeño programa independiente) es capaz de realizar ciertas tareas con gran certeza. También puede estar seguro de que continúa funcionando siempre que no se hayan realizado cambios en ese objeto.

Entonces, ¿qué son las ranuras y las señales? Si comprende que los objetos son como los programas y que no deberían contener idealmente copias o punteros a otros objetos, necesita una forma de comunicarse. Por ejemplo, los procesos que se ejecutan en su computadora pueden usar sockets, direcciones IP y puertos para comunicarse. Los objetos pueden usar algo muy similar a RPC llamado señales y ranuras. Se trata de una estructura de datos pensada como intermediario entre dos objetos más grandes que almacenan subrutinas ( slots ) de objetos y permite que otros objetos llamen (señalen) estas subrutinas ( slots ) con parámetros adecuados sin saber nada de estos otros objetos, salvo los parámetros que exigir.

De modo que la estructura subyacente son conjuntos (posiblemente matrices) de punteros de procedimiento (posiblemente) fuertemente tipados, que otros objetos pueden llamar con parámetros adecuados sin un puntero a estos objetos. Las personas que llaman solo necesitan acceder al objeto de señal (que no contiene detalles de implementación) que define los parámetros esperados.

Esto también es flexible porque permite algunos casos de uso especial, como ranuras que solo responden a la señal una vez, ranuras múltiples para una señal y otros casos de uso similares, como el antirrebote.