Qt : Can't update QQuickWidget from outside MainWindow - c++

I have been trying to fix this issue for 2 days now.I have a gmaps QML project , which I've Integrated into my Qt widgets project using the following code:
gmap locator;
ui->quickWidget->setSource(QUrl::fromLocalFile("/maps/main.qml"));
ui->quickWidget->rootContext()->setContextProperty("gmap",&locator);
ui->quickWidget->show();
When I set the location on the map from the MainWindow using
locator.setData( "28.6082819", "77.0350079");
It works as expected , however , when I add a toolbutton and do the same thing from its slot , it doesn't work.I've connected it to a custom slot in my MainWindow like this:
connect(ui->toolButton_5, SIGNAL(clicked()), this, SLOT(plotmap(QString(ui->lineEdit_3->text()),QString(ui->lineEdit_4->text()),&locator,&ui->quickWidget)));
and here's the custom slot:
void MainWindow::plotmap(QString lat , QString lon, gmap *loc,QQuickWidget *view)
{
loc->setData("02.60","77.04");
view->show();
view->update();
}
Here's my qml files
gmap.cpp
#include "gmap.h"
gmap::gmap()
{
}
void gmap::setData(QString lat,QString lang)
{
qDebug(lat.toLatin1());
emit getLat(lat.toDouble());
emit getLang(lang.toDouble());
}
gmap.h
#ifndef GMAP_H
#define GMAP_H
#include <QObject>
class gmap : public QObject
{
Q_OBJECT
public:
gmap();
signals:
void getLat(double lat);
void getLang(double lang);
public slots:
void setData(QString lat,QString lang);
};
#endif // GMAP_H
main.qml
import QtQuick 2.6
import QtQuick.Window 2.2;
import QtPositioning 5.6;
import QtLocation 5.9
import Qt3D.Input 2.1
import QtQuick.Controls 2.2;
Window {
width: Qt.platform.os == "android" ? Screen.width : 512
height: Qt.platform.os == "android" ? Screen.height : 512
visible: true
Plugin {
id: mapPlugin
name: "osm"
PluginParameter {
name: 'osm.mapping.highdpi_tiles'
value: !!1 }
}
Connections{
target: gmap
onGetLat : mapmarker.center.latitude = lat
}
Connections{
target: gmap
onGetLang : mapmarker.center.longitude = lang
}
Connections{
target: gmap
onGetLang : map.center = QtPositioning.coordinate(mapmarker.center.latitude,mapmarker.center.longitude,150);
}
Map {
id: map
anchors.fill: parent
anchors.rightMargin: -15
anchors.bottomMargin: -10
anchors.leftMargin: 15
anchors.topMargin: 10
plugin: mapPlugin
center: QtPositioning.coordinate() // NSUT
zoomLevel: 14
activeMapType: supportedMapTypes[2]
Button {
x: 389
y: 445
text: "ADD MARKER"
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: 27
anchors.rightMargin: 23
padding: 7
onClicked: gmap.setData(textField.text,textField1.text)
}
MapCircle {
id: mapmarker
center {
latitude: 28.6078
longitude: 77.0406
}
radius: 50.0
color: 'green'
border.width: 3
}
TextField {
id: textField
x: 176
y: 397
text: qsTr("")
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: 75
anchors.rightMargin: 136
}
TextField {
id: textField1
x: 176
y: 445
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: 27
anchors.rightMargin: 136
font.hintingPreference: Font.PreferDefaultHinting
}
}
}
The map in my QQuickWidget doesn't update.What could I be doing wrong , please let me know.

AFAIK your connect syntax is wrong.
Store locator as a member somewhere, in MainWindow for example:
public:
void setLocator(gmap* loc) { m_locator = loc; }
private:
gmap* m_locator;
Add a slot to MainWindow:
private slot:
plotmapFromLineEdits() { plotmap(ui->lineEdit_3->text(), ui->lineEdit_4->text(), m_locator, ui->quickWidget); }
and connect it like this:
connect(ui->toolButton_5, SIGNAL(clicked()), this, SLOT(plotmapFromLineEdits()));
Or in C++11 or above you can connect without defining a slot by using lambda:
connect(ui->toolButton_5, SIGNAL(clicked()), [&](){plotmap(ui->lineEdit_3->text(), ui->lineEdit_4->text(), m_locator, ui->quickWidget);}));
I don't think you have to show and update QQuickWidget every time. Just delete the quickwidget parameter.
Lastly please make sure your class names start with an uppercase letter:
gmap => GMap

Related

Problem integrating QML project into C++ code

I don't know a lot about qt so please bear with me.
I have a qt widgets application that I made as a part of a project , a friend has a Qt quick applications project which I'd like to integrate into my qt widgets app.This is what I've added in my mainwindow.cpp
QQuickView *view = new QQuickView();
QWidget *container = QWidget::createWindowContainer(view, this);
container->setMinimumSize(300, 200);
container->setMaximumSize(600, 400);
view->setSource(QUrl("/maps/main.qml")); file.
ui->qmlwidget->addWidget(container);
However , the integration doesn't work correctly.The qt quick project is a map which takes coordinates as inputs and then points them on the map.It works as expected when it is run standalone but when I integrate it using the above method , clicking the button which is supposed to point out the location does nothing.This is the Qt quick app code:
gmap.cpp
#include "gmap.h"
gmap::gmap()
{
}
void gmap::setData(QString lat,QString lang)
{
qDebug(lat.toLatin1());
emit getLat(lat.toDouble());
emit getLang(lang.toDouble());
}
gmap.h
#ifndef GMAP_H
#define GMAP_H
#include <QObject>
class gmap : public QObject
{
Q_OBJECT
public:
gmap();
signals:
void getLat(double lat);
void getLang(double lang);
public slots:
void setData(QString lat,QString lang);
};
#endif // GMAP_H
main.qml
import QtQuick 2.6
import QtQuick.Window 2.2;
import QtPositioning 5.6;
import QtLocation 5.9
import Qt3D.Input 2.1
import QtQuick.Controls 2.2;
Window {
width: Qt.platform.os == "android" ? Screen.width : 512
height: Qt.platform.os == "android" ? Screen.height : 512
visible: true
Plugin {
id: mapPlugin
name: "osm"
PluginParameter {
name: 'osm.mapping.highdpi_tiles'
value: !!1 }
}
Connections{
target: gmap
onGetLat : mapmarker.center.latitude = lat
}
Connections{
target: gmap
onGetLang : mapmarker.center.longitude = lang
}
Connections{
target: gmap
onGetLang : map.center = QtPositioning.coordinate(mapmarker.center.latitude,mapmarker.center.longitude,150);
}
Map {
id: map
anchors.fill: parent
anchors.rightMargin: -15
anchors.bottomMargin: -10
anchors.leftMargin: 15
anchors.topMargin: 10
plugin: mapPlugin
center: QtPositioning.coordinate() // NSUT
zoomLevel: 14
activeMapType: supportedMapTypes[2]
Button {
x: 389
y: 445
text: "ADD MARKER"
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: 27
anchors.rightMargin: 23
padding: 7
onClicked: gmap.setData(textField.text,textField1.text)
}
MapCircle {
id: mapmarker
center {
latitude: 28.6078
longitude: 77.0406
}
radius: 50.0
color: 'green'
border.width: 3
}
TextField {
id: textField
x: 176
y: 397
text: qsTr("")
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: 75
anchors.rightMargin: 136
}
TextField {
id: textField1
x: 176
y: 445
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: 27
anchors.rightMargin: 136
font.hintingPreference: Font.PreferDefaultHinting
}
}
}
in your qml side,there is no item that was named to gmap. you must first add a gmap object to rootContext
gmap newGmap;
view->rootContext()->setContextProperty("gmap", &newGmap);

FileDialog in Qml not working in Release

I am working on project with Qt Quick Control 2.
When I try to run my software in debug mode FileDialog.qml opens perfectly but when I deploy it as release mode it doesn't work.
Here is my code:
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls 1.3
import QtQuick.Dialogs 1.0
// File Dialog to browse
FileDialog {
id: openDialog
title: "Please Select An Image"
folder: shortcuts.pictures
nameFilters: ["Image files (*.BMP)"]
modality: Qt.NonModal
selectExisting: true
/*
* do my stuff
*/
}
Here it is my Js function that calls FileBrowse.qml (file in parameters).
I call this function in other view like this :
JsCommonCall.openFileDialog("frameFileBrowse.qml",2)
function openFileDialog(file,
parentCalled) {
_component = Qt.createComponent(file);
_popUp = _component.createObject(windowsMain, {"x": offsetPopUpCreate,
"y": offsetPopUpCreate,
"parentCall":parentCalled});
if(_popUp !== null)
_popUp.open()
}
here it is my FileBrowse
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.0
// File Dialog to browse
FileDialog {
id: openDialog
title: "Please Select An Image"
folder: shortcuts.home
nameFilters: ["Image files (*.BMP)"]
selectFolder: true
// variables
property int parentCall;
onAccepted: {
imgCurrentCam1.source = openDialog.fileUrl;
openDialog.close()
}
onRejected: {
openDialog.close()
}
}
This is working for me
FileDialog {
id: fdExport
title: qsTr("File name")
folder: shortcuts.home
selectFolder: true
onAccepted: {
}
}
and to run
fdExport.open()
Please try to leave
modality: Qt.NonModal
from your code.
I don't know which is the problem but the code below is perfectly portable on Windows machines. Tested in Linux too.
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
FileDialog {
id: fdImport
title: qsTr("File name")
folder: shortcuts.home
onAccepted: {
textEdit.text= fdImport.fileUrls[0]
}
}
Rectangle {
id: rectangle
color: "#ffffff"
anchors.fill: parent
Rectangle {
id: rectangle1
color: "#ffffff"
anchors.right: parent.right
anchors.rightMargin: 8
anchors.left: parent.left
anchors.leftMargin: 8
anchors.bottom: rectangle2.top
anchors.bottomMargin: 6
anchors.top: parent.top
anchors.topMargin: 8
TextEdit {
id: textEdit
text: qsTr("Text Edit")
anchors.fill: parent
font.pixelSize: 12
}
}
Rectangle {
id: rectangle2
y: 441
width: 128
height: 32
color: "#ffffff"
anchors.left: parent.left
anchors.leftMargin: 8
anchors.bottom: parent.bottom
anchors.bottomMargin: 7
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: {
fdImport.open()
}
Text {
id: text1
text: qsTr("Click me!")
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors.fill: parent
font.pixelSize: 12
}
}
}
}
}
The qt.conf file
[Paths]
Plugins=plugins
Libraries=libs
Please remember to copy all the dll (release) in the executable folder, with the qml and plugins folders.
One strange but possible reason for it is anti-virus: my FileDialog isn't opening either, and the entire QML application is hanging, while the AV is active.

Integrate C++ and QML. Qt 5.4

I was reading the Qt documentation for the past couple of hours trying to figure out a way to make a UI created with Qt Quick UI (QML) communicate (interact) with C++ code (functions... etc.).
I've read the 5 or 6 similar questions on here to but I'm kind of confused, I have problems figuring out where to start or what to do first.
I'd appreciate it a lot if someone could take the time and list the steps needed to make this work.
What i've done so far. I tried doing ...>add new Item> C++ class but I failed with an error saying:" failed to add one or more files to project"> It seems like the files (.. .cpp and .h) are created, they were in the folder where the other project files were but not included in the project.
What I wanna do is just something simple like changing the text of the textedit through a C++ function or any other way possible.
//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
}
}
}
Thank you for taking the time to read this and/or any replies.
Using Qt 5.4.0 and Qt Creator 3.3.0, create New Project:
Click New Project
Qt Quick Application
Click Choose...
Name the project and select where to place it
Click Next
Select Qt Quick 2.4 from the drop-down menu
Click Next
Select desired Kit(s)
Click Next
Click Finish
Now You should see open main.qml file with following code:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
visible: true
MainForm {
anchors.fill: parent
mouseArea.onClicked: {
Qt.quit();
}
}
}
Change it to:
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 = "";
}
}
//################
}
Add C++ Class to Your project:
Right Mouse Click project name in Projects viewer
Click Add New...
Select C++ Class if not already selected
Click Choose...
In Class name filed enter "CppClass"
Set Base class to QObject
Click Next
Click Finish
Open cppclass.h and change it to:
#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
Open cppclass.cpp and change it to:
#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>");
}
//################
Open main.cpp and change it to:
#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();
}
Run Your application, type some text to Input Field and click send.
In response to Dynamic Remo comment here's another way to have QML and C++ communicate. This approach is based on C++ emitting a signal and QML acting upon it. Following is the code to get it working.
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()
}
}

QML - How to send/pass variable from one qml file to other qml file

How to send a variable, or signal between qml files ?
http://i.stack.imgur.com/MChCG.png
Mainwindow -> create a component Item2.qml
MainWindow -> create a component item1.qml
item1.qml -> create a component Item3.qml
Item3.qml -> change/send variable or signal to ItemII.qml(is created in mainwindow) - How ?
Someone could write a small example ?
Example code:
Item1.qml
//Item 1
import QtQuick 2.1
Rectangle {
width: 200
height: 100
color:"red"
Text{
anchors.centerIn: parent
font.pixelSize: 16
text:"Item1"
width:parent.width
horizontalAlignment: Text.AlignRight
color:"white"
}
}
Item2.qml
//Item 2
import QtQuick 2.1
Rectangle {
width: 100
height: 100
color:"blue"
Text{
anchors.centerIn: parent
font.pixelSize: 16
text:"Item2"
color:"white"
}
}
Item3.qml
//Item 3
import QtQuick 2.1
Rectangle {
id:item3
width: item3Area.pressed?90:100
height: item3Area.pressed?90:100
color:"green"
signal superAwesomeSignal(string txt)
Text{
anchors.centerIn: parent
font.pixelSize: 16
text:"Item3"
color:"white"
}
MouseArea{
id:item3Area
anchors.fill: parent
onClicked:item3.superAwesomeSignal("Hello, from Item 3 ")
}
}
Main.qml
//Main.qml
import QtQuick 2.0
Rectangle {
width: 360
height: 360
Item1{
anchors.top: parent.top
anchors.left: parent.left
Item3{
id:item3
anchors.top: parent.top
onSuperAwesomeSignal: item2.item3SignalReceived(txt)
}
}
Item2{
id:item2
anchors.bottom: parent.bottom
signal item3SignalReceived(string txt)
onItem3SignalReceived:console.debug(txt)
}
}

QT5 QML-C++ binding and interaction: what am i doing wrong?

I am trying to get how to show C++ variables on a QML window, and also how to hande C++ properties or call C++ functions from there.
While i'm trying to follow various tutorials (most of them linked in other questions at this site) i can't get it work....
The "big plan" is that i would like to have a class UI_Updater which will expose to the QML all the data i want to show, and have the "real" app working underline (it will gather data using a socket or a serial).
Right now, all i want is to show 3 integers, changing them with a timer and/or by a couple of menu items.
This is all my code and the errors i get:
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();
}
The QML windows is meant to have multiple pages. I'll copy the code only of the relevant one:
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]
}
Now, it builds, but when i run i get:
TypeError: Cannot call method 'toString' to undefned
and clicking on the menu item "Increment i get
TypeError: object [object Object] has no method 'increment'
Now seems to me that my object UI_Updater was'nt really istanciated.... even if the editor sees it.
What should i do?
Thanks
The error message seem quite clear, you are not invoking increment on an UI_Updater instance but on UI_Updater type.
Try to put an id on your UI_Updater, then you can call methods declare by your UI_Updater C++ class. Here a little update in your 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 ------------------------------------------------
}