qml在stackView的情况下处理Android back键(返回键)全局双击back键退出程序
2017-08-09 23:32
459 查看
在qml中的使用StackView,编译到手机后想通过back键进行pop操作,但是用正常的Keys过滤的时候由于StackView在pop的时候丢失焦点所以back键直接变成android默认的推出功能,然后就想用c++来写一个过滤器来获取Key_Back;
思路来源于http://www.mamicode.com/info-detail-1434390.html(原链接已跪,上个转发的)
先看效果=============》
KeyFilter类实现如下
KeyFilter.h
思路来源于http://www.mamicode.com/info-detail-1434390.html(原链接已跪,上个转发的)
先看效果=============》
1、在qml中正常处理Key_back
方法什么说的没什么说的,需要注意的是正常键盘事件需要获取焦点,如果焦点丢失那么事件也不会接受到,在StackView中遇到的问题就是这个原因,下面贴写正常的代码Rectangle{ anchors.fill: parent; color:"lightgreen"; Keys.onPressed: { if (event.key == Qt.Key_Back) { event.accepted = true; } } focus:true;//必须要有焦点 }
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2、用c++处理
2.1
首先qt c++ QObject派生出来的类中都有过滤事件,我们只要继承一个QObject的类重写下过滤函数就能实现消息的过滤[virtual] bool QObject::eventFilter(QObject *watched, QEvent *event)//过滤的虚函数
2.2
然后将其写成单例模式(方便qml中的信号链接),添加一个sig_KeyBackPress()信号用来通知qml back键被按下KeyFilter类实现如下
KeyFilter.h
#include <QObject> class KeyFilter : public QObject { Q_OBJECT public: static KeyFilter* GetInstance(); explicit KeyFilter(QObject *parent = 0); //设置过滤对象 void SetFilter(QObject *obj); protected: //事件过滤 bool eventFilter(QObject *watched, QEvent *event); private: signals: void sig_KeyBackPress(); void sig_AppExit(); public slots: };KeyFilter.cpp
#include "KeyFilter.h" #include <QKeyEvent> #include <QDebug> #include <QMutex> KeyFilter::KeyFilter(QObject *parent) : QObject(parent) { } //单例 KeyFilter* KeyFilter::GetInstance() { static QMutex mutex; static QScopedPointer<KeyFilter>instance; if(Q_UNLIKELY(!instance)) { mutex.lock(); if(!instance) { instance.reset(new KeyFilter); } mutex.unlock(); } return instance.data(); } bool KeyFilter::eventFilter(QObject *watched, QEvent *event) { //获取事件类型 if(event->type() == QEvent::KeyPress) { //转换成键盘事件 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); //判断是否是back事件 if(keyEvent->key() == Qt::Key_Back) { //发送back键按下的信号 emit sig_KeyBackPress(); return true; } } return false;// } void KeyFilter::SetFilter(QObject *obj) { //将过滤器注册到对应的类 obj->installEventFilter(this); }
2.3
在main.cpp中将过滤器注册为QML的基本类型,通过QQmlComponent来获取对象,然后给对象添加过滤器。#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QtQml> #include <QDebug> #include "KeyFilter.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("keyFilter", KeyFilter::GetInstance()); QQmlComponent component(&engine, QUrl("qrc:/main.qml")); //获取对象 QObject *object = component.create(); //添加过滤器 KeyFilter::GetInstance()->SetFilter(object); return app.exec(); }
2.4
接下来就是qml中的操作啦!具体处理就不多说了直接看代码import QtQuick 2.5 import QtQuick.Window 2.2 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 Window { //用来自适应android property real multiplierH: (mainWindow.height/640)*1000; property real multiplierW: (mainWindow.width/360)*1000; function dpH(numbers) { return numbers*multiplierH/1000; } function dpW(numbers) { return numbers*multiplierW/1000; } function dpX(numbers){ return (dpW(numbers)+dpH(numbers))/2; } id:mainWindow; visible: true width: 360 height: 640 title: qsTr("Hello World") //标记back是否被按下(如果true再次接受到按下消息后将退出app) property bool backPressed: false; //链接过滤器信号 Connections{ target:keyFilter; onSig_KeyBackPress:{ //如果stackview不是在根节点就pop不标记接受到back信号 if (stackView.depth > 1) { stackView.pop(); } //第一次接受到back else if(!backPressed) { //启动一个定时器,在定时器结束后没收再次收到back信号就将back标记初始化 timer.start(); backPressed = true; //启动提示动画 back_animation.start(); } //在 一定时间没连续收到back信号 else if(backPressed) { Qt.quit(); } } } //定时器 Timer{ id:timer; interval: 3000; triggeredOnStart: false; onTriggered: { backPressed = false; timer.stop(); } } MouseArea{ anchors.fill: parent; onClicked: { if (stackView.depth < 2) { var pageTwo = Qt.createComponent("PageTwo.qml"); stackView.push(pageTwo); console.log("depth = "+stackView.depth); } } } StackView{ id: stackView; anchors.fill: parent; focus: true; initialItem: "qrc:/PageOne.qml"; } //退出的消息框 Rectangle{ id:exit_rect; radius: dpX(20); z: 10; width: dpW(130); height: dpH(30); color:"black"; opacity:0; anchors.centerIn: parent; Text{ anchors.centerIn: parent; text:qsTr("再按一次退出"); color: "white"; font.pixelSize: dpX(15); z:10; } } //退出提示的动画 SequentialAnimation{ id:back_animation; NumberAnimation { target: exit_rect; property: "opacity"; duration: 1000; to:100; easing.type: Easing.InCubic; } NumberAnimation { target: exit_rect; property: "opacity"; duration: 1000; to:100; easing.type: Easing.InOutQuad; } NumberAnimation { target: exit_rect; property: "opacity"; duration: 1000; to:0; easing.type: Easing.InOutQuad; } } }
3、这样我们就实现了StcakView back键的返回,以及正常目录下双击back退出程序
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------4、最后上下demo下载地址
点击打开链接相关文章推荐
- Android双击返回键退出程序代码
- Android双击返回键退出程序
- Android 双击返回键退出程序 实现
- Android 双击返回键退出程序 实现
- Android 双击返回键退出程序 实现
- Android -- 双击返回键退出程序
- android双击返回键退出程序
- android双击返回键退出程序
- android双击返回键退出程序
- Android 双击返回键退出程序 实现
- Android按返回键退出程序但不销毁,程序后台运行,同QQ退出处理方式
- Android按返回键退出程序但不销毁,程序后台运行,同QQ退出处理方式
- android双击返回键退出程序
- Android 双击返回键退出程序 实现
- Android双击两次返回按钮退出程序
- Android开发如何双击返回键退出程序
- android双击返回键退出程序
- android返回键后程序不退出moveTaskToBack
- Android 返回键双击退出程序
- android 退出程序及back键相关处理