【问题标题】:Android back button press doesn't trigger keys.onreleased qmlAndroid后退按钮按下不会触发keys.onreleased qml
【发布时间】:2014-09-22 07:24:56
【问题描述】:

我正在使用 Qt5.3 和 Qtquick2.1 创建一个程序。我正在尝试使用 Keys.onReleased 在我的代码中捕获 android 上的后退按钮按下。但是该事件没有被触发。此外,我已将项目焦点设置为 true。但仍然没有成功。这是代码示例

import QtQuick 2.1
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.1

Rectangle
{
    id: main2
    focus: true
    width: Screen.Width
    height: Screen.Height
    Keys.enabled: true
    Keys.priority: Keys.BeforeItem

    property string load_page: ""
    signal deskConnected()

    Loader{
        id: pageloader
        anchors.fill: parent
        source: "qrc:/qml/resources/Firstpage.qml"
    }

    onDeskConnected: {
         pageloader.item.onDeskConnected()
    }

    function loadPatwin(){
        pageloader.source = "qrc:/qml/resources/Secondpage.qml";
    }

    Keys.onReleased: {
        console.log("back");
        if (event.key === Qt.Key_Back) {
            event.accepted=true;
        }
    }
}

这里的 loadPatwin 是在按下某个其他 qml 中定义的按钮时调用的函数。并加载一个新的 qml。但在那之后,当我按下 android 上的后退按钮时,应用程序被关闭,它甚至不会在日志中打印“后退”。有什么建议我在这里做错了吗?

提前致谢。

【问题讨论】:

  • 是的,它不起作用我也尝试了所有方法,如果您有任何提示,请告诉我
  • JNI_OnLoad 知道了。当我们使用 QApplicationengine 从 main.cpp 加载 main.qml 时,问题就出现了。而不是使用 QQuickview 来加载 main.qml 文件。
  • 不是我的情况,因为我使用 QQuickView 加载 main.qml 我猜我的应用程序中也缺少一些东西
  • 你在哪里处理后退按钮事件??在 qml 或 cpp 中??
  • 在 qml 中,在我从堆栈视图推送的组件中

标签: android qt qml qt5 qtquick2


【解决方案1】:

在 qt quick(Qt5.1 和更高版本)中,ApplicationWindowWindow 都有一个closing 信号,当用户在 android 中触摸返回按钮时会发出该信号。 您可以简单地实现一个 onClosing 处理程序并将 close 参数设置为 false。操作方法如下:

onClosing: {
    close.accepted = false
}

通过这个处理程序,您可以轻松管理 android 设备的后退按钮。它不需要任何额外的许可。例如,假设您有一个 StackView 来管理 GUI。您可以编写这些代码行,然后您的应用程序的行为就像原生 android 应用程序一样:

onClosing: {
        if(stack.depth > 1){
            close.accepted = false
            stack.pop();
        }else{
            return;
        }
    }

【讨论】:

  • 谢谢。这正是我一直在寻找的。​​span>
  • 当我使用 Qt 5.7 和 QtQuick.Window 2.2 时,它显示“Invalid property name onClosing”...
  • 实际上,即使编程接口将其标记为错误,它似乎在您的 onClosing 解决方案中运行良好......非常奇怪。
  • @ChrisFlesher onClosing 事件将在 ApplicationWindow 或 Window 对象中发生,这应该是 main.qml 的父组件
  • 我必须做的是将 close.accepted = false 语句移到 if 语句之前,以防止后退按钮在堆栈位于底部时关闭应用程序。很好的解决方案!
【解决方案2】:

在项目完成加载后添加“forceActiveFocus()”对我有用。

在您的示例中,我会将其放在开头。像这样:

Rectangle
{
    id: main2
    focus: true

    Component.onCompleted: {
        main2.forceActiveFocus()
    }

【讨论】:

    【解决方案3】:

    我不知道这是否是一个很好的例子,但我曾经从 QGuiApplication 创建自己的 GuiApplication 类的子类

    #ifndef GUIAPPLICATION_H
    #define GUIAPPLICATION_H
    
    #include <QGuiApplication>
    
    class GuiApplication : public QGuiApplication
    {
        Q_OBJECT
    public:
    #ifdef Q_QDOC
        explicit GuiApplication(int &argc, char **argv);
    #else
        explicit GuiApplication(int &argc, char **argv, int = ApplicationFlags);
    #endif
    
        bool notify(QObject *receiver, QEvent *event);
    signals:
        void back();
    
    };
    
    #endif // GUIAPPLICATION_H
    

    这是用于 cpp 代码的

    #include "guiapplication.h"
    #include <QDebug>
    
    GuiApplication::GuiApplication(int &argc, char **argv, int) :
        QGuiApplication(argc, argv)
    {
    }
    
    bool GuiApplication::notify(QObject *receiver, QEvent *event)
    {
    // to intercept android's back button
    #ifdef Q_OS_ANDROID
        if(event->type() == QEvent::Close) {
            emit back();
            return false;
        }
        else {
            return QGuiApplication::notify(receiver,event);
        }
    #else
            return QGuiApplication::notify(receiver,event);
    #endif
    }
    

    对于 main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "guiapplication.h"
    
    int main(int argc, char *argv[])
    {
    //    QGuiApplication app(argc, argv);
        GuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        QQmlContext *rootContext = engine.rootContext();
        rootContext->setContextProperty("GUI", &app);
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        return app.exec();
    }
    

    最后是 main.qml

    import QtQuick 2.3
    import QtQuick.Controls 1.2
    
    ApplicationWindow {
        id: applicationWindow
    
        visible: true
        width: 360
        height: 360
    
        Connections {
            target: GUI
            onBack: console.log("back")
        }
    }
    

    【讨论】:

      【解决方案4】:

      我自己刚刚偶然发现了这个问题,但是处理WindowApplicationWindowsclosing 信号的建议解决方案与其说是解决方案,不如说是一种解决方法。虽然它可能适用于 Android,但任何跨平台应用程序都会在您实际上想要关闭窗口时使用“返回”按钮处理(例如,按窗口标题上的“x”按钮条)

      要正确执行此操作,我们必须牢记 QtQuick 中的关键事件处理是如何发生的:activeFocus 的项目首先获取事件。如果它不处理该事件,则将其传播到它的parent 项目。这一直持续到它到达根项目。关键是:WindowApplicationWindow 是最外层的对象,但它们不是基于 Item 的!Item 实际上是 Window::contentItem。这是您需要安装 Keys 处理程序以接收所有未处理的键事件的地方,包括 Back 按钮按下。不幸的是,附加属性不适用于只读对象类型的属性,因此我们必须在onCompleted 中强制执行此操作:

      ApplicationWindow {
          id: window
      
          Component.onCompleted: {
              // Connect to `released` signal and dispatch to `back()`
              contentItem.Keys.released.connect(function(event) {
                  if (event.key === Qt.Key_Back) {
                      event.accepted = true
                      window.back()
                  }
              })
          }
      
          function back() {
              // Back button handling goes here
          }
      }
      

      【讨论】:

      • 这完全正确。感谢您找到真正的解决方案而不是老套的解决方案。
      【解决方案5】:

      在 QML === 是布尔比较

      所以而不是 (event.key === Qt.Key_Back)

      你应该使用 (event.key == Qt.Key_Back) {

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-11
        • 1970-01-01
        • 1970-01-01
        • 2020-03-15
        相关资源
        最近更新 更多