HHz的编程日记 - 桌面应用
type: channel
link: https://huanghaozi.com/index.php/tag/%E6%A1%8C%E9%9D%A2%E5%BA%94%E7%94%A8/
items: Qt Quick实现按住执行，松开停止

Qt Quick实现按住执行，松开停止
type: item
date: 2020-03-10T20:15:00+08:00
description: 引言众所周知，Qt开发跨平台应用十分的方便，qml看着也很舒服。但这次我想要实现类似按住说话的功能却没有在API里找到相关的函数（其中有一个onPressedAndHold并不能实现），如果直接用onPressedChange里面装死循环，在执行过程中按钮的状态没法变，进程会卡死在死循环里。经过大量的搜索之后，我最终还是选择了用C++对接qml实现。多线程在qt的C++里实现多线程非常地容易，只需要写一个类，继承自QThread（这只是方法之一），并弄一个private的run函数里面塞线程开始的代码（run函数里不能有参数，可以把参数放在类对象里）。这里我的thread需要接受一个判断按住状态的参数，所以在public加了个bool型的指针，把实现和声明分开为.h和.cpp，如下：/****worker.h****/ #pragma once #include <QtCore> #ifndef WORKER_H #define WORKER_H class Worker : public QThread { public: bool* holding; //判断是否保持按住状态 private: void run(); //线程开始时执行 }; #endif /****worker.cpp****/ #include "worker.h" void Worker::run() { int i = 0; while(*(this->holding)) { //循环条件是holding变量为true qDebug()<<"holding for "<<i<<" seconds."; QThread::msleep(1000); //按住时每隔一秒输出一次 i++; } }C++与QML对接将c++与qml对接也是需要做一个类，继承自QObject，除了将其与qml对接外，还需要与线程类对接，所以我给它整了个线程类的指针/****qccon.h****/ #pragma once #include "worker.h" #ifndef QCCON_H #define QCCON_H class QcCon : public QObject { Q_OBJECT public: Worker* w; //线程对接指针 //QCoreApplication* a; Q_INVOKABLE void toCpp(const QString &); //qml可调用的函数 }; #endif /****qccon.cpp****/ #include "qccon.h" void QcCon::toCpp(const QString &msg) //qml可调用的函数 { if(msg == "t") //若qml传来的消息为t，则将线程的holding变量设置为true { *(w->holding) = true; w->start(); //打开线程 } else *(w->holding) = false; //QObject::connect(w, SIGNAL(finished()), a, SLOT(quit())); } main函数main函数需要创建以上两个类的实例，并将其与qml绑定，必要的代码如下：#include "qccon.h" ... //main函数中加入 QcCon m; Worker w; m.w = &w; engine.rootContext()->setContextProperty("qccon", &m); //将qccon类的实例m整到qml里，对应的qml里的名字叫qcconQML处理在QML里可以直接调用qccon向c++传信息了，如下onPressedChanged: { if(this.pressed) qccon.cppMethod("t"); else qccon.cppMethod("f"); }