QML 几个具有活动焦点/键盘快捷键控制的项目

Posted

技术标签:

【中文标题】QML 几个具有活动焦点/键盘快捷键控制的项目【英文标题】:QML several items with active focus / keyboard shortcut control 【发布时间】:2015-08-26 09:02:30 【问题描述】:

我正在尝试为我的 qml 应用程序实现键盘快捷键控制。我知道有可能使用 Action 元素来做到这一点,但我不想要那些必须使用的菜单和工具栏。 这就是为什么我用键盘事件来处理这个话题。为此,我需要让执行操作的元素成为焦点。但我的目标是全局快捷控制,所以理论上我需要关注所有有问题的元素。 我在文档中找到了FocusScope 类型,但我不确定这是否是我需要的。 这是否意味着嵌套FocusScopes 的焦点“滑动”到不是FocusScope 的最后一个元素并使用focus: true 手动获取焦点,因此只有最后一个元素保持焦点?还是幻灯片中所有获取焦点的元素都设置了activeFocus 属性?

这是正确的方法还是我需要其他方法?

【问题讨论】:

【参考方案1】:

在我看来,Qt Quick 中的焦点是一团糟。它总是让我感到困惑,我最终用forceActiveFocus() 破解它。我推荐新的Shortcut 类型:

Shortcut 
    sequence: StandardKey.Quit
    context: Qt.ApplicationShortcut
    onActivated: Qt.quit()

使用context 属性,您可以选择是要将快捷方式应用于当前窗口还是整个应用程序。

这种类型的动机可以在comments of patch set 5中看到:

Shortcut 旨在取代 Action。以后想干掉后者是因为……

对比实际用户码:http://cutebin.fi/prwznhkbo 查看 BasicButton.qml 周围“动作”相关表达式的数量 恕我直言,整个概念不太适合移动/嵌入式或 QML

动作是一个经常被要求的功能。现在他们有了它,常见的问题是“如何使用不同的图标/文本”或“如何知道触发动作的来源”。两者都与 Action 的唯一目的相矛盾,如果他们只是首先编写更简单的 QML 代码,就不会存在任何“问题”,如示例 sn-p 所示。 :)

显然,Action 最有用的部分是快捷方式功能。那些需要捷径的人对他们需要使用 Action 并不满意,因为“所有这些其他的东西是怎么回事,我只想要一个捷径”。

【讨论】:

嗯,看起来很有希望。谢谢你的好信息。 “我认为 Qt Quick 中的焦点是一团糟”,遗憾的是 链接失效了! @arennuit 我从 Gerrit 的更改中引用的链接?是的,不幸的是。 很公平。感谢收看。【参考方案2】:

也许有不同的方法可以实现这一点,但我知道的方法如下。

这个想法是有一个Item 来控制您需要处理的关键事件。

我会用一个例子来解释自己。正如您将看到的,如果我们有输入小部件(即TextInput),我们必须实现一种机制来将输入返回到我们的Item,以便再次处理键盘事件。在本例中,Qt.Key_Escape 键将用于重新设置焦点。

import QtQuick 2.4
import QtQuick.Controls 1.3

ApplicationWindow 
    id: mainwindow
    title: qsTr("Hello")
    width: 640
    height: 480
    visible: true

    Item 
        anchors.fill: parent
        focus: true

        Keys.onPressed: 
            if ( (event.key === Qt.Key_Q) && (event.modifiers & Qt.ShiftModifier) ) 
                rect.blue()
             else if ( (event.key === Qt.Key_W) && (event.modifiers & Qt.AltModifier) ) 
                rect.red()
             else if ( (event.key === Qt.Key_E) && (event.modifiers & Qt.AltModifier) ) 
                text.text = 'Key Alt+E was pressed'
            
        

        Rectangle
            id: rect
            width: 100
            height: 100
            color: "black"

            function blue() color = "blue"
            function red() color = "red"
        

        Text 
            id: text
            anchors.centerIn: parent
            font.pointSize: 20
        

        TextInput 
            id: textinput
            anchors.top: text.bottom
            text: "sample text"

            Keys.onPressed: 
                if (event.key === Qt.Key_Escape) 
                    console.log('Key Escape was pressed');
                    parent.focus = true;
                
            
        
    

编辑 #1: @Mitch 建议使用 Shortcut QML 类型。如果你可以使用它(它从 Qt 5.5 开始可用),代码会略有不同。无论如何,在某些情况下,您还需要将焦点设置到主应用程序,具体取决于实现的快捷方式序列。例如,如果我们正在输入文本,Shift+Q 在此示例中不起作用。我们需要先按 Escape。

import QtQuick 2.5
import QtQuick.Controls 1.3

ApplicationWindow 
    id: mainwindow
    title: qsTr("Hello")
    width: 640
    height: 480
    visible: true

    Shortcut 
            sequence: "Shift+Q"
            onActivated: rect.blue()
            context: Qt.ApplicationShortcut
    

    Shortcut 
            sequence: "Alt+W"
            onActivated: rect.red()
            context: Qt.ApplicationShortcut
    

    Shortcut 
            sequence: "Alt+E"
            onActivated: text.text = 'Key Alt+E was pressed'
            context: Qt.ApplicationShortcut
    

    Item 
        anchors.fill: parent

        Rectangle
            id: rect
            width: 100
            height: 100
            color: "black"

            function blue() color = "blue"
            function red() color = "red"
        

        Text 
            id: text
            anchors.centerIn: parent
            font.pointSize: 20
        

        TextInput 
            id: textinput
            anchors.top: text.bottom
            text: "sample text"

            Keys.onPressed: 
                if (event.key === Qt.Key_Escape) 
                    console.log('Key Escape was pressed');
                    parent.focus = true;
                
            
        
    

【讨论】:

【参考方案3】:

很像 Mitch,我发现 QML 中的焦点是一团糟,就像它的许多其他方面一样。

我最终实现了我自己的“主动焦点/选择”方案。基本上,我将项目指针列表保留为“活动选择”,我将键盘焦点固定在充当事件调度程序的单个项目上,并将键盘事件重定向到活动选择列表中的所有项目。我还是使用 QML 的MouseArea 来管理选中的项目。

【讨论】:

以上是关于QML 几个具有活动焦点/键盘快捷键控制的项目的主要内容,如果未能解决你的问题,请参考以下文章

如果当焦点处于其他应用程序时,如何拦截键盘事件?

什么对象在QML中主动关注?

WPF虚拟键盘如何不获得当前焦点

电脑快捷键怎么设置

多账号工作台切换至下一个有消息的账号的快捷键是哪个?

当文本字段或文本区域使用纯 JavaScript 获得焦点时禁用键盘快捷键