我正在尝试了解如何在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 ------------------------------------------------
}