QML Keyboard Shortcut Click Button - button

I am trying to add a keyboard shortcut to my QML but I am having a hard time getting it working without repeating logic. Below is the code,
Controls.Button {
id:sendAction
Shortcut {
sequence: "Ctrl+Return"
onActivated: parent.trigger()
}
onPressed: {call function}
}
If I repeat the calling of the function, the keyboard shortcut works but with parent.trigger() it fails with trigger isn't a property of the button. I have tried looking up what functions can be called in a shortcut to trigger the parent but the documentation is quite light. Essentially what I need though is what to add in to onActivated to trigger the onPressed without repeating the function call.

have you tried the pressed signal?
onActivated: parent.pressed()
https://doc.qt.io/qt-5/qml-qtquick-controls2-abstractbutton.html#pressed-signal

Solved with the code below.
Item {
Shortcut{
id: sendShortcut
sequences: ["Ctrl+Enter", "Ctrl+Return"]
onActivated: sendAction.action.trigger()
}
}
Controls.Button {
id:sendAction
action: Controls.Action {
onTriggered{
call function
}
}
onPressed: action.trigger()
}

Related

How can I select a number or text in the spinner textfield on entry?

I am using a javafx spinner for Integers. Is there a way to select the value in the Spinner, when I click on it or move to it with TAB?
Like it works for TextAreas with the following code:
myTextArea.focusedProperty().addListener((obs, isFocused, isNowFocused) -> {
if (isNowFocused) {
myTextArea.selectAll();
}
})
selectAll() does not work for the spinner. I would like to start typing in the spinner field without previously deleting the initial value.
You can call selectAll() on the editor (which is a TextField) of the Spinner.
spinner.focusedProperty().addListener((obs, wasFocused, isFocused) -> {
if (isFocused) {
Platform.runLater(spinner.getEditor()::selectAll);
}
});
When trying this I had to wrap the selectAll call inside a Platform.runLater call. The Spinner itself might be doing something when it gains focus which interferes with the call to selectAll; using Platform.runLater defers the call to some time after Spinner does whatever it does.

QML - Capture all UI events of children objects

In my QML project, I need an object to capture all the UI events of its children objects. So, if any of its children register a click or something, the parent object needs to know about it. The issue here is that all of the children objects are pre-defined classes such as MyButton or MyComboBox. These classes all have defined MouseAreas and onClicked() functions that can't be overridden. Therefore, I need the parent object to capture all the events of its children WITHOUT modifying the MouseAreas of the children. Please let me know the best way to accomplish this.
You can crawl the object tree, connecting a function to every onClicked-signal.
For this we need three parts:
The signal that shall be connected
The function that does the crawling
A function that creates another function to call the signal with custom arguments.
I chose, that my signal shall have to arguments: sender and arguments. Sender is the object, that I clicked on, and arguments are the arguments of the clicked-signal of the clicked object. This is empty for QtQuick.Controls 2.x Buttons and contains one entry (mouse) for MouseAreas.
signal somethingWasClicked(var sender, var arguments)
As this signal has not the same signature as clicked for every clickable object, we can't connect it directly to this signal. We need a intermediary function that calls the signal for us, has the needed arguments in it's scope and has no arguments. We need to build this dynamically for each object we spy on.
function createSpyFunction(object) {
return function() { somethingWasClicked(object, arguments) }
}
And lastly for the crawl-function. We need to store the function we create somewhere. For this I utilize the fact that all QtObjects are JS-Objects in some sense, so I can use Object.defineProperty to dynamically add JS-properties to them. Here I can store our function, without the need of modyfing the sourcecode of the components them selves.
After creating this function, I connect it to the onClicked-handler.
function crawlChildren(obj) {
if (obj.onClicked) {
Object.defineProperty(obj, '__clickedFunction', { value: createSpyFunction(obj) })
obj.onClicked.connect(obj.__clickedFunction)
}
if (obj.children) {
var i = 0
for (; i < obj.children.length; i++) {
crawlChildren(obj.children[i])
}
}
}
This function I finally call in
Component.onCompleted: crawlObj(this.contentItem)
of the root ApplicationWindow of my programm.
As I only call it in the Component.onCompleted-handler, objects that will be added after this, won't be spied uppon. To change this, we will also need to spy on onChildrenChanged, and crawl the newly added objects as well. The process there is almost similar, so this is left as an exercise to the user, or might be subject to a new question.
You can try to overlay your items with a MouseArea. In the event handlers you can check the position and call the event handlers of the underlying items.
Item {
MyButton { id: mybutton
/* set the anchors */
}
MyMouseComboBox { id: myMouseComboBox
/* set the anchors */
}
MouseArea {
anchros.fill: parent
onClicked: {
// mouse.accepted = false
// Check whether clicked point is within mybutton
// on true, call mybutton.doSomething()
// or call mybotton.onPressed(mouse)
}
}

QML Keyboard Shortcuts are interfering with Key OnPressed Events

I'm having an issue with my QML program. In the top-level main.qml file, I have some keyboard Shortcuts like so:
Shortcut {
sequence: "Up"
onActivated: {
// yadda yadda
}
}
In another file, I have several Keys.onPressed calls like this:
Keys.onPressed: {
if (event.key == Qt.Key_Up) {
// yadda yadda
}
}
Apparently, the Shortcuts are interfering with the OnPressed calls. When I comment out the Shortcuts, the OnPressed's work fine. But when they're both active, it seems the Shortcut intercepts the keyboard press and prevents the OnPressed from activating.
I know that with mouse events, Qt has the "accepted" variable. If you want an event to continue propagating down the stack, you can just set "accepted = false" in the OnActivated function in order to accomplish this. However, I am not seeing any equivalent "accepted" variable in the Shortcuts API. Is there some other way I can ensure that the event is propagated correctly?
In order to act like a shortcut, Shortcut must have a higher priority than key handlers in active focus items. Otherwise it would be no different to a normal key handler. However, sometimes there is a need to override a shortcut, like you do.
In Qt 5.8 and earlier, you can disable a Shortcut to prevent it processing shortcut events under certain conditions. For example:
Shortcut {
enabled: !someItem.activeFocus
}
In Qt 5.9, a better mechanism has been introduced for this. Active focus items with key handlers can now override shortcuts by accepting shortcut override events using Keys.shortcutOverride. For example:
Item {
focus: true
Keys.onShortcutOverride: {
if (event.key == Qt.Key_Up)
event.accepted = true
}
Keys.onUpPressed: ...
}

How to receive keyboard events in an unfocused QtQuick Item?

I want to use a press-and-hold behaviour to switch states of a gui Item.
I use a FocusScope(below) to recieve keyboard events.
FocusScope{
id:pageFocus
property var pedalKey//a key id
Keys.enabled: true
Keys.onPressed: {
if(event.key===pedalKey && !event.isAutoRepeat)
{
state="a"
}
}
Keys.onReleased: {
if(event.key===pedalKey && !event.isAutoRepeat)
{
state="b"
}
}
}
It works, but when FocusScope loses the focus.
The most terrible thing is that I don't know which Item got the focus.
Is there any way to enable the Item to receive keyboard events without focus?
You can forward key events to other objects (even multiple objects). Here is the example from Qt's documentation:
Item {
ListView {
id: list1
// ...
}
ListView {
id: list2
// ...
}
Keys.forwardTo: [list1, list2]
focus: true
}
It works, but when FocusScope lost the focus.
Yes, key events are only delivered to the items with activeFocus. The event will be sent to the inner-most item first, proceeding up the chain of parents until one of them accepts the events (using e.g. the handlers you're using here).
The most terrible thing is that I don't know which Item got the focus.
You can use the Window.activeFocusItem attached property to see where the focus is currently.
Is there any way to enable the Item to receive keyboard events without focus?
Not easily or directly. You could use event filtering to intercept events before they get to the window, but I would consider that absolutely an option of last resort. Shortcuts are another possibility, depending on what presses you are trying to intercept.

QML Calendar : Programmatically call onClicked handler

My QML application is displaying a Calendar element.
When the selected date is changed (clicked), I need to update an other element (an image).
I have something like this:
Calendar {
id: calCalendar
onClicked: {
// update other QML element
}
}
It works fine when the user click with the mouse on the calendar: the other element (the image) is correctly updated.
My problem is initialization : when my app is started, the calendar displays the current date by default, and I'd like to programmatically call the onClicked handler, to make sure the image is up to date.
I don't know how to do that.
If you want to do something when a QML component is done initializing you can use the Component.onCompleted : slot.
Calendar {
id: calCalendar
onClicked: {
// update other QML element
}
Component.onCompleted: {
// Do stuff for initialization.
// you could do this here : calCalendar.Clicked()
// if you want to use the same code for initialization and for user input handling later on.
}
}
The point is the following : onXXX : { declares a slot to handle the singal XXX. Here the signal is Clicked. You can trigger the signal programmatically as you say, just by invoking it like a function. You'll need to know a valid overload for the arguments (if any).

Resources