1

I have a situation where I would like to pass a QML event to another QML item in the middle of the initial event handler. e.g.

Item {
   id: item1

   Keys.onPressed: {
      // Pre-process...

      passEventToObject(event, item2);

      // Post-process based on results of event passing...
   }
}

TextInput {
   id: item2
   // Expect key press event to be handled by text input
}

What can I do to acheive passEventToObject?

Notes:

  • I don't have access to modify Keys.onPressed inside item2, it's a QML built-in (TextInput).
  • The event passing must happen in the middle of item1.Keys.onPressed
spbots
  • 1,513
  • 1
  • 15
  • 22

3 Answers3

3

One method to move events between Items is to create a C++ plugin and use QCoreApplication::sendEvent. Unfortunately, Qt doesn't map directly from the QML KeyEvent and the C++ QKeyEvent, so the interface to the plugin will need to expose the internals of the event:

bool EventRelay::relayKeyPressEvent(
   int key,
   Qt::KeyboardModifiers modifiers,
   const QString& text,
   bool autoRepeat,
   ushort count) const
{
   QKeyEvent event(QKeyEvent::KeyPress, key, modifiers, text, autoRepeat, count);
   return relayEventToObject(&event, mpTargetObject);
}

To use it:

EventRelay { id: relay }

Item {
   id: item1
   Keys.onPressed: {
      // Pre-process...

      relay.relayEventToObject(event, item2);

      // Post-process...
   }
}

TextInput {
   id: item2
}
spbots
  • 1,513
  • 1
  • 15
  • 22
  • I have the seem need. This example is not very clear to me: you write the definition of a method with a signature and in QML you call a method with a different name and signature. Maybe `relayEventToObject` is just a method that calls `QCoreApplication::sendEvent` but can you explain better what `relayKeyPressEvent` is meant for? – ceztko Jun 16 '17 at 08:19
3

You can simply invoke the other object's signal in your first object signal handler :

Item {
   id: item1
   Keys.onPressed: {
      // Pre-process...
      item2.Keys.pressed(event);
      // Post-process based on results of event passing...
   }
}

Item {
   id: item2
   Keys.onPressed: {
      // Some other stuff happens here
   }
}
GrecKo
  • 6,615
  • 19
  • 23
  • Thanks - that almost worked. If I had `Keys.onPressed` defined in the second Item it would invoke that action but not the actions of parent classes. My particular case is using a `TextInput`, and when using this method `item2` does not handle the key press. – spbots Nov 14 '14 at 15:58
1

I think it could be useful the section "Signal to Signal Connect" that you can find here. Basically, each signal has a connect method which can be exploited to create a signals chain.

If you are interested to forword key events (as in your example) consider instead the forwardTo property:

This property provides a way to forward key presses, key releases, and keyboard input coming from input methods to other items. This can be useful when you want one item to handle some keys (e.g. the up and down arrow keys), and another item to handle other keys (e.g. the left and right arrow keys). Once an item that has been forwarded keys accepts the event it is no longer forwarded to items later in the list.

The documentation provides a nice and simple example.

BaCaRoZzo
  • 7,502
  • 6
  • 51
  • 82
  • The `forwardTo` property is interesting, however it won't work in the case I've described - I need to forward the event to another object in the middle of processing it (not at the beginning or end as `forwardTo` dictates). – spbots Nov 13 '14 at 17:16
  • Sorry, didn't consider the comments in the code. My fault. :) I'm not sure there exists a way to achieve the interleaving you are searching for. As a naive solution you could intercept events in the first item (pre-processing) emit a custom signal for the second item, and then at the end of the second item processing, another custom signal to the first item (post-processing). – BaCaRoZzo Nov 13 '14 at 20:20