PySide QML图表使用实时数据更新系列

2024-06-16 09:34:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试使用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函数时,它返回以下错误:

Error: list index out of range

如何使用新数据而不是生成的数据更新图表


Tags: importselfclientiddatagetindexif
1条回答
网友
1楼 · 发布于 2024-06-16 09:34:13

问题是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()
    }
}

相关问题 更多 >