Connect python signal to QML ui slot with PySide2
I've just started playing with PySide2 and QML for an upcoming project and I immediately stumbled on a problem: How do I connect a signal emitted by a python class (that inherits from QObject) to a slot in a .qml file?
For example: I have a QThread (python class) that generates a couple of xy coordinates every 50 milliseconds. I want to add the generated couple to a LineSeries defined in a QML file, in order to generate an oscilloscope-like plot.
The question is probably really basic and dumb, but I really need some help.
Best regards
Lando
EDIT 4:
I've found a solution, but I do not really like it. Can you suggest me (if it exists) a more elegant way to do it?
Code for Python:
class Manager(QObject):
dataReady = Signal(float,float)
def __init__(self):
QObject.__init__(self)
self._currX = 0
self._currY = 0
self._delay = 0.5
self._multiplier = 1.0
self._power = 1.0
self._xIncrement = 1.0
self._starter = False
self._threader = None
@Property(bool)
def starter(self):
return self._starter
@starter.setter
def setStarter(self, val):
print("New val: {0}, oldVal: {1}".format(val,self._starter))
if self._starter == val:
return
self._starter = val
if val:
self.start()
else:
self.stop()
@Property(float)
def multiplier(self):
return self._multiplier
@multiplier.setter
def setMultiplier(self, val):
if self._multiplier == val:
return
print(val)
self._multiplier = val
@Property(int)
def power(self):
return self._power
@power.setter
def setPower(self, val):
if self._power == val:
return
print(val)
self._power = val
@Property(float)
def delay(self):
return self._delay
@delay.setter
def setDelay(self, val):
if self._delay == val:
return
print(val)
self._delay = val
@Property(float)
def xIncrement(self):
return self._xIncrement
@xIncrement.setter
def setXIncrement(self, val):
if self._xIncrement == val:
return
print(val)
self._xIncrement = val
def generatePoint(self):
self._currX += self._xIncrement
self._currY = self._multiplier*(self._currX**self._power)
return self._currX,self._currY
def stop(self):
self._goOn = False
if self._threader is not None:
while self._threader.isRunning():
sleep(0.1)
def start(self):
self._goOn = True
self._threader = Threader(core=self.core)
self._threader.start()
def core(self):
while self._goOn:
x,y = self.generatePoint()
print([x,y])
self.dataReady.emit(x,y)
sleep(self._delay)
class Threader(QThread):
def __init__(self,core,parent=None):
QThread.__init__(self,parent)
self._core = core
self._goOn = False
def run(self):
self._core()
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QApplication(sys.argv)
manager = Manager()
engine = QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("Manager", manager)
engine.load('main.qml')
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
Code for QML:
ApplicationWindow {
id: mainWindow
width:640
height: 480
title: qsTr("Simple ui")
visible: true
locale:locale
property var controlsColor: Material.DeepPurple
property var controlsAccent: Material.BlueGrey
property real x: 0.0
property int controlsElevation: 6
property int paneElevation: 4
function drawPoint(theX,theY){
console.log(theX);
mainLine.append(theX,theY)
if (theX >= testXAxis.max){
testXAxis.max = theX;
}
if (theY >= testYAxis.max){
testYAxis.max = theY;
}
if (theY <= testYAxis.min){
testYAxis.min = theY;
}
}
function clearLine(){
mainLine.clear();
mainLine.append(0,0);
}
Pane{
id: mainPanel
anchors.fill: parent
//Material.theme: Material.Dark
RowLayout{
id: mainRowLO
anchors.fill: parent
spacing: 15
//Chart pane
Pane{
id: chartPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 400
ChartView {
id: testChart
title: "Line"
anchors.fill: parent
antialiasing: true
LineSeries {
id: mainLine
name: "LineSeries"
axisX: ValueAxis{
id: testXAxis
min: 0.0
max: 2.0
}
axisY: ValueAxis{
id: testYAxis
min: 0.0
max: 2.0
}
XYPoint { x: 0; y: 0 }
}
}
}
Pane{
id: controlsPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 200
Layout.maximumWidth: 200
ColumnLayout{
id: controlsColumnLO
anchors.fill: parent
spacing: 40
Label{
id: powerLabel
text: "Exponent"
Layout.topMargin: 40
Layout.leftMargin: 10
Layout.rightMargin: 10
}
SpinBox{
id: powerNum
from: 0
value: 1
to: 5
stepSize: 1
width: 80
validator: DoubleValidator {
bottom: Math.min(powerNum.from, powerNum.to)
top: Math.max(powerNum.from, powerNum.to)
}
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
editable: true
onValueChanged: function(){
Manager.power = value;
}
}
Label{
id: multiplierLabel
text: "Multiplier"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: multiplierSlider
from: -50
value: 1
to: 50
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.multiplier = value;
}
}
Label{
id: multValueLabel
text: String(multiplierSlider.value)
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Label{
id: delayLable
text: "Delay[s]"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: delaySlider
from: 0.05
value: 0.1
to: 1
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.delay = value;
}
}
Label{
id: incrementLable
text: "Increment"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: incrementSlider
from: 1.0
value: 1.0
to: 5.0
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.xIncrement = value;
}
}
Item {
// spacer item
id: controlsSpacer
Layout.fillWidth: true
Layout.fillHeight: true
Pane { anchors.fill: parent }//; Material.background: Material.Light; Material.elevation: 4 } // to visualize the spacer
}
Button{
id: startPointBtn
text: "START"
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
onClicked: function(){
console.log(text);
console.log(text=="START")
if(text=="START"){
Manager.starter = true;
Manager.dataReady.connect(drawPoint);
clearLine();
text = "STOP";
}
else{
Manager.starter = false;
text = "START";
Manager.dataReady.disconnect(drawPoint);
}
}
}
}
}
}
}
}
python qml qt-signals pyside2
add a comment |
I've just started playing with PySide2 and QML for an upcoming project and I immediately stumbled on a problem: How do I connect a signal emitted by a python class (that inherits from QObject) to a slot in a .qml file?
For example: I have a QThread (python class) that generates a couple of xy coordinates every 50 milliseconds. I want to add the generated couple to a LineSeries defined in a QML file, in order to generate an oscilloscope-like plot.
The question is probably really basic and dumb, but I really need some help.
Best regards
Lando
EDIT 4:
I've found a solution, but I do not really like it. Can you suggest me (if it exists) a more elegant way to do it?
Code for Python:
class Manager(QObject):
dataReady = Signal(float,float)
def __init__(self):
QObject.__init__(self)
self._currX = 0
self._currY = 0
self._delay = 0.5
self._multiplier = 1.0
self._power = 1.0
self._xIncrement = 1.0
self._starter = False
self._threader = None
@Property(bool)
def starter(self):
return self._starter
@starter.setter
def setStarter(self, val):
print("New val: {0}, oldVal: {1}".format(val,self._starter))
if self._starter == val:
return
self._starter = val
if val:
self.start()
else:
self.stop()
@Property(float)
def multiplier(self):
return self._multiplier
@multiplier.setter
def setMultiplier(self, val):
if self._multiplier == val:
return
print(val)
self._multiplier = val
@Property(int)
def power(self):
return self._power
@power.setter
def setPower(self, val):
if self._power == val:
return
print(val)
self._power = val
@Property(float)
def delay(self):
return self._delay
@delay.setter
def setDelay(self, val):
if self._delay == val:
return
print(val)
self._delay = val
@Property(float)
def xIncrement(self):
return self._xIncrement
@xIncrement.setter
def setXIncrement(self, val):
if self._xIncrement == val:
return
print(val)
self._xIncrement = val
def generatePoint(self):
self._currX += self._xIncrement
self._currY = self._multiplier*(self._currX**self._power)
return self._currX,self._currY
def stop(self):
self._goOn = False
if self._threader is not None:
while self._threader.isRunning():
sleep(0.1)
def start(self):
self._goOn = True
self._threader = Threader(core=self.core)
self._threader.start()
def core(self):
while self._goOn:
x,y = self.generatePoint()
print([x,y])
self.dataReady.emit(x,y)
sleep(self._delay)
class Threader(QThread):
def __init__(self,core,parent=None):
QThread.__init__(self,parent)
self._core = core
self._goOn = False
def run(self):
self._core()
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QApplication(sys.argv)
manager = Manager()
engine = QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("Manager", manager)
engine.load('main.qml')
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
Code for QML:
ApplicationWindow {
id: mainWindow
width:640
height: 480
title: qsTr("Simple ui")
visible: true
locale:locale
property var controlsColor: Material.DeepPurple
property var controlsAccent: Material.BlueGrey
property real x: 0.0
property int controlsElevation: 6
property int paneElevation: 4
function drawPoint(theX,theY){
console.log(theX);
mainLine.append(theX,theY)
if (theX >= testXAxis.max){
testXAxis.max = theX;
}
if (theY >= testYAxis.max){
testYAxis.max = theY;
}
if (theY <= testYAxis.min){
testYAxis.min = theY;
}
}
function clearLine(){
mainLine.clear();
mainLine.append(0,0);
}
Pane{
id: mainPanel
anchors.fill: parent
//Material.theme: Material.Dark
RowLayout{
id: mainRowLO
anchors.fill: parent
spacing: 15
//Chart pane
Pane{
id: chartPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 400
ChartView {
id: testChart
title: "Line"
anchors.fill: parent
antialiasing: true
LineSeries {
id: mainLine
name: "LineSeries"
axisX: ValueAxis{
id: testXAxis
min: 0.0
max: 2.0
}
axisY: ValueAxis{
id: testYAxis
min: 0.0
max: 2.0
}
XYPoint { x: 0; y: 0 }
}
}
}
Pane{
id: controlsPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 200
Layout.maximumWidth: 200
ColumnLayout{
id: controlsColumnLO
anchors.fill: parent
spacing: 40
Label{
id: powerLabel
text: "Exponent"
Layout.topMargin: 40
Layout.leftMargin: 10
Layout.rightMargin: 10
}
SpinBox{
id: powerNum
from: 0
value: 1
to: 5
stepSize: 1
width: 80
validator: DoubleValidator {
bottom: Math.min(powerNum.from, powerNum.to)
top: Math.max(powerNum.from, powerNum.to)
}
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
editable: true
onValueChanged: function(){
Manager.power = value;
}
}
Label{
id: multiplierLabel
text: "Multiplier"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: multiplierSlider
from: -50
value: 1
to: 50
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.multiplier = value;
}
}
Label{
id: multValueLabel
text: String(multiplierSlider.value)
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Label{
id: delayLable
text: "Delay[s]"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: delaySlider
from: 0.05
value: 0.1
to: 1
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.delay = value;
}
}
Label{
id: incrementLable
text: "Increment"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: incrementSlider
from: 1.0
value: 1.0
to: 5.0
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.xIncrement = value;
}
}
Item {
// spacer item
id: controlsSpacer
Layout.fillWidth: true
Layout.fillHeight: true
Pane { anchors.fill: parent }//; Material.background: Material.Light; Material.elevation: 4 } // to visualize the spacer
}
Button{
id: startPointBtn
text: "START"
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
onClicked: function(){
console.log(text);
console.log(text=="START")
if(text=="START"){
Manager.starter = true;
Manager.dataReady.connect(drawPoint);
clearLine();
text = "STOP";
}
else{
Manager.starter = false;
text = "START";
Manager.dataReady.disconnect(drawPoint);
}
}
}
}
}
}
}
}
python qml qt-signals pyside2
provide a Minimal, Complete, and Verifiable example
– eyllanesc
Jan 2 at 17:03
I do not know how to write the code. That's why I'm asking. I have found nothing about this topic and so I have no idea on how a connection between a signal from a python class and a slot on a qml file could be connected
– Lando1784
Jan 2 at 17:26
I'm not asking for the solution, it's obvious that you do not know her, so she asks. What I ask is that you share the code that you indicate you have: I have a QThread (python class) that generates a couple of xy coordinates every 50 milliseconds
– eyllanesc
Jan 2 at 17:28
add a comment |
I've just started playing with PySide2 and QML for an upcoming project and I immediately stumbled on a problem: How do I connect a signal emitted by a python class (that inherits from QObject) to a slot in a .qml file?
For example: I have a QThread (python class) that generates a couple of xy coordinates every 50 milliseconds. I want to add the generated couple to a LineSeries defined in a QML file, in order to generate an oscilloscope-like plot.
The question is probably really basic and dumb, but I really need some help.
Best regards
Lando
EDIT 4:
I've found a solution, but I do not really like it. Can you suggest me (if it exists) a more elegant way to do it?
Code for Python:
class Manager(QObject):
dataReady = Signal(float,float)
def __init__(self):
QObject.__init__(self)
self._currX = 0
self._currY = 0
self._delay = 0.5
self._multiplier = 1.0
self._power = 1.0
self._xIncrement = 1.0
self._starter = False
self._threader = None
@Property(bool)
def starter(self):
return self._starter
@starter.setter
def setStarter(self, val):
print("New val: {0}, oldVal: {1}".format(val,self._starter))
if self._starter == val:
return
self._starter = val
if val:
self.start()
else:
self.stop()
@Property(float)
def multiplier(self):
return self._multiplier
@multiplier.setter
def setMultiplier(self, val):
if self._multiplier == val:
return
print(val)
self._multiplier = val
@Property(int)
def power(self):
return self._power
@power.setter
def setPower(self, val):
if self._power == val:
return
print(val)
self._power = val
@Property(float)
def delay(self):
return self._delay
@delay.setter
def setDelay(self, val):
if self._delay == val:
return
print(val)
self._delay = val
@Property(float)
def xIncrement(self):
return self._xIncrement
@xIncrement.setter
def setXIncrement(self, val):
if self._xIncrement == val:
return
print(val)
self._xIncrement = val
def generatePoint(self):
self._currX += self._xIncrement
self._currY = self._multiplier*(self._currX**self._power)
return self._currX,self._currY
def stop(self):
self._goOn = False
if self._threader is not None:
while self._threader.isRunning():
sleep(0.1)
def start(self):
self._goOn = True
self._threader = Threader(core=self.core)
self._threader.start()
def core(self):
while self._goOn:
x,y = self.generatePoint()
print([x,y])
self.dataReady.emit(x,y)
sleep(self._delay)
class Threader(QThread):
def __init__(self,core,parent=None):
QThread.__init__(self,parent)
self._core = core
self._goOn = False
def run(self):
self._core()
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QApplication(sys.argv)
manager = Manager()
engine = QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("Manager", manager)
engine.load('main.qml')
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
Code for QML:
ApplicationWindow {
id: mainWindow
width:640
height: 480
title: qsTr("Simple ui")
visible: true
locale:locale
property var controlsColor: Material.DeepPurple
property var controlsAccent: Material.BlueGrey
property real x: 0.0
property int controlsElevation: 6
property int paneElevation: 4
function drawPoint(theX,theY){
console.log(theX);
mainLine.append(theX,theY)
if (theX >= testXAxis.max){
testXAxis.max = theX;
}
if (theY >= testYAxis.max){
testYAxis.max = theY;
}
if (theY <= testYAxis.min){
testYAxis.min = theY;
}
}
function clearLine(){
mainLine.clear();
mainLine.append(0,0);
}
Pane{
id: mainPanel
anchors.fill: parent
//Material.theme: Material.Dark
RowLayout{
id: mainRowLO
anchors.fill: parent
spacing: 15
//Chart pane
Pane{
id: chartPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 400
ChartView {
id: testChart
title: "Line"
anchors.fill: parent
antialiasing: true
LineSeries {
id: mainLine
name: "LineSeries"
axisX: ValueAxis{
id: testXAxis
min: 0.0
max: 2.0
}
axisY: ValueAxis{
id: testYAxis
min: 0.0
max: 2.0
}
XYPoint { x: 0; y: 0 }
}
}
}
Pane{
id: controlsPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 200
Layout.maximumWidth: 200
ColumnLayout{
id: controlsColumnLO
anchors.fill: parent
spacing: 40
Label{
id: powerLabel
text: "Exponent"
Layout.topMargin: 40
Layout.leftMargin: 10
Layout.rightMargin: 10
}
SpinBox{
id: powerNum
from: 0
value: 1
to: 5
stepSize: 1
width: 80
validator: DoubleValidator {
bottom: Math.min(powerNum.from, powerNum.to)
top: Math.max(powerNum.from, powerNum.to)
}
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
editable: true
onValueChanged: function(){
Manager.power = value;
}
}
Label{
id: multiplierLabel
text: "Multiplier"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: multiplierSlider
from: -50
value: 1
to: 50
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.multiplier = value;
}
}
Label{
id: multValueLabel
text: String(multiplierSlider.value)
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Label{
id: delayLable
text: "Delay[s]"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: delaySlider
from: 0.05
value: 0.1
to: 1
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.delay = value;
}
}
Label{
id: incrementLable
text: "Increment"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: incrementSlider
from: 1.0
value: 1.0
to: 5.0
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.xIncrement = value;
}
}
Item {
// spacer item
id: controlsSpacer
Layout.fillWidth: true
Layout.fillHeight: true
Pane { anchors.fill: parent }//; Material.background: Material.Light; Material.elevation: 4 } // to visualize the spacer
}
Button{
id: startPointBtn
text: "START"
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
onClicked: function(){
console.log(text);
console.log(text=="START")
if(text=="START"){
Manager.starter = true;
Manager.dataReady.connect(drawPoint);
clearLine();
text = "STOP";
}
else{
Manager.starter = false;
text = "START";
Manager.dataReady.disconnect(drawPoint);
}
}
}
}
}
}
}
}
python qml qt-signals pyside2
I've just started playing with PySide2 and QML for an upcoming project and I immediately stumbled on a problem: How do I connect a signal emitted by a python class (that inherits from QObject) to a slot in a .qml file?
For example: I have a QThread (python class) that generates a couple of xy coordinates every 50 milliseconds. I want to add the generated couple to a LineSeries defined in a QML file, in order to generate an oscilloscope-like plot.
The question is probably really basic and dumb, but I really need some help.
Best regards
Lando
EDIT 4:
I've found a solution, but I do not really like it. Can you suggest me (if it exists) a more elegant way to do it?
Code for Python:
class Manager(QObject):
dataReady = Signal(float,float)
def __init__(self):
QObject.__init__(self)
self._currX = 0
self._currY = 0
self._delay = 0.5
self._multiplier = 1.0
self._power = 1.0
self._xIncrement = 1.0
self._starter = False
self._threader = None
@Property(bool)
def starter(self):
return self._starter
@starter.setter
def setStarter(self, val):
print("New val: {0}, oldVal: {1}".format(val,self._starter))
if self._starter == val:
return
self._starter = val
if val:
self.start()
else:
self.stop()
@Property(float)
def multiplier(self):
return self._multiplier
@multiplier.setter
def setMultiplier(self, val):
if self._multiplier == val:
return
print(val)
self._multiplier = val
@Property(int)
def power(self):
return self._power
@power.setter
def setPower(self, val):
if self._power == val:
return
print(val)
self._power = val
@Property(float)
def delay(self):
return self._delay
@delay.setter
def setDelay(self, val):
if self._delay == val:
return
print(val)
self._delay = val
@Property(float)
def xIncrement(self):
return self._xIncrement
@xIncrement.setter
def setXIncrement(self, val):
if self._xIncrement == val:
return
print(val)
self._xIncrement = val
def generatePoint(self):
self._currX += self._xIncrement
self._currY = self._multiplier*(self._currX**self._power)
return self._currX,self._currY
def stop(self):
self._goOn = False
if self._threader is not None:
while self._threader.isRunning():
sleep(0.1)
def start(self):
self._goOn = True
self._threader = Threader(core=self.core)
self._threader.start()
def core(self):
while self._goOn:
x,y = self.generatePoint()
print([x,y])
self.dataReady.emit(x,y)
sleep(self._delay)
class Threader(QThread):
def __init__(self,core,parent=None):
QThread.__init__(self,parent)
self._core = core
self._goOn = False
def run(self):
self._core()
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QApplication(sys.argv)
manager = Manager()
engine = QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("Manager", manager)
engine.load('main.qml')
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
Code for QML:
ApplicationWindow {
id: mainWindow
width:640
height: 480
title: qsTr("Simple ui")
visible: true
locale:locale
property var controlsColor: Material.DeepPurple
property var controlsAccent: Material.BlueGrey
property real x: 0.0
property int controlsElevation: 6
property int paneElevation: 4
function drawPoint(theX,theY){
console.log(theX);
mainLine.append(theX,theY)
if (theX >= testXAxis.max){
testXAxis.max = theX;
}
if (theY >= testYAxis.max){
testYAxis.max = theY;
}
if (theY <= testYAxis.min){
testYAxis.min = theY;
}
}
function clearLine(){
mainLine.clear();
mainLine.append(0,0);
}
Pane{
id: mainPanel
anchors.fill: parent
//Material.theme: Material.Dark
RowLayout{
id: mainRowLO
anchors.fill: parent
spacing: 15
//Chart pane
Pane{
id: chartPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 400
ChartView {
id: testChart
title: "Line"
anchors.fill: parent
antialiasing: true
LineSeries {
id: mainLine
name: "LineSeries"
axisX: ValueAxis{
id: testXAxis
min: 0.0
max: 2.0
}
axisY: ValueAxis{
id: testYAxis
min: 0.0
max: 2.0
}
XYPoint { x: 0; y: 0 }
}
}
}
Pane{
id: controlsPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 200
Layout.maximumWidth: 200
ColumnLayout{
id: controlsColumnLO
anchors.fill: parent
spacing: 40
Label{
id: powerLabel
text: "Exponent"
Layout.topMargin: 40
Layout.leftMargin: 10
Layout.rightMargin: 10
}
SpinBox{
id: powerNum
from: 0
value: 1
to: 5
stepSize: 1
width: 80
validator: DoubleValidator {
bottom: Math.min(powerNum.from, powerNum.to)
top: Math.max(powerNum.from, powerNum.to)
}
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
editable: true
onValueChanged: function(){
Manager.power = value;
}
}
Label{
id: multiplierLabel
text: "Multiplier"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: multiplierSlider
from: -50
value: 1
to: 50
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.multiplier = value;
}
}
Label{
id: multValueLabel
text: String(multiplierSlider.value)
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Label{
id: delayLable
text: "Delay[s]"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: delaySlider
from: 0.05
value: 0.1
to: 1
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.delay = value;
}
}
Label{
id: incrementLable
text: "Increment"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: incrementSlider
from: 1.0
value: 1.0
to: 5.0
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.xIncrement = value;
}
}
Item {
// spacer item
id: controlsSpacer
Layout.fillWidth: true
Layout.fillHeight: true
Pane { anchors.fill: parent }//; Material.background: Material.Light; Material.elevation: 4 } // to visualize the spacer
}
Button{
id: startPointBtn
text: "START"
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
onClicked: function(){
console.log(text);
console.log(text=="START")
if(text=="START"){
Manager.starter = true;
Manager.dataReady.connect(drawPoint);
clearLine();
text = "STOP";
}
else{
Manager.starter = false;
text = "START";
Manager.dataReady.disconnect(drawPoint);
}
}
}
}
}
}
}
}
python qml qt-signals pyside2
python qml qt-signals pyside2
edited Jan 2 at 18:13
Lando1784
asked Jan 2 at 16:58
Lando1784Lando1784
255
255
provide a Minimal, Complete, and Verifiable example
– eyllanesc
Jan 2 at 17:03
I do not know how to write the code. That's why I'm asking. I have found nothing about this topic and so I have no idea on how a connection between a signal from a python class and a slot on a qml file could be connected
– Lando1784
Jan 2 at 17:26
I'm not asking for the solution, it's obvious that you do not know her, so she asks. What I ask is that you share the code that you indicate you have: I have a QThread (python class) that generates a couple of xy coordinates every 50 milliseconds
– eyllanesc
Jan 2 at 17:28
add a comment |
provide a Minimal, Complete, and Verifiable example
– eyllanesc
Jan 2 at 17:03
I do not know how to write the code. That's why I'm asking. I have found nothing about this topic and so I have no idea on how a connection between a signal from a python class and a slot on a qml file could be connected
– Lando1784
Jan 2 at 17:26
I'm not asking for the solution, it's obvious that you do not know her, so she asks. What I ask is that you share the code that you indicate you have: I have a QThread (python class) that generates a couple of xy coordinates every 50 milliseconds
– eyllanesc
Jan 2 at 17:28
provide a Minimal, Complete, and Verifiable example
– eyllanesc
Jan 2 at 17:03
provide a Minimal, Complete, and Verifiable example
– eyllanesc
Jan 2 at 17:03
I do not know how to write the code. That's why I'm asking. I have found nothing about this topic and so I have no idea on how a connection between a signal from a python class and a slot on a qml file could be connected
– Lando1784
Jan 2 at 17:26
I do not know how to write the code. That's why I'm asking. I have found nothing about this topic and so I have no idea on how a connection between a signal from a python class and a slot on a qml file could be connected
– Lando1784
Jan 2 at 17:26
I'm not asking for the solution, it's obvious that you do not know her, so she asks. What I ask is that you share the code that you indicate you have: I have a QThread (python class) that generates a couple of xy coordinates every 50 milliseconds
– eyllanesc
Jan 2 at 17:28
I'm not asking for the solution, it's obvious that you do not know her, so she asks. What I ask is that you share the code that you indicate you have: I have a QThread (python class) that generates a couple of xy coordinates every 50 milliseconds
– eyllanesc
Jan 2 at 17:28
add a comment |
1 Answer
1
active
oldest
votes
The simplest solution is to use Connections but in the case of PySide/PySide2 you can not get the arguments so I'll use the trick they point to in this answer.
If you are going to send a point then use QPoint as it is directly translated to point type in QML. You must also calculate the max and min to update the axes.
Considering the above, the solution is the following:
*.py
import os
import sys
import time
from PySide2 import QtCore, QtWidgets, QtQml
class Manager(QtCore.QObject):
dataReady = QtCore.Signal(QtCore.QPointF, name='dataReady')
def __init__(self, parent=None):
super(Manager, self).__init__(parent)
self._currX = 0
self._currY = 0
self._delay = 0.5
self._multiplier = 1.0
self._power = 1.0
self._xIncrement = 1.0
self._starter = False
self._goOn = False
self._threader = None
@QtCore.Property(bool)
def starter(self):
return self._starter
@starter.setter
def setStarter(self, val):
if self._multiplier == val:
return
print(val)
if val:
self.start()
else:
self.stop()
self._starter = val
@QtCore.Property(float)
def multiplier(self):
return self._multiplier
@multiplier.setter
def setMultiplier(self, val):
if self._multiplier == val:
return
print(val)
self._multiplier = val
@QtCore.Property(int)
def power(self):
return self._power
@power.setter
def setPower(self, val):
if self._power == val:
return
print(val)
self._power = val
@QtCore.Property(float)
def delay(self):
return self._delay
@delay.setter
def setDelay(self, val):
if self._delay == val:
return
print(val)
self._delay = val
@QtCore.Property(float)
def xIncrement(self):
return self._xIncrement
@xIncrement.setter
def setXIncrement(self, val):
if self._xIncrement == val:
return
print(val)
self._xIncrement = val
def generatePoint(self):
self._currX += self._xIncrement
self._currY = self._multiplier*(self._currX**self._power)
return self._currX,self._currY
def stop(self):
self._goOn = False
if self._threader is not None:
while self._threader.isRunning():
time.sleep(0.1)
def start(self):
self._goOn = True
self._threader = Threader(self.core, self)
self._threader.start()
def core(self):
while self._goOn:
p = QtCore.QPointF(*self.generatePoint())
self.dataReady.emit(p)
time.sleep(self._delay)
# -------------------------------------------------
class Threader(QtCore.QThread):
def __init__(self,core,parent=None):
super(Threader, self).__init__(parent)
self._core = core
def run(self):
self._core()
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QtWidgets.QApplication(sys.argv)
manager = Manager()
app.aboutToQuit.connect(manager.stop)
manager.start()
engine = QtQml.QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("Manager", manager)
engine.load('main.qml')
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
*.qml
import QtQuick 2.9
import QtCharts 2.2
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.5
import QtQuick.Controls.Material 2.12
ApplicationWindow {
id: mainWindow
width:640
height: 480
title: qsTr("Simple ui")
visible: true
locale:locale
property int controlsColor: Material.DeepPurple
property int controlsAccent: Material.BlueGrey
property real x: 0.0
property int controlsElevation: 6
property int paneElevation: 4
signal reemitted(point p)
Component.onCompleted: Manager.dataReady.connect(mainWindow.reemitted)
onReemitted: {
testXAxis.max = Math.max(testXAxis.max, p.x)
testXAxis.min = Math.min(testXAxis.min, p.x)
testYAxis.max = Math.max(testYAxis.max, p.y)
testYAxis.min = Math.min(testYAxis.min, p.y)
mainLine.append(p.x, p.y)
}
function drawPoint(xy){
mainLine.append(xy[0],xy[1])
if (mainWindow.x >= testXAxis.max){
testXAxis.max = mainWindow.x;
}
if (py >= testYAxis.max){
testYAxis.max = py;
}
if (py <= testYAxis.min){
testYAxis.min = py;
}
}
function clearLine(){
mainLine.clear();
mainLine.append(0,0);
}
Pane{
id: mainPanel
anchors.fill: parent
//Material.theme: Material.Dark
RowLayout{
id: mainRowLO
anchors.fill: parent
spacing: 15
//Chart pane
Pane{
id: chartPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 400
ChartView {
id: testChart
title: "Line"
anchors.fill: parent
antialiasing: true
LineSeries {
id: mainLine
name: "LineSeries"
axisX: ValueAxis{
id: testXAxis
min: 0.0
max: 2.0
}
axisY: ValueAxis{
id: testYAxis
min: 0.0
max: 2.0
}
XYPoint { x: 0; y: 0 }
}
}
}
Pane{
id: controlsPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 200
Layout.maximumWidth: 200
ColumnLayout{
id: controlsColumnLO
anchors.fill: parent
spacing: 40
Label{
id: powerLabel
text: "Exponent"
Layout.topMargin: 40
Layout.leftMargin: 10
Layout.rightMargin: 10
}
SpinBox{
id: powerNum
from: 0
value: 1
to: 5
stepSize: 1
width: 80
validator: DoubleValidator {
bottom: Math.min(powerNum.from, powerNum.to)
top: Math.max(powerNum.from, powerNum.to)
}
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
editable: true
onValueChanged: function(){
Manager.power = value;
}
}
Label{
id: multiplierLabel
text: "Multiplier"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: multiplierSlider
from: -50
value: 1
to: 50
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.multiplier = value;
}
}
Label{
id: multValueLabel
text: String(multiplierSlider.value)
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Label{
id: delayLable
text: "Delay[s]"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: delaySlider
from: 0.05
value: 0.1
to: 1
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.delay = value;
}
}
Label{
id: incrementLable
text: "Increment"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: incrementSlider
from: 1.0
value: 1.0
to: 5.0
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.xIncrement = value;
}
}
Item {
// spacer item
id: controlsSpacer
Layout.fillWidth: true
Layout.fillHeight: true
Pane { anchors.fill: parent }//; Material.background: Material.Light; Material.elevation: 4 } // to visualize the spacer
}
Button{
id: startPointBtn
text: "START"
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
onClicked: function(){
console.log(text);
if(text=="START"){
clearLine();
Manager.starter = true;
text = "STOP";
}
else{
Manager.starter = false;
text = "START";
}
}
}
}
}
}
}
}

add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54010254%2fconnect-python-signal-to-qml-ui-slot-with-pyside2%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The simplest solution is to use Connections but in the case of PySide/PySide2 you can not get the arguments so I'll use the trick they point to in this answer.
If you are going to send a point then use QPoint as it is directly translated to point type in QML. You must also calculate the max and min to update the axes.
Considering the above, the solution is the following:
*.py
import os
import sys
import time
from PySide2 import QtCore, QtWidgets, QtQml
class Manager(QtCore.QObject):
dataReady = QtCore.Signal(QtCore.QPointF, name='dataReady')
def __init__(self, parent=None):
super(Manager, self).__init__(parent)
self._currX = 0
self._currY = 0
self._delay = 0.5
self._multiplier = 1.0
self._power = 1.0
self._xIncrement = 1.0
self._starter = False
self._goOn = False
self._threader = None
@QtCore.Property(bool)
def starter(self):
return self._starter
@starter.setter
def setStarter(self, val):
if self._multiplier == val:
return
print(val)
if val:
self.start()
else:
self.stop()
self._starter = val
@QtCore.Property(float)
def multiplier(self):
return self._multiplier
@multiplier.setter
def setMultiplier(self, val):
if self._multiplier == val:
return
print(val)
self._multiplier = val
@QtCore.Property(int)
def power(self):
return self._power
@power.setter
def setPower(self, val):
if self._power == val:
return
print(val)
self._power = val
@QtCore.Property(float)
def delay(self):
return self._delay
@delay.setter
def setDelay(self, val):
if self._delay == val:
return
print(val)
self._delay = val
@QtCore.Property(float)
def xIncrement(self):
return self._xIncrement
@xIncrement.setter
def setXIncrement(self, val):
if self._xIncrement == val:
return
print(val)
self._xIncrement = val
def generatePoint(self):
self._currX += self._xIncrement
self._currY = self._multiplier*(self._currX**self._power)
return self._currX,self._currY
def stop(self):
self._goOn = False
if self._threader is not None:
while self._threader.isRunning():
time.sleep(0.1)
def start(self):
self._goOn = True
self._threader = Threader(self.core, self)
self._threader.start()
def core(self):
while self._goOn:
p = QtCore.QPointF(*self.generatePoint())
self.dataReady.emit(p)
time.sleep(self._delay)
# -------------------------------------------------
class Threader(QtCore.QThread):
def __init__(self,core,parent=None):
super(Threader, self).__init__(parent)
self._core = core
def run(self):
self._core()
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QtWidgets.QApplication(sys.argv)
manager = Manager()
app.aboutToQuit.connect(manager.stop)
manager.start()
engine = QtQml.QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("Manager", manager)
engine.load('main.qml')
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
*.qml
import QtQuick 2.9
import QtCharts 2.2
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.5
import QtQuick.Controls.Material 2.12
ApplicationWindow {
id: mainWindow
width:640
height: 480
title: qsTr("Simple ui")
visible: true
locale:locale
property int controlsColor: Material.DeepPurple
property int controlsAccent: Material.BlueGrey
property real x: 0.0
property int controlsElevation: 6
property int paneElevation: 4
signal reemitted(point p)
Component.onCompleted: Manager.dataReady.connect(mainWindow.reemitted)
onReemitted: {
testXAxis.max = Math.max(testXAxis.max, p.x)
testXAxis.min = Math.min(testXAxis.min, p.x)
testYAxis.max = Math.max(testYAxis.max, p.y)
testYAxis.min = Math.min(testYAxis.min, p.y)
mainLine.append(p.x, p.y)
}
function drawPoint(xy){
mainLine.append(xy[0],xy[1])
if (mainWindow.x >= testXAxis.max){
testXAxis.max = mainWindow.x;
}
if (py >= testYAxis.max){
testYAxis.max = py;
}
if (py <= testYAxis.min){
testYAxis.min = py;
}
}
function clearLine(){
mainLine.clear();
mainLine.append(0,0);
}
Pane{
id: mainPanel
anchors.fill: parent
//Material.theme: Material.Dark
RowLayout{
id: mainRowLO
anchors.fill: parent
spacing: 15
//Chart pane
Pane{
id: chartPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 400
ChartView {
id: testChart
title: "Line"
anchors.fill: parent
antialiasing: true
LineSeries {
id: mainLine
name: "LineSeries"
axisX: ValueAxis{
id: testXAxis
min: 0.0
max: 2.0
}
axisY: ValueAxis{
id: testYAxis
min: 0.0
max: 2.0
}
XYPoint { x: 0; y: 0 }
}
}
}
Pane{
id: controlsPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 200
Layout.maximumWidth: 200
ColumnLayout{
id: controlsColumnLO
anchors.fill: parent
spacing: 40
Label{
id: powerLabel
text: "Exponent"
Layout.topMargin: 40
Layout.leftMargin: 10
Layout.rightMargin: 10
}
SpinBox{
id: powerNum
from: 0
value: 1
to: 5
stepSize: 1
width: 80
validator: DoubleValidator {
bottom: Math.min(powerNum.from, powerNum.to)
top: Math.max(powerNum.from, powerNum.to)
}
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
editable: true
onValueChanged: function(){
Manager.power = value;
}
}
Label{
id: multiplierLabel
text: "Multiplier"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: multiplierSlider
from: -50
value: 1
to: 50
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.multiplier = value;
}
}
Label{
id: multValueLabel
text: String(multiplierSlider.value)
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Label{
id: delayLable
text: "Delay[s]"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: delaySlider
from: 0.05
value: 0.1
to: 1
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.delay = value;
}
}
Label{
id: incrementLable
text: "Increment"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: incrementSlider
from: 1.0
value: 1.0
to: 5.0
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.xIncrement = value;
}
}
Item {
// spacer item
id: controlsSpacer
Layout.fillWidth: true
Layout.fillHeight: true
Pane { anchors.fill: parent }//; Material.background: Material.Light; Material.elevation: 4 } // to visualize the spacer
}
Button{
id: startPointBtn
text: "START"
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
onClicked: function(){
console.log(text);
if(text=="START"){
clearLine();
Manager.starter = true;
text = "STOP";
}
else{
Manager.starter = false;
text = "START";
}
}
}
}
}
}
}
}

add a comment |
The simplest solution is to use Connections but in the case of PySide/PySide2 you can not get the arguments so I'll use the trick they point to in this answer.
If you are going to send a point then use QPoint as it is directly translated to point type in QML. You must also calculate the max and min to update the axes.
Considering the above, the solution is the following:
*.py
import os
import sys
import time
from PySide2 import QtCore, QtWidgets, QtQml
class Manager(QtCore.QObject):
dataReady = QtCore.Signal(QtCore.QPointF, name='dataReady')
def __init__(self, parent=None):
super(Manager, self).__init__(parent)
self._currX = 0
self._currY = 0
self._delay = 0.5
self._multiplier = 1.0
self._power = 1.0
self._xIncrement = 1.0
self._starter = False
self._goOn = False
self._threader = None
@QtCore.Property(bool)
def starter(self):
return self._starter
@starter.setter
def setStarter(self, val):
if self._multiplier == val:
return
print(val)
if val:
self.start()
else:
self.stop()
self._starter = val
@QtCore.Property(float)
def multiplier(self):
return self._multiplier
@multiplier.setter
def setMultiplier(self, val):
if self._multiplier == val:
return
print(val)
self._multiplier = val
@QtCore.Property(int)
def power(self):
return self._power
@power.setter
def setPower(self, val):
if self._power == val:
return
print(val)
self._power = val
@QtCore.Property(float)
def delay(self):
return self._delay
@delay.setter
def setDelay(self, val):
if self._delay == val:
return
print(val)
self._delay = val
@QtCore.Property(float)
def xIncrement(self):
return self._xIncrement
@xIncrement.setter
def setXIncrement(self, val):
if self._xIncrement == val:
return
print(val)
self._xIncrement = val
def generatePoint(self):
self._currX += self._xIncrement
self._currY = self._multiplier*(self._currX**self._power)
return self._currX,self._currY
def stop(self):
self._goOn = False
if self._threader is not None:
while self._threader.isRunning():
time.sleep(0.1)
def start(self):
self._goOn = True
self._threader = Threader(self.core, self)
self._threader.start()
def core(self):
while self._goOn:
p = QtCore.QPointF(*self.generatePoint())
self.dataReady.emit(p)
time.sleep(self._delay)
# -------------------------------------------------
class Threader(QtCore.QThread):
def __init__(self,core,parent=None):
super(Threader, self).__init__(parent)
self._core = core
def run(self):
self._core()
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QtWidgets.QApplication(sys.argv)
manager = Manager()
app.aboutToQuit.connect(manager.stop)
manager.start()
engine = QtQml.QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("Manager", manager)
engine.load('main.qml')
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
*.qml
import QtQuick 2.9
import QtCharts 2.2
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.5
import QtQuick.Controls.Material 2.12
ApplicationWindow {
id: mainWindow
width:640
height: 480
title: qsTr("Simple ui")
visible: true
locale:locale
property int controlsColor: Material.DeepPurple
property int controlsAccent: Material.BlueGrey
property real x: 0.0
property int controlsElevation: 6
property int paneElevation: 4
signal reemitted(point p)
Component.onCompleted: Manager.dataReady.connect(mainWindow.reemitted)
onReemitted: {
testXAxis.max = Math.max(testXAxis.max, p.x)
testXAxis.min = Math.min(testXAxis.min, p.x)
testYAxis.max = Math.max(testYAxis.max, p.y)
testYAxis.min = Math.min(testYAxis.min, p.y)
mainLine.append(p.x, p.y)
}
function drawPoint(xy){
mainLine.append(xy[0],xy[1])
if (mainWindow.x >= testXAxis.max){
testXAxis.max = mainWindow.x;
}
if (py >= testYAxis.max){
testYAxis.max = py;
}
if (py <= testYAxis.min){
testYAxis.min = py;
}
}
function clearLine(){
mainLine.clear();
mainLine.append(0,0);
}
Pane{
id: mainPanel
anchors.fill: parent
//Material.theme: Material.Dark
RowLayout{
id: mainRowLO
anchors.fill: parent
spacing: 15
//Chart pane
Pane{
id: chartPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 400
ChartView {
id: testChart
title: "Line"
anchors.fill: parent
antialiasing: true
LineSeries {
id: mainLine
name: "LineSeries"
axisX: ValueAxis{
id: testXAxis
min: 0.0
max: 2.0
}
axisY: ValueAxis{
id: testYAxis
min: 0.0
max: 2.0
}
XYPoint { x: 0; y: 0 }
}
}
}
Pane{
id: controlsPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 200
Layout.maximumWidth: 200
ColumnLayout{
id: controlsColumnLO
anchors.fill: parent
spacing: 40
Label{
id: powerLabel
text: "Exponent"
Layout.topMargin: 40
Layout.leftMargin: 10
Layout.rightMargin: 10
}
SpinBox{
id: powerNum
from: 0
value: 1
to: 5
stepSize: 1
width: 80
validator: DoubleValidator {
bottom: Math.min(powerNum.from, powerNum.to)
top: Math.max(powerNum.from, powerNum.to)
}
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
editable: true
onValueChanged: function(){
Manager.power = value;
}
}
Label{
id: multiplierLabel
text: "Multiplier"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: multiplierSlider
from: -50
value: 1
to: 50
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.multiplier = value;
}
}
Label{
id: multValueLabel
text: String(multiplierSlider.value)
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Label{
id: delayLable
text: "Delay[s]"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: delaySlider
from: 0.05
value: 0.1
to: 1
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.delay = value;
}
}
Label{
id: incrementLable
text: "Increment"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: incrementSlider
from: 1.0
value: 1.0
to: 5.0
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.xIncrement = value;
}
}
Item {
// spacer item
id: controlsSpacer
Layout.fillWidth: true
Layout.fillHeight: true
Pane { anchors.fill: parent }//; Material.background: Material.Light; Material.elevation: 4 } // to visualize the spacer
}
Button{
id: startPointBtn
text: "START"
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
onClicked: function(){
console.log(text);
if(text=="START"){
clearLine();
Manager.starter = true;
text = "STOP";
}
else{
Manager.starter = false;
text = "START";
}
}
}
}
}
}
}
}

add a comment |
The simplest solution is to use Connections but in the case of PySide/PySide2 you can not get the arguments so I'll use the trick they point to in this answer.
If you are going to send a point then use QPoint as it is directly translated to point type in QML. You must also calculate the max and min to update the axes.
Considering the above, the solution is the following:
*.py
import os
import sys
import time
from PySide2 import QtCore, QtWidgets, QtQml
class Manager(QtCore.QObject):
dataReady = QtCore.Signal(QtCore.QPointF, name='dataReady')
def __init__(self, parent=None):
super(Manager, self).__init__(parent)
self._currX = 0
self._currY = 0
self._delay = 0.5
self._multiplier = 1.0
self._power = 1.0
self._xIncrement = 1.0
self._starter = False
self._goOn = False
self._threader = None
@QtCore.Property(bool)
def starter(self):
return self._starter
@starter.setter
def setStarter(self, val):
if self._multiplier == val:
return
print(val)
if val:
self.start()
else:
self.stop()
self._starter = val
@QtCore.Property(float)
def multiplier(self):
return self._multiplier
@multiplier.setter
def setMultiplier(self, val):
if self._multiplier == val:
return
print(val)
self._multiplier = val
@QtCore.Property(int)
def power(self):
return self._power
@power.setter
def setPower(self, val):
if self._power == val:
return
print(val)
self._power = val
@QtCore.Property(float)
def delay(self):
return self._delay
@delay.setter
def setDelay(self, val):
if self._delay == val:
return
print(val)
self._delay = val
@QtCore.Property(float)
def xIncrement(self):
return self._xIncrement
@xIncrement.setter
def setXIncrement(self, val):
if self._xIncrement == val:
return
print(val)
self._xIncrement = val
def generatePoint(self):
self._currX += self._xIncrement
self._currY = self._multiplier*(self._currX**self._power)
return self._currX,self._currY
def stop(self):
self._goOn = False
if self._threader is not None:
while self._threader.isRunning():
time.sleep(0.1)
def start(self):
self._goOn = True
self._threader = Threader(self.core, self)
self._threader.start()
def core(self):
while self._goOn:
p = QtCore.QPointF(*self.generatePoint())
self.dataReady.emit(p)
time.sleep(self._delay)
# -------------------------------------------------
class Threader(QtCore.QThread):
def __init__(self,core,parent=None):
super(Threader, self).__init__(parent)
self._core = core
def run(self):
self._core()
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QtWidgets.QApplication(sys.argv)
manager = Manager()
app.aboutToQuit.connect(manager.stop)
manager.start()
engine = QtQml.QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("Manager", manager)
engine.load('main.qml')
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
*.qml
import QtQuick 2.9
import QtCharts 2.2
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.5
import QtQuick.Controls.Material 2.12
ApplicationWindow {
id: mainWindow
width:640
height: 480
title: qsTr("Simple ui")
visible: true
locale:locale
property int controlsColor: Material.DeepPurple
property int controlsAccent: Material.BlueGrey
property real x: 0.0
property int controlsElevation: 6
property int paneElevation: 4
signal reemitted(point p)
Component.onCompleted: Manager.dataReady.connect(mainWindow.reemitted)
onReemitted: {
testXAxis.max = Math.max(testXAxis.max, p.x)
testXAxis.min = Math.min(testXAxis.min, p.x)
testYAxis.max = Math.max(testYAxis.max, p.y)
testYAxis.min = Math.min(testYAxis.min, p.y)
mainLine.append(p.x, p.y)
}
function drawPoint(xy){
mainLine.append(xy[0],xy[1])
if (mainWindow.x >= testXAxis.max){
testXAxis.max = mainWindow.x;
}
if (py >= testYAxis.max){
testYAxis.max = py;
}
if (py <= testYAxis.min){
testYAxis.min = py;
}
}
function clearLine(){
mainLine.clear();
mainLine.append(0,0);
}
Pane{
id: mainPanel
anchors.fill: parent
//Material.theme: Material.Dark
RowLayout{
id: mainRowLO
anchors.fill: parent
spacing: 15
//Chart pane
Pane{
id: chartPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 400
ChartView {
id: testChart
title: "Line"
anchors.fill: parent
antialiasing: true
LineSeries {
id: mainLine
name: "LineSeries"
axisX: ValueAxis{
id: testXAxis
min: 0.0
max: 2.0
}
axisY: ValueAxis{
id: testYAxis
min: 0.0
max: 2.0
}
XYPoint { x: 0; y: 0 }
}
}
}
Pane{
id: controlsPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 200
Layout.maximumWidth: 200
ColumnLayout{
id: controlsColumnLO
anchors.fill: parent
spacing: 40
Label{
id: powerLabel
text: "Exponent"
Layout.topMargin: 40
Layout.leftMargin: 10
Layout.rightMargin: 10
}
SpinBox{
id: powerNum
from: 0
value: 1
to: 5
stepSize: 1
width: 80
validator: DoubleValidator {
bottom: Math.min(powerNum.from, powerNum.to)
top: Math.max(powerNum.from, powerNum.to)
}
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
editable: true
onValueChanged: function(){
Manager.power = value;
}
}
Label{
id: multiplierLabel
text: "Multiplier"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: multiplierSlider
from: -50
value: 1
to: 50
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.multiplier = value;
}
}
Label{
id: multValueLabel
text: String(multiplierSlider.value)
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Label{
id: delayLable
text: "Delay[s]"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: delaySlider
from: 0.05
value: 0.1
to: 1
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.delay = value;
}
}
Label{
id: incrementLable
text: "Increment"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: incrementSlider
from: 1.0
value: 1.0
to: 5.0
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.xIncrement = value;
}
}
Item {
// spacer item
id: controlsSpacer
Layout.fillWidth: true
Layout.fillHeight: true
Pane { anchors.fill: parent }//; Material.background: Material.Light; Material.elevation: 4 } // to visualize the spacer
}
Button{
id: startPointBtn
text: "START"
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
onClicked: function(){
console.log(text);
if(text=="START"){
clearLine();
Manager.starter = true;
text = "STOP";
}
else{
Manager.starter = false;
text = "START";
}
}
}
}
}
}
}
}

The simplest solution is to use Connections but in the case of PySide/PySide2 you can not get the arguments so I'll use the trick they point to in this answer.
If you are going to send a point then use QPoint as it is directly translated to point type in QML. You must also calculate the max and min to update the axes.
Considering the above, the solution is the following:
*.py
import os
import sys
import time
from PySide2 import QtCore, QtWidgets, QtQml
class Manager(QtCore.QObject):
dataReady = QtCore.Signal(QtCore.QPointF, name='dataReady')
def __init__(self, parent=None):
super(Manager, self).__init__(parent)
self._currX = 0
self._currY = 0
self._delay = 0.5
self._multiplier = 1.0
self._power = 1.0
self._xIncrement = 1.0
self._starter = False
self._goOn = False
self._threader = None
@QtCore.Property(bool)
def starter(self):
return self._starter
@starter.setter
def setStarter(self, val):
if self._multiplier == val:
return
print(val)
if val:
self.start()
else:
self.stop()
self._starter = val
@QtCore.Property(float)
def multiplier(self):
return self._multiplier
@multiplier.setter
def setMultiplier(self, val):
if self._multiplier == val:
return
print(val)
self._multiplier = val
@QtCore.Property(int)
def power(self):
return self._power
@power.setter
def setPower(self, val):
if self._power == val:
return
print(val)
self._power = val
@QtCore.Property(float)
def delay(self):
return self._delay
@delay.setter
def setDelay(self, val):
if self._delay == val:
return
print(val)
self._delay = val
@QtCore.Property(float)
def xIncrement(self):
return self._xIncrement
@xIncrement.setter
def setXIncrement(self, val):
if self._xIncrement == val:
return
print(val)
self._xIncrement = val
def generatePoint(self):
self._currX += self._xIncrement
self._currY = self._multiplier*(self._currX**self._power)
return self._currX,self._currY
def stop(self):
self._goOn = False
if self._threader is not None:
while self._threader.isRunning():
time.sleep(0.1)
def start(self):
self._goOn = True
self._threader = Threader(self.core, self)
self._threader.start()
def core(self):
while self._goOn:
p = QtCore.QPointF(*self.generatePoint())
self.dataReady.emit(p)
time.sleep(self._delay)
# -------------------------------------------------
class Threader(QtCore.QThread):
def __init__(self,core,parent=None):
super(Threader, self).__init__(parent)
self._core = core
def run(self):
self._core()
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QtWidgets.QApplication(sys.argv)
manager = Manager()
app.aboutToQuit.connect(manager.stop)
manager.start()
engine = QtQml.QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("Manager", manager)
engine.load('main.qml')
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
*.qml
import QtQuick 2.9
import QtCharts 2.2
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.5
import QtQuick.Controls.Material 2.12
ApplicationWindow {
id: mainWindow
width:640
height: 480
title: qsTr("Simple ui")
visible: true
locale:locale
property int controlsColor: Material.DeepPurple
property int controlsAccent: Material.BlueGrey
property real x: 0.0
property int controlsElevation: 6
property int paneElevation: 4
signal reemitted(point p)
Component.onCompleted: Manager.dataReady.connect(mainWindow.reemitted)
onReemitted: {
testXAxis.max = Math.max(testXAxis.max, p.x)
testXAxis.min = Math.min(testXAxis.min, p.x)
testYAxis.max = Math.max(testYAxis.max, p.y)
testYAxis.min = Math.min(testYAxis.min, p.y)
mainLine.append(p.x, p.y)
}
function drawPoint(xy){
mainLine.append(xy[0],xy[1])
if (mainWindow.x >= testXAxis.max){
testXAxis.max = mainWindow.x;
}
if (py >= testYAxis.max){
testYAxis.max = py;
}
if (py <= testYAxis.min){
testYAxis.min = py;
}
}
function clearLine(){
mainLine.clear();
mainLine.append(0,0);
}
Pane{
id: mainPanel
anchors.fill: parent
//Material.theme: Material.Dark
RowLayout{
id: mainRowLO
anchors.fill: parent
spacing: 15
//Chart pane
Pane{
id: chartPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 400
ChartView {
id: testChart
title: "Line"
anchors.fill: parent
antialiasing: true
LineSeries {
id: mainLine
name: "LineSeries"
axisX: ValueAxis{
id: testXAxis
min: 0.0
max: 2.0
}
axisY: ValueAxis{
id: testYAxis
min: 0.0
max: 2.0
}
XYPoint { x: 0; y: 0 }
}
}
}
Pane{
id: controlsPane
Material.elevation: paneElevation
//Material.background: Material.Grey
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumHeight: 200
Layout.minimumWidth: 200
Layout.maximumWidth: 200
ColumnLayout{
id: controlsColumnLO
anchors.fill: parent
spacing: 40
Label{
id: powerLabel
text: "Exponent"
Layout.topMargin: 40
Layout.leftMargin: 10
Layout.rightMargin: 10
}
SpinBox{
id: powerNum
from: 0
value: 1
to: 5
stepSize: 1
width: 80
validator: DoubleValidator {
bottom: Math.min(powerNum.from, powerNum.to)
top: Math.max(powerNum.from, powerNum.to)
}
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
editable: true
onValueChanged: function(){
Manager.power = value;
}
}
Label{
id: multiplierLabel
text: "Multiplier"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: multiplierSlider
from: -50
value: 1
to: 50
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.multiplier = value;
}
}
Label{
id: multValueLabel
text: String(multiplierSlider.value)
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Label{
id: delayLable
text: "Delay[s]"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: delaySlider
from: 0.05
value: 0.1
to: 1
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.delay = value;
}
}
Label{
id: incrementLable
text: "Increment"
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
}
Slider{
id: incrementSlider
from: 1.0
value: 1.0
to: 5.0
stepSize: 0.01
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.leftMargin: 10
Layout.rightMargin: 10
Layout.fillWidth: true
onValueChanged: function(){
Manager.xIncrement = value;
}
}
Item {
// spacer item
id: controlsSpacer
Layout.fillWidth: true
Layout.fillHeight: true
Pane { anchors.fill: parent }//; Material.background: Material.Light; Material.elevation: 4 } // to visualize the spacer
}
Button{
id: startPointBtn
text: "START"
Material.foreground: controlsColor
Material.accent: controlsAccent
Material.elevation: controlsElevation
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.rightMargin: 10
onClicked: function(){
console.log(text);
if(text=="START"){
clearLine();
Manager.starter = true;
text = "STOP";
}
else{
Manager.starter = false;
text = "START";
}
}
}
}
}
}
}
}

answered Jan 2 at 18:10
eyllanesceyllanesc
85.1k103563
85.1k103563
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54010254%2fconnect-python-signal-to-qml-ui-slot-with-pyside2%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown

provide a Minimal, Complete, and Verifiable example
– eyllanesc
Jan 2 at 17:03
I do not know how to write the code. That's why I'm asking. I have found nothing about this topic and so I have no idea on how a connection between a signal from a python class and a slot on a qml file could be connected
– Lando1784
Jan 2 at 17:26
I'm not asking for the solution, it's obvious that you do not know her, so she asks. What I ask is that you share the code that you indicate you have: I have a QThread (python class) that generates a couple of xy coordinates every 50 milliseconds
– eyllanesc
Jan 2 at 17:28