Qml使用cpp文件的信号槽

文章目录


一、C++文件Demo

Q_INVOKABLE是一个Qt元对象系统中的宏,用于将C++函数暴露给QML引擎。具体来说,它使得在QML代码中可以直接调用C++类中被标记为Q_INVOKABLE的成员函数。

cpp 复制代码
public:
    SerialPort();
    // 返回可用串口
    Q_INVOKABLE QStringList availablePorts();
    // 打开串口
    Q_INVOKABLE bool open(QString portName, QString buadRate, QString dataBits, QString stopBits,QString parity, QString flowControl);
    // 关闭串口
    Q_INVOKABLE void close();
    // 直接调用接口
    Q_INVOKABLE void say();

signals:
    //返回串口打开信息
    Q_INVOKABLE void openMsg(bool open, QString error);
    //接口,用于多线程
    Q_INVOKABLE void sendMsg(QString msg);

public slots:
    //
    void sendMsgSlot(QString msg);

private:
    QThread* m_thread;

    QSerialPort* m_port;

    QMutex m_mutex;
cpp 复制代码
m_port = new QSerialPort();
connect(this, &SerialPort::sendMsg, this, &SerialPort::sendMsgSlot);

tts = new QTextToSpeech(this);

m_thread = new QThread;
m_thread->setObjectName("串口线程");
this->moveToThread(m_thread);
connect(m_thread, &QThread::finished, this, &QThread::deleteLater);
connect(m_thread, &QThread::finished, this, &SerialPort::deleteLater);
m_thread->start();
cpp 复制代码
QStringList SerialPort::availablePorts()
{
    QStringList list;
    foreach(auto info, QSerialPortInfo::availablePorts()) list.append(info.portName());
    list<<"COM11"<<"COM22";
    return list;
}
cpp 复制代码
bool SerialPort::open(QString portName, QString buadRate, QString dataBits, QString stopBits,QString parity, QString flowControl)
{
    bool ok = false;
    QString errstr = "m_port异常";
    {
        QMutexLocker locker(&m_mutex);
        if(!m_port)
        {
            emit openMsg(false, errstr);
            locker.unlock();
            return false;
        }
        m_port->setPortName(portName);
        m_port->setBaudRate(buadRate.toInt());
        m_port->setDataBits((QSerialPort::DataBits)dataBits.toInt());
        m_port->setStopBits((QSerialPort::StopBits)stopBits.toInt());
        m_port->setParity((QSerialPort::Parity)parity.toInt());
        m_port->setFlowControl((QSerialPort::FlowControl)flowControl.toInt());
        ok = m_port->open(QIODevice::ReadWrite);
        errstr = m_port->errorString();
    }
    emit openMsg(ok, errstr);
    return ok;
}
cpp 复制代码
void SerialPort::close()
{
    QMutexLocker locker(&m_mutex);
    if(m_port && m_port->isOpen()) m_port->close();
}
cpp 复制代码
void SerialPort::say()
{
    qDebug()<<"SerialPort CurrrntThread = "<< QThread::currentThread();
    qDebug()<<"---------------------------------------------------------";
    QString text = "2,8,k,1,0";
    tts->say(text);
}
cpp 复制代码
void SerialPort::sendMsgSlot(QString msg)
{
    qDebug()<<"SerialPort CurrrntThread = "<< QThread::currentThread();
    qDebug()<<msg;
    qDebug()<<"---------------------------------------------------------";
}

二、使用步骤

1. 初始化C++文件和QML文件,并建立信号槽

qml中的槽函数也是定义成signal, 所以connect时,槽函数也是SIGNAL()

cpp 复制代码
serial = new SerialPort;
//serial 类向 QML 对象的上下文公开数据
ui->quickWidget_2->rootContext()->setContextProperty("serial", serial);
//根据窗口大小调整QML大小
ui->quickWidget_2->setResizeMode(QQuickWidget::SizeRootObjectToView);
// 
ui->quickWidget_2->setSource(QUrl("qrc:/Form02.qml"));
//
QObject* obj = ui->quickWidget_2->rootObject();
// 调用qml中信号或者槽函数,调用成功返回true,否则false
// 根节点,被调用信号或槽,连接方式,被调用信号或槽的参数1, 被调用信号或槽的参数2(最多10个参数)
if(QMetaObject::invokeMethod(obj, "slotOpenSerial", Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(QString, "")))
    connect(serial, SIGNAL(openMsg(bool,QString)), obj, SIGNAL(slotOpenSerial(bool,QString)));

2.在qml中调用

QGroupButton 自定义的按钮组

cpp 复制代码
Item {
    id: item
    Layout.fillWidth: true
    Layout.preferredHeight: 36

    property alias checkedButton: btngroup.checkedButton

    property int btnIndexChanged: 0

    onBtnIndexChangedChanged: {
        if(btnIndexChanged == 0) {
            checkedButton = ok
        }
        else {
            checkedButton = cancle
        }
    }

    ButtonGroup {
        id: btngroup
        exclusive: true
        buttons: row.children

        onCheckedButtonChanged:
        {
            console.log("button text: ", checkedButton.text)
            btnIndexChanged = checkedButton == ok ? 0 : 1;
        }
    }

    Rectangle{
        id: rect
        anchors.fill: parent

        RowLayout {
            id: row
            anchors.fill: rect
            spacing: 6
            QButton{id: ok; text: "OK"}
            QButton{id: cancle; text: "Cancle"}
        }
    }
}
cpp 复制代码
signal slotOpenSerial(bool isOpen, string error)

onSlotOpenSerial: {
    //console.log(isOpen, error)
    if(!isOpen)
    {
        group.btnIndexChanged = 1
    }
}

qrc:/Form02.qml

cpp 复制代码
//自定义的按钮组
QGroupButton{
	id: group
	Layout.columnSpan: 2
	Layout.fillWidth: true
	onCheckedButtonChanged:
	{
		if(checkedButton.text == "OK"){
			open =  serial.open(portName.currentText, cboxBuad.currentText, dataBits.currentText,stopBits.currentText, parity.currentText, flowControl.currentText);
			console.log("serial return: ", open)
		}
		else
		{
			serial.close()
		}
	}
}

下面代码仅看这段:
QButton{
text: "1";
onClicked: {
//直接调用接口
serial.say();
//通过信号调用
serial.sendMsg("TTTT");
}
}

cpp 复制代码
Rectangle {
    Layout.columnSpan: 2
    Layout.fillWidth: true
    Layout.fillHeight: true
    color: "#156448"
    Flow {
        anchors.fill: parent
        anchors.margins: 9
        spacing: 6
        QButton{
            text: "1";
            onClicked: {
                serial.say();
                serial.sendMsg("TTTT");
            }
        }
        QButton{text: "2"}
        QButton{text: "3"}
        QButton{text: "4"}
        QButton{text: "5"}
        QButton{text: "6"}
        QButton{text: "7"}
        QButton{text: "8"}
        QButton{text: "9"}
        QButton{text: "10"}
        QButton{text: "11"}
        QButton{text: "12"}
        QButton{text: "13"}
        QButton{text: "14"}
        QButton{text: "15"}
        QButton{text: "16"}
        QButton{text: "17"}
        QButton{text: "18"}
        QButton{text: "19"}
        Rectangle {
            width:60
            height: 26
            color: "green"
            property alias text: in1.text
            onTextChanged: console.log(text)
            TextInput {
                id: in1
                anchors.fill: parent
                text: "input"
                color: "red"
                KeyNavigation.tab: in2
                selectByMouse: true
            }
        }
        Rectangle {
            width:60
            height: 26
            color: "green"
            TextInput {
                id: in2
                anchors.fill: parent
                text: "input"
                color: "red"

                KeyNavigation.tab: in1
                KeyNavigation.up: in1
            }
        }
        Loader {
            sourceComponent: testComponent
        }

    }
}

结果如图:

//---------------------------------------------------------

MainWindow CurrentThread = QThread(0x24ce850) //主线程

//---------------------------------------------------------

qml: button text: OK // 点击OK按钮打印

qml: button text: Cancle // 打开串口失败,取消OK按钮,默认Cancle按钮被点击打印

qml: serial return: false // serial.open(...)返回值打印

SerialPort CurrrntThread = QThread(0x24ce850) // serial.say() 函数运行的线程

//---------------------------------------------------------

SerialPort CurrrntThread = QThread(0xfcc9f0, name = "串口线程") // serial.sendMsg("TTTT")运行的线程

"TTTT" // 槽函数打印

//---------------------------------------------------------


相关推荐
矛取矛求2 小时前
QT的前景与互联网岗位发展
开发语言·qt
Leventure_轩先生2 小时前
[WASAPI]从Qt MultipleMedia来看WASAPI
开发语言·qt
晓纪同学11 小时前
QT-简单视觉框架代码
开发语言·qt
威桑11 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
飞飞-躺着更舒服11 小时前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
fyzy11 小时前
Qt获取本地计算的CPU温度
qt
cbdg375711 小时前
Qt 6 QML Settings location 不创建指定路径文件
qt
了一li11 小时前
Qt中的QProcess与Boost.Interprocess:实现多进程编程
服务器·数据库·qt
杨德杰11 小时前
QT网络(一):主机信息查询
网络·qt
黄金右肾12 小时前
Qt之串口设计-线程实现(十二)
qt·thread·serialport