QML/QtQuick 和 QWidget 之间的双向连接

Two way connection between QML/QtQuick and QWidget

我正在尝试制作一个可以使用 QSerialPort 和 QtQuick 的应用程序,因此我需要以某种方式将类似桌面的应用程序连接到 QML。 我设法(好的,我复制并做了一些更改)将信息从 QML 发送到 main.cpp,但我无法以其他方式发送任何内容。 想要的效果是从 .cpp 管理所有内容,添加和删除 ListElements 并发送参数以绘制图形。

main.cpp
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QQuickView view(QUrl::fromLocalFile("path/main.qml"));
    QObject *item = view.rootObject();
    MyClass myClass,mySecondClass;
    QObject::connect(item, SIGNAL(qmlSignal(QVariant)),
                     &myClass, SLOT(cppSlot(QVariant)));
    QObject::connect(&myClass, SIGNAL(Nazwa(QVariant)),
                     item, SLOT(onNazwa(QVariant)));
    QVariant c=200;
    emit myClass.Nazwa(c);

    view.show();
    return app.exec();
}

myclass.h

#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
#include <QDebug>
#include <QQuickItem>
class MyClass : public QObject
{
    Q_OBJECT
public:
    explicit MyClass(QObject *parent = 0);

signals:
    void Nazwa(QVariant a);

public slots:
    void cppSlot(const QVariant &v) {
       qDebug() << "QVariant :):" << v;

       QQuickItem *item =
           qobject_cast<QQuickItem*>(v.value<QObject*>());
       qDebug() << "Wymiary:" << item->width()
                << item->height();
    }

};

#endif // MYCLASS_H

main.qml

import QtQuick.Window 2.0
import QtQuick 2.0

Item {
    id: item
    width: 100; height: 100
//    Item{
//        id: item2
//        onNazwa: {    }
//    }
    signal qmlSignal(var anObject)
    MouseArea {
        anchors.fill: parent
        onClicked: {
            parent.width=200;
            item.qmlSignal(item)
        }
    }
}

此外,对 main.qml 的任何更改都会中断第一个连接,我什至不知道为什么。你能给我一些建议或例子吗?我在 Qt 文档上花了第二天,但我仍然做不到:(

您可以在 qml 上设置 属性 并对它的变化做出反应。

main.qml

Item {
    id: item
    property alias nazwa: item2.nazwa

    Item{
        id: item2
        property var nazwa: null
        onNazwaChanged: {} 
    }
}

以及 main.cpp

QQmlProperty::write(item, "nazwa", 10);

或者,您可以直接从 c++ 调用方法到 qml。

一切都解释得很好here

好的。我明白你想要什么,但我建议你通过 engine 方式。试试下面的代码。我用了很简单的例子只是为了展示如何,仅此而已。

MyClass.H:

#include <QObject>
#include <QSerialPort>

class MyClass : public QObject
{
    Q_OBJECT
    QSerialPort *_port;
public:
    explicit MyClass(QObject *parent = 0);

signals:
    void sendData(const QString &data);

public slots:
    void startCom(const QString &name, int baud);
    void read();
    void writeData(const QByteArray &data = QByteArray("data"));
};

MyClass.CPP:

MyClass::MyClass(QObject *parent) : QObject(parent)
{
}

void MyClass::startCom(const QString &name, int baud)
{
    _port = new QSerialPort(name, this);
    _port->setBaudRate(baud);
    if(_port->open(QIODevice::ReadWrite))
        connect(_port, &QSerialPort::readyRead, this, &MyClass::read);
    else
        emit sendData(tr("Error"));
}

void MyClass::read()
{
    emit sendData(QString::fromStdString(_port->readAll().toStdString()));
}

void MyClass::writeData(const QByteArray &data)
{
    _port->write(data);
}

main.cpp:

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType<MyClass>("com.some.myclass", 1, 0, "MyClass");
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

main.qml:

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
import com.some.myclass 1.0

Window {
    id: root
    signal startPort(string name, int baud)
    width: 640
    height: 480
    ColumnLayout {
        id: colLay
        TextField {
            id: comName
            placeholderText: qsTr("COM-port name")
        }
        ComboBox {
            id: baud
            model: [ 9600, 19200, 115200 ]
        }
        Button {
            id: portBut
            text: qsTr("Start serial")
            onClicked: root.startPort(comName.text, baud.currentText)
        }
        Button {
            id: sendBut
            text: qsTr("Write data")
            onClicked: comClass.writeData
        }
        Label {
            id: dataLbl
            text: qsTr("No data")
        }
    }
    MyClass {
        id: comClass
        onSendData: dataLbl.text = data
    }

    onStartPort: comClass.startCom(name, baud)

    Component.onCompleted: root.show();
}