将C++和QML集成。Qt 5.4

8
我过去几个小时一直在阅读Qt文档,试图找出一种使用Qt Quick UI (QML)创建的UI与C++代码(函数等)进行通信(交互)的方法。
我已经阅读了这里的5到6个类似问题,但我有些困惑,不知道从哪里开始或者首先要做什么。如果有人能花时间列出所需步骤使其工作,我将不胜感激。
到目前为止,我尝试了... >添加新项目> C++类,但是失败了,并显示错误消息:"无法将一个或多个文件添加到项目中"。看起来文件(.cpp和.h)已经被创建,它们在其他项目文件所在的文件夹中,但未包含在项目中。我想做的只是像通过C++函数或任何其他可能的方式更改textedit的文本这样简单的事情。
//Test.qml (main.qml)
    import QtQuick 2.1
    import QtQuick.Window 2.0

Rectangle {
     id: rootRect
    width: Screen.width/2
    height: Screen.height/2
    color: "gray"


    Button{}

    Rectangle{
        id: textField
        width: 120
        height: 40
        color: "white"
        x:274; y: 61
        border.color: "blue"
        border.width: 4
        radius: 2

    }

    TextEdit {

        id: display
        x: 274
        y: 61
        width: 80
        height: 20
        text: qsTr("Text Edit")
        font.pixelSize: 22
        color: "black"
        anchors.centerIn: textField

    }

    Rectangle{
        id: inputField
        width: textField.width
        height: textField.height
        border.color: "green"
        border.width: 3
        color: "white"
        x: 140; y: 61
    }

    TextEdit{
        id: input
        color: "red"
        font.pixelSize: 30
        anchors.centerIn: inputField
        text: "Some Text"


    }

}

//Button.cpl

import QtQuick 2.0
import QtQuick.Window 2.0


Item {

    property string defaultText: "New Text"


    Rectangle{
    id: button
    width: rootRect.width/6
    height: rootRect.height/8
    color: "black"
    x: 200; y: 200
    radius: 10

    }

    MouseArea{
        id: buttonClickArea
        width: 0
        anchors.rightMargin: 0
        anchors.bottomMargin: 0
        anchors.fill: button

        onClicked: {

                display.text = defaultText
        }
    }

}

感谢您抽出时间阅读本文和/或任何回复。

2
我没有看到任何编写C++部分的尝试。至于你的错误 - 看起来你试图将C++类文件添加到“Qt Quick UI”项目中。这种类型的项目仅包含QML部分,并使用qmlscene实用程序运行。你需要的是“Qt Quick Application”。创建项目后,您将获得一个可用于QML和C++文件的项目。因此,现在您可以将C++类添加到项目中。请参阅文档以了解如何将C++插件集成到QML中。 - folibis
2
顺便提一下,在QtQuick.Controls 1.3中已经有了Button项目。 - folibis
1
基本上就是@folibis所说的:新建文件或项目...>Qt Quick应用程序。在那里,您可以使用QML和C++类。您在其他答案中找到的代码可以复制到这些源文件中。 - BaCaRoZzo
@BaCaRoZzo和filibis。感谢你们的评论。看起来我想学习的那个人忘了提到要集成C++,我们需要创建一个Qt Quick应用程序,因为他所有其他项目都是Qt Quick UI(纯QML)起步的。folibis,我的C++代码已准备好,只是在尝试找到一种连接它与UI的方法。至于文档,我觉得它非常混乱......例如,在两个相似的示例中,包含了不同的“东西”……等等。我想我必须从头开始挖掘文档。 - hekri
1
如果您能够将这两个示例联系起来,我们可以尝试帮助您并/或指向不同或更详细的示例。 :) - BaCaRoZzo
@BaCaRoZzo 非常感谢。我已经解决了这个问题,但是又遇到了另一个问题。如果您能看一下就好了。 :) http://stackoverflow.com/questions/27473173/what-to-include-to-make-this-qt-project-work - hekri
1个回答

17

使用Qt 5.4.0和Qt Creator 3.3.0创建新项目:

  1. 点击“新建项目”
  2. 选择“Qt Quick 应用程序”
  3. 点击“选择…”
  4. 命名您的项目并选择放置位置
  5. 点击“下一步”
  6. 从下拉菜单中选择“Qt Quick 2.4”
  7. 点击“下一步”
  8. 选择所需的Kit(如果有)
  9. 点击“下一步”
  10. 点击“完成”

现在,您应该看到打开了包含以下代码的main.qml文件:

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    visible: true
    MainForm {
        anchors.fill: parent
        mouseArea.onClicked: {
            Qt.quit();
        }

    }
}
将其改为:
import QtQuick 2.4
import QtQuick.Window 2.2

//### New Code ###

import QtQuick.Controls 1.3

//################

Window {
    id: window1
    visible: true

    //### New Code ###

    width: 400
    height: 500

    TextArea {
        id: textArea
        readOnly: true
        anchors.bottom: textInput.top
        anchors.bottomMargin: 6
        anchors.right: parent.right
        anchors.rightMargin: 8
        anchors.left: parent.left
        anchors.leftMargin: 7
        anchors.top: parent.top
        anchors.topMargin: 7
    }

    TextField {
        id: textInput
        y: 470
        height: 23
        anchors.right: sendButton.left
        anchors.rightMargin: 6
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 7
        anchors.left: parent.left
        anchors.leftMargin: 7
    }

    Button {
        id: sendButton
        x: 328
        y: 470
        width: 64
        height: 23
        text: qsTr("Send")
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 7
        anchors.right: parent.right
        anchors.rightMargin: 8

        onClicked: {
            CppClass.sendMessage(textInput.text, textArea);
            textInput.text = "";
        }
    }

    //################
}

将C++类添加到您的项目中:

  1. 在项目查看器中,右键单击项目名称
  2. 点击"Add New..."
  3. 如果没有选择C++类,请选择C++类
  4. 点击"Choose..."
  5. 在"class name"字段中输入"CppClass"
  6. 将基类设置为QObject
  7. 点击"下一步"
  8. 点击"完成"

打开cppclass.h并将它更改为:

#ifndef CPPCLASS_H
#define CPPCLASS_H

#include <QObject>

//### New Code ###

#include <QQuickItem>
#include <QQuickTextDocument>
#include <QTextDocument>

//################

class CppClass : public QObject
{
    Q_OBJECT
public:
    explicit CppClass(QObject *parent = 0);
    ~CppClass();

    //### New Code ###

    Q_INVOKABLE void sendMessage(const QString &msg, QQuickItem *textArea);

    //################

signals:

public slots:
};

#endif // CPPCLASS_H
请打开cppclass.cpp并将其更改为:
#include "cppclass.h"

CppClass::CppClass(QObject *parent) : QObject(parent)
{

}

CppClass::~CppClass()
{

}
//### New Code ###

void CppClass::sendMessage(const QString &msg, QQuickItem *textArea)
{
    QTextDocument *textDocument = textArea->property("textDocument").value<QQuickTextDocument*>()->textDocument();

    textDocument->setHtml(textDocument->toHtml() + "\n<b>Text sent to Cpp side:</b> <i>" + msg + "</i>");
}

//################
打开 main.cpp 并将其更改为:
#include <QGuiApplication>
#include <QQmlApplicationEngine>

//### New Code ###

#include <QQmlContext>

#include "cppclass.h"

//################

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

    QQmlApplicationEngine engine;

    //### New Code ###

    CppClass cppClass;

    engine.rootContext()->setContextProperty("CppClass", &cppClass);

    //################

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

运行你的应用程序,输入一些文本到输入框中,然后点击发送按钮。


针对Dynamic Remo的评论,这里介绍另一种QML和C++通信的方法。该方法基于C++发出信号,QML作出响应。以下是让它工作的代码。


cppclass.h

#ifndef CPPCLASS_H
#define CPPCLASS_H

#include <QObject>

#include <QDateTime>

class CppClass : public QObject
{
    Q_OBJECT
public:
    explicit CppClass(QObject *parent = 0);
    ~CppClass();

    Q_INVOKABLE void getCurrentTime();

signals:
    void timeUpdate(QString currentTime);

public slots:
};

#endif // CPPCLASS_H

cppclass.cpp

#include "cppclass.h"

CppClass::CppClass(QObject *parent) : QObject(parent)
{

}

CppClass::~CppClass()
{

}

void CppClass::getCurrentTime()
{
    emit timeUpdate(QDateTime::currentDateTime().toString("ddd dd MMMM yyyy hh:mm:ss.zzz"));
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include <QQmlContext>

#include "cppclass.h"

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

    CppClass cppClass;

    QQmlApplicationEngine engine;

    engine.rootContext()->setContextProperty("CppClass", &cppClass);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

main.qml:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls 1.2

Window {
    id: rootWindow
    width: 400
    height: 400
    visible: true

    Connections {
        target: CppClass

        onTimeUpdate: {
            initailizeDllMsg.text = currentTime
        }
    }

    Text {
        id: initailizeDllMsg
        text: qsTr("{current time placeholder}")
        font.pointSize: 14
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
    }

    Button {
        id: button1
        x: 163
        y: 357
        text: qsTr("Show current time")
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 20
        anchors.horizontalCenter: parent.horizontalCenter

        onClicked: CppClass.getCurrentTime()
    }
}

这很有帮助 :) 我可以理解从TextField访问TextArea并设置文本。您能否指导我如何更改QML TEXT的文本? 谢谢! Text { id: initailizeDllMsg text: initailize_lbl } - Dynamic Remo
@DynamicRemo,我已经更新了我的答案,展示了如何实现您想要的。 - Maz T
非常感谢你,你救了我的一天。 - HosSeinM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接