I'm trying to make a QtChart updatable when I change a combobox whick contains years. For the purpose of this question I made a list with random data and a shorted version of my project. here is my chart_ui.py from QtDesigner
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.year_ccb = QtWidgets.QComboBox(self.centralwidget)
self.year_ccb.setGeometry(QtCore.QRect(10, 10, 111, 22))
self.year_ccb.setObjectName("year_ccb")
self.chart_fm = QtWidgets.QFrame(self.centralwidget)
self.chart_fm.setGeometry(QtCore.QRect(20, 60, 741, 391))
self.chart_fm.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.chart_fm.setFrameShadow(QtWidgets.QFrame.Raised)
self.chart_fm.setObjectName("chart_fm")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
and here is my main.py file with the example code:
import datetime
import sys
from PyQt5.QtChart import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt, QRect, QPropertyAnimation, QParallelAnimationGroup, QDate
from chart_ui import Ui_MainWindow
class LoginWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
global widgets
widgets = self.ui
self.chart_one_create()
####################################################
years = ('2019', '2020', '2021')
widgets.year_ccb.addItems(years)
widgets.year_ccb.currentIndexChanged.connect(self.chart_one_create)
####################################################
self.show()
def chart_one_create(self):
self.series = QBarSeries()
self.set_tkf = QBarSet("TAEKWON-DO")
self.set_fenc = QBarSet("ΞΙΦΑΣΚΙΑ")
self.set_oplo = QBarSet("ΟΠΛΟΜΑΧΙΑ")
self.set_spends = QBarSet("ΕΞΟΔΑ")
if widgets.year_ccb.currentText() == '2019':
list_of_data = [["1", "2", "3", "4", "5"], [(45, 637, 12, 43), (12, 154, 132, 454),
(435, 117, 212, 453), (45, 657, 112, 455),
(451, 667, 12, 475)]] # manual add data
elif widgets.year_ccb.currentText() == '2020':
list_of_data = [["5", "6", "7", "8", "9"], [(425, 67, 172, 43), (192, 584, 132, 454),
(435, 167, 212, 453), (45, 657, 12, 455),
(453, 667, 162, 475)]] # manual add data
else:
list_of_data = [["10", "11", "12", "13", "14"], [(45, 67, 12, 43), (127, 54, 132, 454),
(435, 187, 212, 453), (45, 657, 152, 455),
(45, 667, 122, 475)]] # manual add data
for i in range(len(list_of_data[0])): # για καθε μηνα που εχει στην πρωτη εσωτερικη λιστα
if list_of_data[1][i][0] is None:
tkd = 0
else:
tkd = list_of_data[1][i][0]
self.set_tkf.append(tkd)
if list_of_data[1][i][1] is None:
fenc = 0
else:
fenc = list_of_data[1][i][1]
self.set_fenc.append(fenc)
if list_of_data[1][i][2] is None:
oplo = 0
else:
oplo = list_of_data[1][i][2]
self.set_oplo.append(oplo)
if list_of_data[1][i][3] is None:
spen = 0
else:
spen = list_of_data[1][i][3]
self.set_spends.append(spen)
self.series.append(self.set_tkf)
self.series.append(self.set_fenc)
self.series.append(self.set_oplo)
self.series.append(self.set_spends)
##############################################################
self.chart = QChart()
self.chart.addSeries(self.series)
self.chart.setTitle("Monthly Stats per Year")
self.chart.setAnimationOptions(QChart.AllAnimations)
self.chart.setTheme(QChart.ChartThemeBrownSand)
self.chart.setBackgroundBrush(QBrush(QColor("transparent")))
self.chart.legend().setVisible(True)
self.chart.legend().setAlignment(Qt.AlignBottom)
##############################################################
self.axisX = QBarCategoryAxis()
self.axisY = QValueAxis()
self.axisY.setRange(0, 3000)
##############################################################
self.categories_months=list_of_data[0]
self.axisX.append(self.categories_months)
self.chart.addAxis(self.axisX, Qt.AlignBottom)
self.chart.addAxis(self.axisY, Qt.AlignLeft)
self.series.attachAxis(self.axisX)
self.series.attachAxis(self.axisY)
##############################################################
self.chartview = QChartView(self.chart)
vbox = QGridLayout(widgets.chart_fm)
vbox.setContentsMargins(0, 0, 0, 0)
vbox.addWidget(self.chartview)
self.update_chart_one()
def update_chart_one(self):
pass
# Create the application object
if __name__ == "__main__":
app = QApplication(sys.argv)
window = LoginWindow()
sys.exit(app.exec_())
So please help me in order to understant what I have to write in def update_chart_one(self): to make my chart refresh its data when I change the year from combobox. Maybe something like:
def update_chart_one(self):
self.series.clear()
self.categories_months.clear()
and then somehow refresh the data in chart.
Chart: Y axis shows the money and in X axis are the months ( first list in data list_of_data[0])
You have to reuse the series by removing the previous data:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QBrush, QColor
from PyQt5.QtWidgets import QApplication, QGridLayout, QMainWindow
from PyQt5.QtChart import (
QBarCategoryAxis,
QBarSeries,
QBarSet,
QChart,
QChartView,
QValueAxis,
)
from chart_ui import Ui_MainWindow
class LoginWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.build_chart()
years = ("2019", "2020", "2021")
self.ui.year_ccb.currentIndexChanged.connect(self.handle_index_changed)
self.ui.year_ccb.addItems(years)
def build_chart(self):
self.series = QBarSeries()
self.set_tkf = QBarSet("TAEKWON-DO")
self.set_fenc = QBarSet("ΞΙΦΑΣΚΙΑ")
self.set_oplo = QBarSet("ΟΠΛΟΜΑΧΙΑ")
self.set_spends = QBarSet("ΕΞΟΔΑ")
self.series.append(self.set_tkf)
self.series.append(self.set_fenc)
self.series.append(self.set_oplo)
self.series.append(self.set_spends)
self.chart = QChart()
self.chart.addSeries(self.series)
self.chart.setTitle("Monthly Stats per Year")
self.chart.setAnimationOptions(QChart.AllAnimations)
self.chart.setTheme(QChart.ChartThemeBrownSand)
self.chart.setBackgroundBrush(QBrush(QColor("transparent")))
self.chart.legend().setVisible(True)
self.chart.legend().setAlignment(Qt.AlignBottom)
self.axisX = QBarCategoryAxis()
self.axisY = QValueAxis()
self.axisY.setRange(0, 3000)
self.chart.addAxis(self.axisX, Qt.AlignBottom)
self.chart.addAxis(self.axisY, Qt.AlignLeft)
self.series.attachAxis(self.axisX)
self.series.attachAxis(self.axisY)
self.chartview = QChartView(self.chart)
vbox = QGridLayout(self.ui.chart_fm)
vbox.setContentsMargins(0, 0, 0, 0)
vbox.addWidget(self.chartview)
def handle_index_changed(self):
default = [
["10", "11", "12", "13", "14"],
[
(45, 67, 12, 43),
(127, 54, 132, 454),
(435, 187, 212, 453),
(45, 657, 152, 455),
(45, 667, 122, 475),
],
]
data = {
"2019": [
["1", "2", "3", "4", "5"],
[
(45, 637, 12, 43),
(12, 154, 132, 454),
(435, 117, 212, 453),
(45, 657, 112, 455),
(451, 667, 12, 475),
],
],
"2020": [
["5", "6", "7", "8", "9"],
[
(425, 67, 172, 43),
(192, 584, 132, 454),
(435, 167, 212, 453),
(45, 657, 12, 455),
(453, 667, 162, 475),
],
],
}
values = data.get(self.ui.year_ccb.currentText(), default)
self.update_chart_one(values)
def update_chart_one(self, datas):
self.axisX.clear()
self.set_tkf.remove(0, self.set_tkf.count())
self.set_fenc.remove(0, self.set_fenc.count())
self.set_oplo.remove(0, self.set_oplo.count())
self.set_spends.remove(0, self.set_spends.count())
categories, data = datas
self.axisX.append(categories)
for tkf, fenc, oplo, spends in data:
self.set_tkf.append(tkf)
self.set_fenc.append(fenc)
self.set_oplo.append(oplo)
self.set_spends.append(spends)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = LoginWindow()
window.show()
sys.exit(app.exec_())