[英]PySide QML Charts update Series with real-time data
我嘗試使用 OPC UA 協議接收到的新數據動態更新圖表系列
Python 代碼:
class Thread(QThread):
motor1 = Signal(int)
motor2 = Signal(int)
motor3 = Signal(int)
var = Signal(int)
strr = Signal(str)
def run(self):
client.connect()
while True:
d1 = client.get_node("ns=4;s=Deger_1")
d2 = client.get_node("ns=4;s=Deger_2")
d3 = client.get_node("ns=4;s=Deger_3")
button = client.get_node("ns=4;s=QT_Button")
string = client.get_node("ns=4;s=QT_String")
button = button.get_value()
string = string.get_value()
d1 = d1.get_value()
d2 = d2.get_value()
d3 = d3.get_value()
self.motor1.emit(d1)
self.motor2.emit(d2)
self.motor3.emit(d3)
self.var.emit(d1)
self.strr.emit(string)
class ChartModel(QObject):
def __init__(self, parent=None):
super(ChartModel, self).__init__(parent)
self.thread = Thread()
self.thread.var.connect(self.opcua)
self.thread.start()
self.timestamp = time()
self.my_data = []
self.my_list = []
self.index = -1
@Slot(QtCharts.QAbstractSeries)
def update_series(self, series):
self.index += 1
if self.index > 4:
self.index = 0
series.clear()
for p in self.my_data[self.index]:
series.append(p.x(), p.y())
@Slot()
def generateData(self):
for i in range(5):
my_list = []
for j in range(500):
my_list.append(QPoint(j, random.uniform(1, 70)))
self.my_data.append(my_list)
@Slot(int)
def opcua(self, val):
tsignal = time() - self.timestamp
XY = QPoint(tsignal, val)
self.my_list.append(XY)
@Slot()
def get_data(self):
self.my_data.append(self.my_list)
print(len(self.my_data))
class MainWindow(QObject):
def __init__(self):
QObject.__init__(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
main = MainWindow()
chartmodel = ChartModel()
engine = QQmlApplicationEngine()
# engine.rootContext().setContextProperty("backend", main)
engine.rootContext().setContextProperty("chartmodel", chartmodel)
engine.load(os.path.join(os.path.dirname(__file__), "qml/main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
QML代碼
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import QtCharts 2.0
import QtQuick.Controls.Styles 1.0
import QtQuick.Dialogs 1.1
Item {
width: 1000
height: 800
Rectangle {
id: rectangle
property int amountOfData: 0
color: "#27273a"
anchors.fill: parent
Timer{
id: miTimer
interval: 100
running: true
repeat: true
onTriggered: {
chartmodel.update_series(chartViewItem.series(0))
}
}
MessageDialog {
id: msgbox
title: "Error"
text: "Data are not accepted !"
onAccepted: {
msgbox.close();
}
Component.onCompleted: visible = false
}
ChartView {
id: chartViewItem
x: 0
y: 0
width: 752
height: 592
antialiasing: true
theme:ChartView.ChartThemeDark
ValueAxis {
id: axisX
min:0
max:500
}
ValueAxis{
id: axisY
min:0
max:100
}
Rectangle {
id: horizontalScrollMask
visible: false
anchors.fill: parent
}
MouseArea {
id: chartMouseAreaA
anchors.fill: parent
anchors.rightMargin: -8
anchors.bottomMargin: -8
anchors.leftMargin: 8
anchors.topMargin: 8
acceptedButtons: Qt.LeftButton | Qt.RightButton
onMouseXChanged: {
if ((mouse.buttons & Qt.LeftButton) == Qt.LeftButton) {
chartViewItem.scrollLeft(mouseX - horizontalScrollMask.x);
horizontalScrollMask.x = mouseX;
}
}
onPressed: {
if (mouse.button == Qt.LeftButton) {
horizontalScrollMask.x = mouseX;
}
}
}
}
TextField {
id: mintxt
x: 766
y: 68
placeholderText: qsTr("min X")
}
TextField {
id: maxtxt
x: 766
y: 124
placeholderText: qsTr("max X")
}
Button {
id: button
x: 825
y: 176
text: qsTr("Zoom")
onClicked: {
if(mintxt.text>maxtxt.text)
msgbox.open()
else
axisX.min=mintxt.text;
axisX.max=maxtxt.text;
}
}
}
Component.onCompleted: {
var series = chartViewItem.createSeries(ChartView.SeriesTypeSpline,"Random",axisX,axisY)
chartmodel.get_data()
}
}
當我使用chartmodel.generateData()
時,代碼適用於生成的數據,但是當我嘗試get_data
function 時,它返回以下錯誤:
錯誤:列表索引超出范圍
如何用新數據而不是生成的數據更新圖表?
問題是OP在不理解代碼的情況下復制代碼,例如索引是否必要? 索引的目的是什么? 當然,在原始示例中,代碼的作者試圖展示一個顯示循環數據的簡單示例。
在這種情況下,您必須遍歷列表:
import os
import sys
from PySide2.QtCore import *
from PySide2.QtWidgets import *
from PySide2.QtCharts import *
from PySide2.QtQml import *
from time import *
import random
class Thread(QThread):
motor1 = Signal(int)
motor2 = Signal(int)
motor3 = Signal(int)
var = Signal(int)
strr = Signal(str)
def run(self):
client.connect()
while True:
d1 = client.get_node("ns=4;s=Deger_1")
d2 = client.get_node("ns=4;s=Deger_2")
d3 = client.get_node("ns=4;s=Deger_3")
button = client.get_node("ns=4;s=QT_Button")
string = client.get_node("ns=4;s=QT_String")
button = button.get_value()
string = string.get_value()
d1 = d1.get_value()
d2 = d2.get_value()
d3 = d3.get_value()
self.motor1.emit(d1)
self.motor2.emit(d2)
self.motor3.emit(d3)
self.var.emit(d1)
self.strr.emit(string)
class ChartModel(QObject):
def __init__(self, parent=None):
super(ChartModel, self).__init__(parent)
self.thread = Thread()
self.thread.var.connect(self.opcua)
self.thread.start()
self.timestamp = time()
self.my_list = []
@Slot(QtCharts.QAbstractSeries)
def update_series(self, series):
series.clear()
for p in self.my_list:
series.append(p.x(), p.y())
@Slot(int)
def opcua(self, val):
tsignal = time() - self.timestamp
XY = QPoint(tsignal, val)
self.my_list.append(XY)
class MainWindow(QObject):
def __init__(self):
QObject.__init__(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
main = MainWindow()
chartmodel = ChartModel()
engine = QQmlApplicationEngine()
# engine.rootContext().setContextProperty("backend", main)
engine.rootContext().setContextProperty("chartmodel", chartmodel)
engine.load(os.path.join(os.path.dirname(__file__), "qml/main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import QtCharts 2.0
import QtQuick.Controls.Styles 1.0
import QtQuick.Dialogs 1.1
Window {
width: 1000
height: 800
visible: true
Rectangle {
id: rectangle
property int amountOfData: 0
color: "#27273a"
anchors.fill: parent
Timer{
id: miTimer
interval: 100
running: true
repeat: true
onTriggered: {
chartmodel.update_series(chartViewItem.series(0))
}
}
MessageDialog {
id: msgbox
title: "Error"
text: "Data are not accepted !"
onAccepted: {
msgbox.close();
}
Component.onCompleted: visible = false
}
ChartView {
id: chartViewItem
x: 0
y: 0
width: 752
height: 592
antialiasing: true
theme:ChartView.ChartThemeDark
ValueAxis {
id: axisX
min:0
max:500
}
ValueAxis{
id: axisY
min:0
max:100
}
Rectangle {
id: horizontalScrollMask
visible: false
anchors.fill: parent
}
MouseArea {
id: chartMouseAreaA
anchors.fill: parent
anchors.rightMargin: -8
anchors.bottomMargin: -8
anchors.leftMargin: 8
anchors.topMargin: 8
acceptedButtons: Qt.LeftButton | Qt.RightButton
onMouseXChanged: {
if ((mouse.buttons & Qt.LeftButton) == Qt.LeftButton) {
chartViewItem.scrollLeft(mouseX - horizontalScrollMask.x);
horizontalScrollMask.x = mouseX;
}
}
onPressed: {
if (mouse.button == Qt.LeftButton) {
horizontalScrollMask.x = mouseX;
}
}
}
}
TextField {
id: mintxt
x: 766
y: 68
placeholderText: qsTr("min X")
}
TextField {
id: maxtxt
x: 766
y: 124
placeholderText: qsTr("max X")
}
Button {
id: button
x: 825
y: 176
text: qsTr("Zoom")
onClicked: {
if(mintxt.text>maxtxt.text)
msgbox.open()
else
axisX.min=mintxt.text;
axisX.max=maxtxt.text;
}
}
}
Component.onCompleted: {
var series = chartViewItem.createSeries(ChartView.SeriesTypeSpline,"Random",axisX,axisY)
miTimer.start()
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.