QT5 QML-C++结合和相互作用:我做错了什么



我正在尝试了解如何在QML窗口上显示C++变量,以及如何处理C++属性或从那里调用C++函数。虽然我正在努力学习各种教程(其中大多数都链接到本网站的其他问题中),但我无法做到。。。。

"大计划"是,我希望有一个类UI_Updater,它将向QML公开我想要显示的所有数据,并让"真实"应用程序在下划线下工作(它将使用套接字或串行数据收集数据)。

现在,我只想显示3个整数,用定时器和/或几个菜单项来更改它们。这是我所有的代码和我得到的错误:

ui_updater.h

#ifndef UI_UPDATER_H
#define UI_UPDATER_H
#include <QObject>
#include <QtGui>
class UI_Updater : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int countEjT
               READ getcountEjT
               WRITE setcountEjT
               NOTIFY countEjTChanged
    )
    Q_PROPERTY(int countEjF
               READ getcountEjF
               WRITE setcountEjF
               NOTIFY countEjFChanged
    )
    Q_PROPERTY(int countEjFNC
               READ getcountEjFNC
               WRITE setcountEjFNC
               NOTIFY countEjFNCChanged
    )
public:
    explicit UI_Updater(QObject *parent = 0);
    int getcountEjT();
    int getcountEjF();
    int getcountEjFNC();
    void setcountEjT(int NewVal);
    void setcountEjF(int NewVal);
    void setcountEjFNC(int NewVal);
    Q_INVOKABLE void increment(int i);
signals:
    void countEjTChanged();
    void countEjFChanged();
    void countEjFNCChanged();
public slots:
    void testSlot();
private:
    int _countEjT;
    int _countEjF;
    int _countEjFNC;
    QTimer *myTimer;
    void OnTimeout();
};
#endif // UI_UPDATER_H

ui_updater.cpp

#include "ui_updater.h"
UI_Updater::UI_Updater(QObject *parent) :
    QObject(parent)
{
    myTimer = new QTimer(this);
    myTimer->start(1000);
    connect(myTimer, SIGNAL(timeout()), this, SLOT(testSlot()));
    _countEjT = _countEjF = _countEjFNC = 0;
    emit countEjTChanged();
    emit countEjFChanged();
    emit countEjFNCChanged();
}
void UI_Updater::setcountEjT(int NewVal)
{
    _countEjT = NewVal;
    emit countEjTChanged();
}
void UI_Updater::setcountEjF(int NewVal)
{
    _countEjF = NewVal;
    emit countEjFChanged();
}
void UI_Updater::setcountEjFNC(int NewVal)
{
    _countEjFNC = NewVal;
    emit countEjFNCChanged();
}

int UI_Updater::getcountEjT()
{
    return _countEjT;
}
int UI_Updater::getcountEjF()
{
    return _countEjF;
}
int UI_Updater::getcountEjFNC()
{
    return _countEjFNC;
}

void UI_Updater::OnTimeout()
{
    increment(0);
}
void UI_Updater::increment(int i)
{
    if (i==0) {
        ++_countEjT;
    }else{
        _countEjT+=i;
    }
    emit countEjTChanged();
    if (_countEjT%2 == 0) {
        ++_countEjF;
        emit countEjFChanged();
    }
    if (_countEjF%4 == 0) {
        ++_countEjFNC;
        emit countEjFNCChanged();
    }
}
void UI_Updater::testSlot()
{
    increment(2);
}

main.cpp

#include <QtGui/QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include <QtQuick/QQuickView>   // Necessario per QQuickWindow
#include "ui_updater.h"
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType<UI_Updater>("Phase.UI_Updater", 1, 0, "UI_Updater");
    QQmlApplicationEngine engine(QUrl("qrc:/qml/MainForm.qml"));
    QObject *topLevel = engine.rootObjects().value(0);
    QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
    if ( !window ) {
        qWarning("Error: Your root item has to be a Window.");
        return -1;
    }
    window->show(); // Evita di dover settare visible: true nel file qml
    return app.exec();
}

QML窗口应该有多个页面。我只复制相关的代码:

MainForm.qml

import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Window 2.1
import Phase.UI_Updater 1.0
ApplicationWindow {
    id: screen
    width: 480
    height: 272
    //toolBar: {
    //}
    property int partition: height / 3
    title: qsTr("Main Screen")
    menuBar: MenuBar {
        Menu {
            title: qsTr("File")
            MenuItem {
                text: qsTr("Exit")
                onTriggered: Qt.quit();
            }
        }
        Menu {
            title: qsTr("Pages")
            MenuItem {
                text: qsTr("Working")
                onTriggered: currentPage = "pagWorking";
            }
            MenuItem {
                text: qsTr("Graphics")
                onTriggered: currentPage = "pagGraphics";
            }
            MenuItem {
                text: qsTr("Setup")
                onTriggered: currentPage = "pagSetup";
            }
            // These items should increment the variables....
            MenuItem {
                text: qsTr("Add One")
                onTriggered: UI_Updater.countEjT = UI_Updater.countEjT + 1;
            }
            MenuItem {
                text: qsTr("Increment")
                onTriggered: UI_Updater.increment(1);
            }
        }
    }
    // GESTIONE PAGINE ---------------------------------------------------------
    property variant pagesList: [
        "pagWorking",
        "pagSetup",
        "pagGraphics"
    ];
    property string currentPage: "pagWorking";
    Repeater {
        model: pagesList;
        delegate: Loader {
            id: pageLoader
            x: 0
            y: 0
            anchors.rightMargin: 0
            anchors.bottomMargin: 0
            anchors.leftMargin: 0
            anchors.topMargin: 0
            active: false;
            asynchronous: true;
            anchors.fill: parent;
            visible: (currentPage === modelData);
            source: "%1.qml".arg(modelData);
            onVisibleChanged: { loadIfNotLoaded(); }
            Component.onCompleted: { loadIfNotLoaded(); }
            function loadIfNotLoaded() {
                // Carica la pagina la prima volta che ce n'è bisogno
                if (visible && !active) {
                    active = true;
                }
            }
        }   // Fine Loader
    }
    UI_Updater {
        countEjT: 0;
        countEjF: 0;
        countEjFNC: 0;
    }
    // Fine GESTIONE PAGINE ------------------------------------------------
}

pagWorking.qml

import QtQuick 2.0
import QtQuick.Controls 1.0
import Phase.UI_Updater 1.0
Rectangle {
    id: pagBackground
    width: 400
    height: 250
    gradient: Gradient {
        GradientStop {
            position: 0
            color: "#010036"
        }
        GradientStop {
            position: 1
            color: "#08006b"
        }
    }
    Label {
        id: lPagTitle
        x: 0
        width: parent.width
        height: 20
        color: "#0e909c"
        text: "Working"
        font.bold: true
        font.pointSize: 12
        verticalAlignment: Text.AlignVCenter
        horizontalAlignment: Text.AlignHCenter
        anchors.top: parent.top
        anchors.topMargin: 0
    }
    GroupBox {
        id: group_box1
        x: 133
        width: 120
        height: 100
        anchors.top: parent.top
        anchors.topMargin: 20
        anchors.horizontalCenter: parent.horizontalCenter
        Text {
            id: tTachimetro
            x: 162
            y: 50
            width: 100
            height: 30
            color: "#d0d0ff"
            text: qsTr("000.0°")
            anchors.verticalCenterOffset: 5
            anchors.verticalCenter: parent.verticalCenter
            font.bold: true
            style: Text.Normal
            verticalAlignment: Text.AlignVCenter
            font.pixelSize: 25
            anchors.horizontalCenter: parent.horizontalCenter
            horizontalAlignment: Text.AlignHCenter
        }
        Text {
            id: labTach
            x: 149
            y: 30
            width: 100
            height: 20
            color: "#a0a0ff"
            text: qsTr("Position")
            anchors.verticalCenterOffset: -20
            anchors.verticalCenter: parent.verticalCenter
            anchors.horizontalCenterOffset: 0
            verticalAlignment: Text.AlignVCenter
            font.pixelSize: 15
            anchors.horizontalCenter: parent.horizontalCenter
            horizontalAlignment: Text.AlignHCenter
        }
    }
    GroupBox {
        id: group_box2
        x: 204
        width: 200
        height: 74
        anchors.horizontalCenterOffset: 100
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.top: parent.top
        anchors.topMargin: 120
        Text {
            id: tET
            x: 147
            y: 0
            width: 110
            height: 20
            color: "#ff8000"
            text: UI_Updater.countEjT.toString();
            anchors.right: parent.right
            anchors.rightMargin: 0
            anchors.top: parent.top
            anchors.topMargin: 0
            font.bold: true
            style: Text.Normal
            verticalAlignment: Text.AlignVCenter
            font.pixelSize: 16
            horizontalAlignment: Text.AlignRight
        }
        Text {
            id: labET
            x: 11
            width: 70
            height: 20
            color: "#a0a0ff"
            text: qsTr("Ej T")
            anchors.top: parent.top
            anchors.topMargin: 0
            anchors.right: parent.right
            anchors.rightMargin: 110
            verticalAlignment: Text.AlignVCenter
            font.pixelSize: 16
            horizontalAlignment: Text.AlignRight
        }

        Text {
            id: tEF
            x: 130
            y: 21
            width: 110
            height: 20
            color: "#ff8000"
            text: UI_Updater.countEjF.toString();
            anchors.top: parent.top
            font.bold: true
            font.pixelSize: 16
            verticalAlignment: Text.AlignVCenter
            style: Text.Normal
            anchors.rightMargin: 0
            anchors.right: parent.right
            anchors.topMargin: 21
            horizontalAlignment: Text.AlignRight
        }
        Text {
            id: labEF
            x: 60
            y: 21
            width: 70
            height: 20
            color: "#a0a0ff"
            text: qsTr("Ej F")
            anchors.top: parent.top
            font.pixelSize: 16
            verticalAlignment: Text.AlignVCenter
            anchors.rightMargin: 110
            anchors.right: parent.right
            anchors.topMargin: 21
            horizontalAlignment: Text.AlignRight
        }
        Text {
            id: tENCF
            x: 130
            y: 40
            width: 110
            height: 20
            color: "#ff8000"
            text: UI_Updater.countEjFNC.toString();
            anchors.top: parent.top
            font.bold: true
            anchors.rightMargin: 0
            style: Text.Outline
            verticalAlignment: Text.AlignVCenter
            font.pixelSize: 16
            anchors.right: parent.right
            anchors.topMargin: 42
            horizontalAlignment: Text.AlignRight
        }
        Text {
            id: labENCF
            x: 60
            y: 40
            width: 70
            height: 20
            color: "#a0a0ff"
            text: qsTr("Ej FNC")
            anchors.top: parent.top
            anchors.rightMargin: 110
            verticalAlignment: Text.AlignVCenter
            font.pixelSize: 16
            anchors.right: parent.right
            anchors.topMargin: 42
            horizontalAlignment: Text.AlignRight
        }
    }
    property bool shown: false;
    state: "NASCOSTO";
    onVisibleChanged:  {
        if (visible === false)
            pagBackground.state = "NASCOSTO"
        else if (visible === true)
            pagBackground.state = "VISIBILE"
    }
    states: [
        State {
            name: "VISIBILE"
            PropertyChanges { target: pagBackground; opacity: 1 }
        }
        ,
        State {
            name: "NASCOSTO"
            PropertyChanges { target: pagBackground; opacity: 0 }
        }
    ]
    //! [states]
    //! [transitions]
        transitions: [
            Transition {
                to: "NASCOSTO"
                NumberAnimation { properties: "opacity"; duration: 1500; easing.type: Easing.OutExpo }
            }
            ,
            Transition {
                to: "VISIBILE"
                NumberAnimation { properties: "opacity"; duration: 1500; easing.type: Easing.OutExpo }
            }
        ]
    //! [transitions]
}

现在,它正在构建,但当我运行时,我得到:

类型错误:无法将方法"toString"调用为未定义的

并点击菜单项"增量i获取

类型错误:object[object object]没有方法"increment"

现在在我看来,我的对象UI_Updater并没有真正被隔离。。。。即使编辑看到了。

我该怎么办?

感谢

错误消息似乎很清楚,您不是在UI_Updater实例上调用increment,而是在UI_Updater类型上调用。

尝试在UI_Updater上放置一个id,然后可以调用UI_Updater C++类声明的方法。以下是MainForm.qml:中的一个小更新

import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Window 2.1
import Phase.UI_Updater 1.0
ApplicationWindow {
    id: screen
    width: 480
    height: 272
    //toolBar: {
    //}
    property int partition: height / 3
    title: qsTr("Main Screen")
    menuBar: MenuBar {
        Menu {
            title: qsTr("File")
            MenuItem {
                text: qsTr("Exit")
                onTriggered: Qt.quit();
            }
        }
        Menu {
            title: qsTr("Pages")
            MenuItem {
                text: qsTr("Working")
                onTriggered: currentPage = "pagWorking";
            }
            MenuItem {
                text: qsTr("Graphics")
                onTriggered: currentPage = "pagGraphics";
            }
            MenuItem {
                text: qsTr("Setup")
                onTriggered: currentPage = "pagSetup";
            }
            // These items should increment the variables....
            MenuItem {
                text: qsTr("Add One")
                onTriggered: updater.countEjT = updater.countEjT + 1;
            }
            MenuItem {
                text: qsTr("Increment")
                onTriggered: updater.increment(1);
            }
        }
    }
    // GESTIONE PAGINE ---------------------------------------------------------
    property variant pagesList: [
        "pagWorking",
        "pagSetup",
        "pagGraphics"
    ];
    property string currentPage: "pagWorking";
    Repeater {
        model: pagesList;
        delegate: Loader {
            id: pageLoader
            x: 0
            y: 0
            anchors.rightMargin: 0
            anchors.bottomMargin: 0
            anchors.leftMargin: 0
            anchors.topMargin: 0
            active: false;
            asynchronous: true;
            anchors.fill: parent;
            visible: (currentPage === modelData);
            source: "%1.qml".arg(modelData);
            onVisibleChanged: { loadIfNotLoaded(); }
            Component.onCompleted: { loadIfNotLoaded(); }
            function loadIfNotLoaded() {
                // Carica la pagina la prima volta che ce n'è bisogno
                if (visible && !active) {
                    active = true;
                }
            }
        }   // Fine Loader
    }
    UI_Updater {
        id: updater
        countEjT: 0;
        countEjF: 0;
        countEjFNC: 0;
    }
    // Fine GESTIONE PAGINE ------------------------------------------------
}

相关内容

  • 没有找到相关文章