• Qml使用cpp文件的信号槽



    一、C++文件Demo

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

    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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    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();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    QStringList SerialPort::availablePorts()
    {
        QStringList list;
        foreach(auto info, QSerialPortInfo::availablePorts()) list.append(info.portName());
        list<<"COM11"<<"COM22";
        return list;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    void SerialPort::close()
    {
        QMutexLocker locker(&m_mutex);
        if(m_port && m_port->isOpen()) m_port->close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    void SerialPort::say()
    {
        qDebug()<<"SerialPort CurrrntThread = "<< QThread::currentThread();
        qDebug()<<"---------------------------------------------------------";
        QString text = "2,8,k,1,0";
        tts->say(text);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    void SerialPort::sendMsgSlot(QString msg)
    {
        qDebug()<<"SerialPort CurrrntThread = "<< QThread::currentThread();
        qDebug()<<msg;
        qDebug()<<"---------------------------------------------------------";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    二、使用步骤

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

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

    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)));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.在qml中调用

    QGroupButton 自定义的按钮组

    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"}
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    signal slotOpenSerial(bool isOpen, string error)
    
    onSlotOpenSerial: {
        //console.log(isOpen, error)
        if(!isOpen)
        {
            group.btnIndexChanged = 1
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    qrc:/Form02.qml

    //自定义的按钮组
    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()
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

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

    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
            }
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    结果如图:
    //---------------------------------------------------------
    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” // 槽函数打印
    //---------------------------------------------------------

    在这里插入图片描述


  • 相关阅读:
    使用HTML制作静态网站:传统文化戏剧锡剧带psd设计图(2个页面)
    【测开求职】面试题:HR面相关的开放性问题
    JAVAEE初阶 操作系统
    Day40 代码随想录打卡|二叉树篇---完全二叉树的节点个数
    C++学习之运算符与表达式
    使用C#如何监控选定文件夹中文件的变动情况?
    【Python脚本进阶】2.1、端口扫描器(上):TCP全连接扫描
    大数据技术从业者注意了!使用代理IP时避开这些误区
    计算机组成原理 | 指令系统
    业务架构·应用架构·数据架构实战~业务驱动的数据架构设计
  • 原文地址:https://blog.csdn.net/qq_44084616/article/details/134523211