您的位置:首页 > 移动开发 > Android开发

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(原链接已跪,上个转发的)

先看效果=============》


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下载地址

点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  qml qt qt on android