2012-02-07 22 views
5

Estoy creando una aplicación utilizando Qt que consiste en un widget que se utiliza como fondo de la aplicación y una interfaz de control de usuario que flota arriba.Cómo widgets independientes de capa en Qt?

Un ejemplo similar es google maps, donde el mapa está en el fondo y los controles están en la parte superior del fondo.

Pero la cosa es que el widget de fondo se puede cambiar a un widget diferente (hay un widget que muestra un mapa, otro widget que muestra imágenes de vídeo, ...)

Y lo mismo sucede para el botones en la interfaz de control de usuario, no están directamente relacionados con el fondo actual y se pueden cambiar dinámicamente.

He intentado usar QStackedLayout, utilizando dos capas, el widget de fondo y la interfaz de control del usuario. Pero no puede interactuar con la capa de fondo porque todos los clics están bloqueados por el widget en el frente.

¿Alguna sugerencia?

Respuesta

1

Su pregunta es demasiado genérica para darle una respuesta específica, pero la solución más obvia es implementar clases que hereden de QWidget para cada componente posible de su sistema. En su ejemplo, puedo visualizar 2 componentes distintos: Fondo y Controles. Antecedentes almacenaría todos los datos de imagen, como mapas y videos, mientras que los controles tendrían los botones para interactuar con el sistema. Incluso puede dividir el fondo en diferentes clases para administrar imágenes o videos. Recomiendo usar una clase central de GUIController que herede de QObject para administrar todas las interacciones de la interfaz, como conectar las señales/ranuras o implementar cualquier animación, de esta manera puedes agregar/administrar múltiples widgets sin pasar por diferentes .cpp.

EDIT: Con su comentario, parece que su problema principal es que los eventos de su mouse no se propagan a sus widgets como esperaba. Probablemente la razón para esto es que no está estableciendo las relaciones padre/hijos entre los componentes. Asegúrese de que está llamando la QWidget constructor por defecto en sus clases de widgets personalizados como la de arriba:

CustoWidget(QWidget *parent = 0, Qt::WFlags flags = 0) : QWidget(parent, flags) 
{ 
//your code here 
} 

Al crear la clase controladora, configura las relaciones correctas entre los componentes. En el contexto de su equipo, seens para mí que todos los componentes se añadirán como hijos de fondo, por lo que se parecería a continuación:

class Controller : public QObject 
{ 
public: 
    Controller(QObject *parent = 0, Qt::WFlags flags = 0) : QObject(parent, flags) 
    { 
    wdg_back_= new BackWidget(this); 
    wdg_control_ = new Controls(wdg_back); 
    wdg_1_ = new GenericWidget(wdg_back); 

    //connect your signals/slots, etc 
    } 

private: 
    BackWidget *wdg_back_; 
    Controls *wdg_control_; 
    GenericWidget *wdg_1_; 
} 
+1

Ese es el enfoque que he seguido, me han agrupado todos los controles en un solo flash, que los contiene con los diseños apropiados. Pero el problema es que, incluso si hay algunos widgets dispersos en la pantalla, este Widget de control ocupa toda la pantalla y bloquea los eventos del mouse. Otra cosa que creo que podría resolver este problema es agregar los controles uno por uno como capas separadas en el widget apilado. De esta manera, solo bloquearán los clics del mouse que están en ellos. – Victor

+0

¿Estás seguro de que estás agregando todos tus widgets como elementos secundarios de este widget de control/fondo? Asegúrese de que sus constructores de widgets personalizados estén llamando al constructor predeterminado de QWidget y que esté configurando el widget de titular (probablemente el fondo) como el padre de todos sus widgets durante la inicialización de la GUI. –

+0

El problema parece ser el que se discute aquí: http://www.qtcentre.org/threads/45844-Mouse-events-with-StackAll-QStackedLayout Dado que estoy usando un apilado Layout con dos widgets (el fondo y el widget de control), el widget de control, que está en la parte superior, está bloqueando todos los eventos de clic del mouse. Voy a intentar configurar el widget de control como elementos secundarios del fondo, en lugar de que sean hermanos. – Victor

2

puede colocar un filtro en el flujo de eventos a sus widgets de interfaz utilizando el QObject::installEventFilter() función, e interceptar todos los eventos entrantes de clic de mouse. Una vez que haya capturado estos eventos, use la función de filtro para delegarlos en el widget de fondo o entréguelos a los botones de la interfaz frontal. Lo más probable es que tenga que usar las coordenadas (x, y) del clic del mouse para determinar si un evento debe ir al widget de fondo, o uno de los widgets de los botones de primer plano.

Otra opción es crear una clase derivada desde QAbstractButton (o cualquier QWidget que esté utilizando para sus botones) y volver a implementar las funciones de evento para clics del mouse en ese widget (es decir, QAbstractButton::mousePressEvent(), etc.). Cuando llega un clic del mouse, verifique si el mouse estaba sobre el botón y, de no ser así, envíe el evento al widget de fondo mediante una señal o QCoreApplication::sendEvent().

+0

Este es un enfoque agradable que no había pensado, Definitivamente implementaré esto si no puedo encontrar otra manera de establecerlos sin bloquear los eventos de clic del mouse. – Victor

+0

He intentado implementar esto, actualmente estoy tratando de reenviar todos los mousePressEvents al widget de fondo con: QCoreApplication :: sendEvent (_bgWidget, ev); dentro del controlador mousePressEvent, pero se reciben en el elemento primario del widget de fondo en lugar de en el widget de fondo. – Victor

+1

Su objeto de fondo también tiene que volver a implementar 'mousePressEvent()' o 'event()' para poder procesar correctamente los eventos que está enviando ... de lo contrario, las implementaciones predeterminadas de estas funciones en la clase base 'derivado de simplemente devolverá' falso ', y el padre será el receptor del evento. – Jason

0

Ok, finalmente he encontrado una solución para mi problema.

Mi enfoque de utilizar QStackedWidget era incorrecto, el widget en el fondo no se puede hacer clic, y aunque podría hacerse, no es lo que estaba buscando.

Al final, esto es lo que he hecho:

QWidget *centralWidget = new QWidget(this); 
setCentralWidget(centralWidget); 

MapView *backgroundWidget = new MapView(centralWidget); 
backgroundWidget->setMinimumSize(1024,600); 

QGridLayout *controlsLayout = new QGridLayout(centralWidget); 
MyControlWidget *control1 = new MyControlWidget(centralWidget); 
control1->setMinimumSize(140,140); 
control1->show(); 

controlsLayout->addWidget(control1,2,0); 

lo tanto, crear un QWidget, centralWidget que será la matriz del fondo y el primer plano. Establezca el fondo en pantalla completa y organice los controles en un QGridLayout, que no afecta al widget de fondo.

Si hago clic en un control, el evento es procesado por este control, pero al hacer clic en un espacio vacío activará un evento de ratón en el backgroundWidget, que es lo que necesitaba.

Voy a probar esto durante algún tiempo y si funciona bien voy a cerrar la pregunta.

Cuestiones relacionadas