Connect python signal to QML ui slot with PySide2












1















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);
}
}
}
}
}
}
}
}









share|improve this question

























  • 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


















1















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);
}
}
}
}
}
}
}
}









share|improve this question

























  • 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
















1












1








1








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);
}
}
}
}
}
}
}
}









share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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





















  • 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














1 Answer
1






active

oldest

votes


















0














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";
}
}
}
}
}
}
}
}


enter image description here






share|improve this answer
























    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
    });


    }
    });














    draft saved

    draft discarded


















    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









    0














    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";
    }
    }
    }
    }
    }
    }
    }
    }


    enter image description here






    share|improve this answer




























      0














      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";
      }
      }
      }
      }
      }
      }
      }
      }


      enter image description here






      share|improve this answer


























        0












        0








        0







        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";
        }
        }
        }
        }
        }
        }
        }
        }


        enter image description here






        share|improve this answer













        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";
        }
        }
        }
        }
        }
        }
        }
        }


        enter image description here







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 2 at 18:10









        eyllanesceyllanesc

        85.1k103563




        85.1k103563
































            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            The term 'EXEC' is not recognized as the name of a cmdlet Powershell

            NPM command prompt closes immediately [closed]

            Error binding properties and functions in emscripten