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" // 槽函数打印

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


相关推荐
huanggang9821 小时前
在Ubuntu22.04上使用Qt Creator开发ROS2项目
qt·ros2
老秦包你会2 小时前
Qt第三课 ----------容器类控件
开发语言·qt
spygg3 小时前
Qt低版本多网卡组播bug
qt·组播·多网卡组播·qt5.7.0
码农客栈4 小时前
qt QWebSocketServer详解
qt
plmm烟酒僧5 小时前
Windows下QT调用MinGW编译的OpenCV
开发语言·windows·qt·opencv
Black_Friend5 小时前
关于在VS中使用Qt不同版本报错的问题
开发语言·qt
CSUC5 小时前
【Qt】QTreeView 和 QStandardItemModel的关系
qt
冷凝女子6 小时前
【QT】海康视频及openCv抓拍正脸接口
qt·opencv·音视频·海康
苏三有春8 小时前
PyQt5实战——UTF-8编码器功能的实现(六)
开发语言·qt
Vanranrr9 小时前
C++ QT
java·c++·qt