更新 PYQT5 中的图表数据

Posted

技术标签:

【中文标题】更新 PYQT5 中的图表数据【英文标题】:Update chart data in PYQT5 【发布时间】:2020-01-15 12:47:58 【问题描述】:

我的上一个问题Insert QChartView to ui

def draw_chart(self, obj, chart_view, replace=0):
    obj.setContentsMargins(0, 0, 0, 0)
    lay = QtWidgets.QHBoxLayout(obj)
    lay.setContentsMargins(0, 0, 0, 0)
    if replace:
        # lay.replaceWidget(chart_view)
        pass
    else:
        lay.addWidget(chart_view)

我这样调用这个函数:

    cv1 = self.candle_chart(self.p)
    self.draw_chart(self.chart1, cv1, 0)

candle_chart 返回一个QtChart.QChartView 对象,self.chart1Qwidget 的对象名称。

第一次可以正常使用,但是当我想更新图表时它会出错:

QLayout: Attempting to add QLayout "" to QWidget "chart1", which already has a layout

我正在尝试通过单击按钮来更改图表数据

完整代码:

class Test(base_3, form_3):
    def __init__(self):
        super(base_3, self).__init__()
        self.setupUi(self)

        self.p = [(1, 7380, 7520, 7380, 7510, 7324),
              (2, 7520, 7580, 7410, 7440, 7372),
              (3, 7440, 7650, 7310, 7520, 7434),
              (4, 7450, 7640, 7450, 7550, 7480),
              (5, 7510, 7590, 7460, 7490, 7502),
              (6, 7500, 7590, 7480, 7560, 7512),
              (7, 7560, 7830, 7540, 7800, 7584)]

        self.next.clicked.connect(self.more)

        self.lmt = 3
        self.st = 0

        cv1 = self.candle_chart(self.p[self.st:self.lmt])
        self.draw_chart(self.chart1, cv1, 0)

    def more(self):
        cv1 = self.candle_chart(self.p[self.st:self.lmt])
        self.draw_chart(self.chart1, cv1, 1)

        self.st += 1
        self.lmt += 1

    def draw_chart(self, label, chart_view, replace=0):
        label.setContentsMargins(0, 0, 0, 0)
        lay = QtWidgets.QHBoxLayout(label)
        lay.setContentsMargins(0, 0, 0, 0)
        if replace:
            # lay.replaceWidget(chart_view)
            pass
        else:
            lay.addWidget(chart_view)


    def candle_chart(self, data):
        series = QtChart.QCandlestickSeries()
        series.setDecreasingColor(QtCore.Qt.red)
        series.setIncreasingColor(QtCore.Qt.green)

        tm = []
        i = 0
        for d, o, h, l, c, v in data:
            # x = x[1]
            # series.append(QtChart.QCandlestickSet(x["open"], x["high"], x["low"], x["close"]))
            series.append(QtChart.QCandlestickSet(o, h, l, c))
            tm.append(str(i))
            i += 1

        chart = QtChart.QChart()
        chart.addSeries(series)
        chart.createDefaultAxes()
        chart.legend().hide()
        chart.axisX(series).setCategories(tm)
        chart_view = QtChart.QChartView(chart)
        return chart_view

用户界面代码:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>1381</width>
    <height>680</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="next">
    <property name="geometry">
     <rect>
      <x>490</x>
      <y>540</y>
      <width>88</width>
      <height>33</height>
     </rect>
    </property>
    <property name="text">
     <string>Next</string>
    </property>
   </widget>
   <widget class="QWidget" name="chart1" native="true">
    <property name="enabled">
     <bool>true</bool>
    </property>
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>0</y>
      <width>460</width>
      <height>250</height>
     </rect>
    </property>
   </widget>
   <widget class="QWidget" name="chart2" native="true">
    <property name="geometry">
     <rect>
      <x>460</x>
      <y>0</y>
      <width>460</width>
      <height>250</height>
     </rect>
    </property>
   </widget>
   <widget class="QWidget" name="chart3" native="true">
    <property name="geometry">
     <rect>
      <x>920</x>
      <y>0</y>
      <width>460</width>
      <height>250</height>
     </rect>
    </property>
   </widget>
   <widget class="QWidget" name="chart5" native="true">
    <property name="geometry">
     <rect>
      <x>450</x>
      <y>250</y>
      <width>450</width>
      <height>250</height>
     </rect>
    </property>
   </widget>
   <widget class="QWidget" name="chart6" native="true">
    <property name="geometry">
     <rect>
      <x>900</x>
      <y>250</y>
      <width>450</width>
      <height>250</height>
     </rect>
    </property>
   </widget>
   <widget class="QWidget" name="chart4" native="true">
    <property name="enabled">
     <bool>true</bool>
    </property>
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>250</y>
      <width>450</width>
      <height>250</height>
     </rect>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>1381</width>
     <height>25</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

【问题讨论】:

我已经在上面添加了完整的代码 您的代码不是我认为您应该知道的 MRE,因此如果您需要更多帮助,请提供您被要求的内容或在您的情况下实施我的解决方案。 我已经把代码最小化了。 你可以提供“数据”的例子 已更新...... 【参考方案1】:

您不必更换小部件,最好重复使用,如下所示:

import sys

from PyQt5 import QtCore, QtWidgets, uic, QtChart

# load both ui file
uifile_1 = "UI/main.ui"
form_1, base_1 = uic.loadUiType(uifile_1)


class Example(base_1, form_1):
    def __init__(self):
        super(base_1, self).__init__()
        self.setupUi(self)

        self.series = QtChart.QCandlestickSeries()
        self.series.setDecreasingColor(QtCore.Qt.red)
        self.series.setIncreasingColor(QtCore.Qt.green)

        self.ma5 = QtChart.QLineSeries()  # 5-days average data line

        self.chart = QtChart.QChart()
        self.chart.addSeries(self.series)  # candle
        self.chart.addSeries(self.ma5)  # ma5 line
        self.chart.createDefaultAxes()
        self.chart.legend().hide()
        self.chart.axisX(self.ma5).setVisible(False)

        self.chart.setAnimationOptions(QtChart.QChart.SeriesAnimations)

        self.chartview = QtChart.QChartView(self.chart)

        self.chart_container.setContentsMargins(0, 0, 0, 0)
        lay = QtWidgets.QHBoxLayout(self.chart_container)
        lay.setContentsMargins(0, 0, 0, 0)
        lay.addWidget(self.chartview)

        self.update_data()

        timer = QtCore.QTimer(self, interval=1000, timeout=self.update_data)
        timer.start()

    def update_data(self):

        import random

        data = ((i, *random.sample(range(7000, 8000), 5)) for i in range(7))

        self.series.clear()
        self.ma5.clear()

        tm = []  # stores str type data
        x_min, x_max, y_min, y_max = (
            float("inf"),
            -float("inf"),
            float("inf"),
            -float("inf"),
        )
        # in a loop,  series and ma5 append corresponding data
        for num, o, h, l, c, m in data:
            self.series.append(QtChart.QCandlestickSet(o, h, l, c))
            self.ma5.append(QtCore.QPointF(num, m))
            tm.append(str(num))
            x_min = min(x_min, num)
            x_max = max(x_max, num)
            y_min = min(y_min, m, o, h, l, c)
            y_max = max(y_max, m, o, h, l, c)

        self.chart.axisY(self.series).setMin(y_min)
        self.chart.axisY(self.series).setMax(y_max)
        self.chart.axisX(self.series).setCategories(tm)

        self.chart.axisX(self.ma5).setMin(x_min)
        self.chart.axisX(self.ma5).setMax(x_max)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    ex = Example()
    ex.show()
    sys.exit(app.exec_())

【讨论】:

以上是关于更新 PYQT5 中的图表数据的主要内容,如果未能解决你的问题,请参考以下文章

Matplotlib 和 PyQt5 绘图图

在pyqt5中动态更改数据破折号

PyQt5 - 从 QLineEdit 传递用户输入以更新另一个文件中的字典

PyQT5 实时更新图

尝试使用 PyQt5 获得 GUI 的实时图

PyQt5 - 使用 Line Edit 从编辑窗口更新标签