Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Layer independent widgets in Qt?

I'm creating an application using Qt which consists of a widget that is used as the background of the application, and a user control interface that is floating above.

A similar example is google maps, where the map is on the background and the controls are on top of the background.

But the thing is that the background widget can be changed to a different widget (there's a widget that displays a map, another widget that displays video feed, ...)

And the same thing happens for the buttons in the user control interface, they are not directly related to the current background and can be change dinamically.

I've tried using a QStackedLayout, using two layers, the background widget and the user control interface. But you cannot interact with the background layer because all the clicks are blocked by the widget in the front.

Any suggestions?

like image 506
Victor Avatar asked Feb 07 '12 12:02

Victor


2 Answers

You could place a filter on the event stream to your interface widgets using the QObject::installEventFilter() function, and intercept all the incoming mouse-click events. Once you have captured these events, use the filter function to delegate them to either the background widget, or deliver them to the front interface buttons. You would most likely have to use the (x,y) coordinates of the mouse-click to determine if an event should go to the background widget, or one of the foreground button widgets.

Another option is to create a derived class from QAbstractButton (or whatever QWidget you're using for your buttons), and re-implement the event functions for mouse-clicks on that widget (i.e., QAbstractButton::mousePressEvent(), etc.). When a mouse-click arrives, check to see if the mouse was over the button, and if it wasn't, send the event to the background widget via a signal or QCoreApplication::sendEvent().

like image 78
Jason Avatar answered Sep 29 '22 22:09

Jason


Your question is too generic to give you a especific answer, but the most obvious solution is to implement classes that inherits from QWidget for each possible component of you system. In your example I can visualize 2 distinct components: Background and Controls. Background would store all the image data, like maps and videos, while the Controls would have the buttons to interact with the system. You can even break the Background into different classes to manage image or video. I recommend using a central GUIController class that inherits from QObject to manage all the interface interactions, like connecting the signals/slots or implementing any animations, this way you can add/manage multiple widgets without going trough different .cpp's.

EDIT: With your comment, seems that your main problem is that your mouse events are not propagating to your widgets as you expected. Probably the reason for this is that you are not setting the parent/children relationships between the components. Make sure that you are calling the default QWidget constructor in your custom widgets classes like above:

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

When creating the Controller class, sets the right relationships between the components. In the context of your system, seens to me that all components will be added as Background children, so it would looks like below:

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_;
}
like image 25
Ian Medeiros Avatar answered Sep 29 '22 22:09

Ian Medeiros