pass data between qt controls (slider) and C++ application
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:
Code:
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;
};
The definition of the setter and getter methods:
Code:
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.
Code:
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
Re: pass data between qt controls (slider) and C++ application
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,
_
Re: pass data between qt controls (slider) and C++ application
Quote:
Originally Posted by
anda_skoa
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:
Code:
Q_PROPERTY(float inner READ inner WRITE setInner NOTIFY innerChanged)
Then inside the .qml file I have the following snippet:
Code:
TessellationSceneItem
{
id: tessSceneItem
inner: 10
}
I get the crashing point while running with debugger at the following points:
Code:
void TessellationSceneItem::setInner(float innerFactor)
{
if(innerFactor == mTessScene->innerTessellationFactor())
return;
mTessScene->setInnerTessellationFactor(innerFactor);
emit innerChanged();
}
..............................
..............................
GLfloat TeapotTessellation::innerTessellationFactor()
{
return mInnerTessellationFactor;
}
Quote:
Originally Posted by
anda_skoa
Does it work when you assign fixed values in QML?
The issue prevails.
Quote:
Originally Posted by
anda_skoa
DId you try with having matching types for your properties and the slider's value property?
I did not understand this part.
Thanks
Re: pass data between qt controls (slider) and C++ application
Quote:
Originally Posted by
sajis997
I get the crashing point while running with debugger at the following points:
Code:
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.
Quote:
Originally Posted by
sajis997
I did not understand this part.
Your properties have a different type (float) than the slider's value property (qreal).
Cheers,
_
Re: pass data between qt controls (slider) and C++ application
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 ?
Code:
//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)
Re: pass data between qt controls (slider) and C++ application
Quote:
Originally Posted by
sajis997
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.
Quote:
Originally Posted by
sajis997
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.
Quote:
Originally Posted by
sajis997
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,
_