使用 python 和 QML Oscilloscope 动态绘图效果很好,但相同的程序在树莓派中不起作用,替换功能不起作用

Posted

技术标签:

【中文标题】使用 python 和 QML Oscilloscope 动态绘图效果很好,但相同的程序在树莓派中不起作用,替换功能不起作用【英文标题】:Graphing dynamically with python and QML Oscilloscope works great, but the same program doesn't work in raspberry pi, replace function don't work 【发布时间】:2020-09-02 21:40:42 【问题描述】:

我正在使用 Python 运行 Qt QML 应用程序。我正在使用 qt 图表动态绘制值。为此,我编写了与 Qt 文档中的示波器示例类似的代码,除了我使用 Python 而不是 C++。我首先在 QML 中创建了一个线条系列。然后我使用上下文属性向 QML 公开了一个名为“Bridge”的类作为“con”。在名为“Bridge”的类中,我生成了初始数据。然后我在每次计时器计数时更新图表,方法是将系列传递给“桥”类,然后使用替换函数,以便系列快速获取数据,而不是使用清除和追加。

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()
    

这个 QML 本质上是一个位于中心的图表。在Component.onCompleted 中,我创建了一个使用上下文属性类的线系列,我使用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_())

效果很好。

问题是完全相同的程序在树莓派 3 中不起作用。错误在series.replace(self.my_data[self.index])

显示类型错误:

replace(double,double,double,double) needs 4 argument(s), 1 given!

为了在树莓派上运行代码,我从以下位置安装了Pyside2 库: https://forum.qt.io/topic/112813/installing-pyside2-on-raspberry-pi/7 它的版本是PySide2 5.11.2

对于 QML 模块,我使用了sudo apt-get install qml-module-xxxxxxx 对于每个需要的库

【问题讨论】:

你能指出你在运行help(QtCharts.QLineSeries.replace)时得到了什么吗? 我现在试过了。它显示如下: >>>> help(QtCharts.QLineSeries.replace) 关于method_descriptor的帮助:replace(...) 你确定它只是说“method_descriptor: replace(...)”吗?我希望有更多信息,尝试在覆盆子控制台中运行python -c "from PySide2.QtCharts import QtCharts; help(QtCharts.QLineSeries.replace)" 基本一样。关于 method_descriptor 的帮助:replace(...) (END) 我也在使用 python3 而不是 python。树莓派有 python 3.7.3。此外,我进一步检查并意识到 append 函数也会发生同样的情况。 TypeError: append(double,double) 需要 2 个参数,1 个给定!相同的代码在桌面上运行良好。 试试我的解决方案 【参考方案1】:

一种可能的解决方案是替换

series.replace(self.my_data[self.index])

与:

series.clear()
for p in self.my_data[self.index]:
    series.append(p.x(), p.y())

【讨论】:

这个变通方法使代码在树莓派上运行。现在我可以在树莓派 3 上动态更新图表了。非常感谢您的帮助。现在,我尝试使用 replace 而不是 clear + append 的原因是因为根据 Qt 文档,替换要快得多。在桌面上,我测量了计时器触发之间的时间。使用替换花费的时间更少。我在 pi 上做了同样的事情,列出了 200 个元素,我可以让它在计时器触发之间至少间隔 130 毫秒。也许如果我在 pi4 上运行它,它会运行得更快。我不知道为什么这些 pyside2 函数在 pi 上不起作用。 @ManuelAnatoliyArciaSalmeron 1) 问题不在于 RPI,而在于您使用的 PySide2 非常旧版本。我安装了 PySide2 5.11.2 并且在我的桌面上遇到了同样的错误,可能未来版本的 raspbian(或您使用的发行版)将提供更新的版本。 2)它说的是正确的:替换比清除+附加更快。 3)如果我的回答对您有帮助,请不要忘记标记为正确,如果您不知道该怎么做,请查看tour 是的,我确实使用 Raspbian。你知道是否有办法为树莓派安装更新的 PySide2 或者我交叉编译会更好(必须去学习如何做到这一点)。 @ManuelAnatoliyArciaSalmeron pip 提供的二进制文件不适用于 ARM 架构,因此它们对 RPI 无效,因此如果您想要更新版本的 PySide2,您必须手动编译 PySide2(或者使用交叉编译器或其他方式)

以上是关于使用 python 和 QML Oscilloscope 动态绘图效果很好,但相同的程序在树莓派中不起作用,替换功能不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Python 和 QML 上的多页

从 Python 设置 qml 属性?

QT/QML 数据模型

使用 PySide2 将 python 信号连接到 QML ui 插槽

QML使用Python的函数

从 QML 到 Python Signal/Slots 的数据