0

I need to make a GUI button that tells it's parent (or parent's parent or even parent's parent's parent...) that different widget in the QStackedLayout should be shown. I created a custom QEvent:

class SwitchScreenEventWidget : public QEvent {
public:
  SwitchScreenEventWidget(QWidget* w) : SwitchScreenEvent(), widget(w) {
    if(widget==nullptr)
      throw "SwitchScreenEventWidget received null widget.";
  }
  virtual QWidget* getWidget() const {;return widget;}
private:
  QWidget* const widget;
};

I invoke it like this:

// Through debugger I checked that this is getting called properly
void GraphButton::buttonClicked()
{
  if(qApp!=nullptr && parent()!=nullptr)
    qApp->notify(parent(), new SwitchScreenEventWidget(getGraph()));
}

And handle it like this:

bool ViewStack::eventFilter(QEvent* e)
{
    if(e->type()>=QEvent::User) {
      if(SwitchScreenEvent* event = dynamic_cast<SwitchScreenEvent*>(e)) {
        // Show the given widget
      }
      return true;
    }
    return false;
}

I use eventFilter which is then registered to the main app widget. But the event is not getting captured. Somewhere I read some QEvents simply don't bubble up through the hierarchy.

So do all events bubble or not? If not, which do, which don't and why? And how do I make my event bubble properly?

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
  • 1
    Try setting the `accepted` flag of your event to false. – thuga Jan 18 '16 at 12:44
  • 1
    Why don't you use signal-slot system for this purpose? Are you limited somehow? – NG_ Jan 18 '16 at 13:09
  • @troyane I don't want to directly access main widget from the `QPushButton` - I want the solution to be working regardless of the number of parent nodes the button has. – Tomáš Zato Jan 18 '16 at 13:16
  • You could still use signal, just search recursivly for your ``findChildren`` from your most upper window and connect the signal. – Sebastian Lange Jan 18 '16 at 13:53
  • @SebastianLange yeah, that's smart and I already do it for other things, but I would still prefer the event method, because those buttons can be added after app init. – Tomáš Zato Jan 18 '16 at 13:56
  • @TomášZato Another option would be to have a MainWindow-Singleton or subclass Q[Gui]Application and have a signal-to-signal connection there, which then connects to your upper-widget slot (both probably bad design). – Sebastian Lange Jan 18 '16 at 14:03
  • Can you provide maximum simplified but workin example, so we can play with it. – NG_ Jan 18 '16 at 18:31
  • @troyane Ok, I will try to create a sample project. But the question itself is complicated enough - the code will be probably too large for a SO question. – Tomáš Zato Jan 18 '16 at 19:12

1 Answers1

0

I think the best way for you is subclassing QApplication, override notify method and do your "bubbles events" by yourself. I'm pretty sure that mouse and keyboard events "bubbles up" by this method and other events don't.

bool QCoreApplication::notify(QObject * receiver, QEvent * event)

Sends event to receiver: receiver->event(event). Returns the value that is returned from the receiver's event handler. Note that this function is called for all events sent to any object in any thread.

For certain types of events (e.g. mouse and key events), the event will be propagated to the receiver's parent and so on up to the top-level object if the receiver is not interested in the event (i.e., it returns false).

So you can change this behavior by your realisation.

Also about you code example. I think this check

if( qApp!=nullptr )

is useless beacause of you always will have instance of qApp.

Evgeny
  • 3,910
  • 2
  • 20
  • 37