I am running a Qt QML application with Python. I am graphing values using qt charts dynamically. To do this I made a similar code as in the oscilloscope example from Qt documentation, except that instead of C++ I used Python. I first created a line series in QML. Then I exposed a class called "Bridge" as "con" to QML using context property. Inside the class called "Bridge", I generated the initial data. Then I am updating the chart every time the timer counts by passing the series to the "Bridge" class and then using the replace function so that the series gets the data fastly instead of using clear and append.
import QtQuick 2.10
import QtQuick.Window 2.5
import QtQuick.Controls 2.4
import QtCharts 2.0
Window {
id: window
title: qsTr("QML and Python graphing dynamically")
width: 640
height: 480
color: "#1b480d"
visible: true
Timer{
id: miTimer
interval: 1 / 24 * 1000 //update every 200ms
running: true
repeat: true
onTriggered: {
con.update_series(chart.series(0))
}
}
Label {
id: label
x: 298
color: "#f1f3f4"
text: qsTr("Graphin dynamically with python")
anchors.horizontalCenterOffset: 0
anchors.top: parent.top
anchors.topMargin: 10
font.bold: true
font.pointSize: 25
anchors.horizontalCenter: parent.horizontalCenter
}
ChartView {
id: chart
x: 180
y: 90
width: 500
height: 300
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
ValueAxis{
id: axisX
min: 0
max: 200
}
ValueAxis{
id: axisY
min: 0
max: 100
}
}
Component.onCompleted: {
console.log("Se ha iniciado QML\n")
var series = chart.createSeries(ChartView.SeriesTypeLine,"My grafico",axisX,axisY)
con.generateData()
}
}
This QML essentially is a chart in the center. In Component.onCompleted
, I create a line series which is using a context property class, I update it using python.
# This Python file uses the following encoding: utf-8
import sys
from os.path import abspath, dirname, join
import random
from PySide2.QtCore import QObject, Slot, QPoint
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCharts import QtCharts
from PySide2.QtWidgets import QApplication # <---
class Bridge(QObject):
def __init__(self, parent=None):
super(Bridge, self).__init__(parent)
self.my_data = []
self.index = -1
@Slot(QtCharts.QAbstractSeries)
def update_series(self, series):
self.index += 1
if(self.index > 4):
self.index = 0
series.replace(self.my_data[self.index])
@Slot()
def generateData(self):
my_data = []
for i in range (5):
my_list = []
for j in range(200):
my_list.append(QPoint(j,random.uniform(0,100)))
self.my_data.append(my_list)
if __name__ == "__main__":
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
bridge = Bridge()
# Expose the Python object to QML
context = engine.rootContext()
context.setContextProperty("con", bridge)
#engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
# Get the path of the current directory, and then add the name
# of the QML file, to load it.
qmlFile = join(dirname(__file__), 'main.qml')
engine.load(abspath(qmlFile))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
It works nicely.
The problem is that the exact same program doesn't work in the raspberry pi 3. The error is on series.replace(self.my_data[self.index])
It says TypeError:
replace(double,double,double,double) needs 4 argument(s), 1 given!
To run the code on the raspberry pi I installed Pyside2
libraries from:
https://forum.qt.io/topic/112813/installing-pyside2-on-raspberry-pi/7
Its version is PySide2 5.11.2
.
And for QML modules I used sudo apt-get install qml-module-xxxxxxx
for each needed library
One possible solution is to replace
series.replace(self.my_data[self.index])
with:
series.clear()
for p in self.my_data[self.index]:
series.append(p.x(), p.y())