PDA

View Full Version : pass data between qt controls (slider) and C++ application



sajis997
31st December 2014, 08:29
Hello ,

I am facing some confusion regarding passing data between the qt qick slider and QQuickItem object in C++, that results in application crash. I have the following class with the defined properties:



class TessellationSceneItem : public QQuickItem
{
Q_OBJECT
//the property defintion must be at the top of the class
//the notify signal is needed for correct property bindings
Q_PROPERTY(float outer READ outer WRITE setOuter NOTIFY outerChanged)
Q_PROPERTY(float inner READ inner WRITE setInner NOTIFY innerChanged)
Q_PROPERTY(float maxPatchVertices READ maxPatchVertices NOTIFY maxPatchVerticesChanged)

public:
TessellationSceneItem();

void setOuter(float);
void setInner(float);

float inner();
float outer();

float maxPatchVertices() const;

signals:
void innerChanged();
void outerChanged();
void maxPatchVerticesChanged();
.............
............
private:

TeapotTessellation* mTessScene;

QTime mTIme;

};



The definition of the setter and getter methods:



void TessellationSceneItem::setOuter(float outerFactor)
{
if(outerFactor == mTessScene->outerTessellationFactor())
return;

mTessScene->setOuterTessellationFactor(outerFactor);
//do not emit notifier if value does not actually change
emit outerChanged();
}

void TessellationSceneItem::setInner(float innerFactor)
{
if(innerFactor == mTessScene->innerTessellationFactor())
return;

mTessScene->setInnerTessellationFactor(innerFactor);
emit innerChanged();
}

float TessellationSceneItem::inner()
{
return (float)(mTessScene->innerTessellationFactor());
}

float TessellationSceneItem::outer()
{
return (float)(mTessScene->outerTessellationFactor());
}

float TessellationSceneItem::maxPatchVertices() const
{
return (float) (mTessScene->getMaxPatchVertices());
}


The idea is to have the slider value loaded with the value set in the underlying C++ application. Then with every slider interaction , the underlying value( outer, inner) in the C++ side will be updated. I tried the following in the .qml file , but the application crashes.



import QtQuick 2.0
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import TeapotTessellation 1.0

Item {
id: root
width: 512; height: 512


TessellationSceneItem
{
id: tessSceneItem
// outer: outerTessellationSlider.value
// inner: innerTessellationSlider.value
}

GridLayout {
id: controlLayout
columns: 2

Text {
id: outerTessellationText
text: qsTr("Outer Tess. Factor: ")
color: "black"
opacity: 1.0
}

Slider {
id: outerTessellationSlider
opacity: 1.0
// value: tessSceneItem.outer
minimumValue: 1.0
maximumValue: 64//tessSceneItem.maxPatchVertices
stepSize: 1.0
Layout.fillWidth: true
}


Text {
id: innerTessellationText
text: qsTr("Inner Tess. Factor: ")
color: "black"
opacity: 1.0
}



Slider {
id: innerTessellationSlider
opacity: 1.0
// value: tessSceneItem.inner
minimumValue: 1.0
maximumValue: 64.0//tessSceneItem.maxPatchVertices
stepSize: 1.0
Layout.fillWidth: true
}
}


Rectangle {
id: rect
color: "red"
radius: 10
opacity: 0.1
border.color: "black"
anchors.fill: controlLayout
}
}



The commented part of the .qml file are the places that cause the application crash. Any hint ?

Thanks

anda_skoa
31st December 2014, 12:37
Did the crash backtrace contain any information on where it crashes?
Does it work when you assign fixed values in QML?
DId you try with having matching types for your properties and the slider's value property?

Cheers,
_

sajis997
31st December 2014, 15:43
Did the crash backtrace contain any information on where it crashes?

It depends which of the propetties I am working with. For example I am working with the follwoing property:


Q_PROPERTY(float inner READ inner WRITE setInner NOTIFY innerChanged)

Then inside the .qml file I have the following snippet:



TessellationSceneItem
{
id: tessSceneItem

inner: 10
}


I get the crashing point while running with debugger at the following points:



void TessellationSceneItem::setInner(float innerFactor)
{
if(innerFactor == mTessScene->innerTessellationFactor())
return;

mTessScene->setInnerTessellationFactor(innerFactor);
emit innerChanged();
}

..............................
..............................

GLfloat TeapotTessellation::innerTessellationFactor()
{
return mInnerTessellationFactor;
}




Does it work when you assign fixed values in QML?

The issue prevails.


DId you try with having matching types for your properties and the slider's value property?

I did not understand this part.

Thanks

anda_skoa
1st January 2015, 14:57
I get the crashing point while running with debugger at the following points:



void TessellationSceneItem::setInner(float innerFactor)
{
if(innerFactor == mTessScene->innerTessellationFactor())
return;

mTessScene->setInnerTessellationFactor(innerFactor);
emit innerChanged();
}

..............................
..............................

GLfloat TeapotTessellation::innerTessellationFactor()
{
return mInnerTessellationFactor;
}



You forgot to mark the line where the crash happens.



I did not understand this part.

Your properties have a different type (float) than the slider's value property (qreal).

Cheers,
_

sajis997
1st January 2015, 15:45
The issue is resolved. It was trying to access the class member functions without even being instantiated at the first time. I have one question though , when does the Qt Property System gets initialized ? right after the call of the class constructor ?

What if the property system do have to access some read-only value after some other classes initialization ? Is it possible to make the Qt property system to be inintialized in lazy manner ?

Because I need to access some opengl related value that depends on the opengl driver installed and then pass that value to the qml slider maximumvalue

Now it seems that the Qt property system gets the initialization call before the opengl initialization at the back-end ? Any idea to get it working ?



//the property defintion must be at the top of the class
//the notify signal is needed for correct property bindings
Q_PROPERTY(float outer READ outer WRITE setOuter NOTIFY outerChanged)
Q_PROPERTY(float inner READ inner WRITE setInner NOTIFY innerChanged)
Q_PROPERTY(float maxPatchVertices READ maxPatchVertices NOTIFY maxPatchVerticesChanged)

anda_skoa
1st January 2015, 17:39
I have one question though , when does the Qt Property System gets initialized ? right after the call of the class constructor ?

The property system doesn't need any initialization, it is based on invoking member functions which are callable as soon as an object instance has been created.



What if the property system do have to access some read-only value after some other classes initialization ? Is it possible to make the Qt property system to be inintialized in lazy manner ?

You can change a property's value at any time, all bindings on that property will get re-evaluated.



Now it seems that the Qt property system gets the initialization call before the opengl initialization at the back-end ? Any idea to get it working ?

As there is no "initializtion" of the property system, just make sure that the getter of the property returns the correct value once it is available.
Make sure you have emitted the property's change notifiier signal when you need QML to update the bindings for the new value.

Cheers,
_