ich benötige schon wieder eure Hilfe. Mit QChartView will ich ein Linien Diagramm darstellen. Das klappt auch gut wenn ich einen Datensatz habe. In dem Fall geht es um Gewichte, die über die Zeit aufgetragen werden. Wenn ich jetzt in dem Diagramm eine zweite Linie haben möchte, die das Gewicht einer weiteren Person anzeigt, dann bekomme ich die Linie zwar rein, aber entweder bezieht sich die Werte der y-Achse nur auf eine Person oder ich habe zwei y-Achsen bzw. Labes.
Schön wäre es, wenn sich der Wertebereich einer y-Achse entsprechend aller Datensätze so aufteilt, damit man jede Linie zu ordnen kann. Also wenn einer 40kg wiegt und einer 120kg, dann hätte ich gerne eine y- Achse mit dem Wertebereich von 40kg -120kg.
Ich weis das ich gerade soviel Achsen wie Datensätze bekomme, weil alles in der Schleife ist und das wenn ich das aus der Schleife nehme, sich die Achse auf den letzten Datensatz bezieht. Ich weis leider nicht, wie ich mein gewünschtes verhalten hinbekomme.
Code: Alles auswählen
import sys
from csv import DictReader
from json import loads
from pathlib import Path
from PySide6.QtCharts import QChart, QChartView, QDateTimeAxis, QLineSeries, QValueAxis
from PySide6.QtCore import QDateTime, QRegularExpression, Qt
from PySide6.QtGui import QPainter, QRegularExpressionValidator
from PySide6.QtWidgets import QApplication, QHBoxLayout, QSizePolicy, QWidget
from ui_form import Ui_Example
ROOT = Path(__file__).parent
MEMBERS_FILE = ROOT / "members.json"
WEIGHT_FILE = ROOT / "members_to_weight.csv"
TIME_FORMAT = "%d.%m.%Y - %H:%M"
class Example(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_Example()
self.ui.setupUi(self)
self.create_chart()
validator = QRegularExpressionValidator(QRegularExpression(r"^[a-zA-Z\s]*$/"))
self.ui.user_name.setValidator(validator)
self.user_id = None
self.update_chart()
def create_chart(self):
self.chart = QChart()
self.chart.setAnimationOptions(QChart.AllAnimations)
self.chart_view = QChartView(self.chart)
self.chart_view.setRenderHint(QPainter.Antialiasing)
self.main_layout = QHBoxLayout()
size = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
size.setHorizontalStretch(10)
self.chart_view.setSizePolicy(size)
self.main_layout.addWidget(self.chart_view)
self.ui.tabWidget.widget(2).setLayout(self.main_layout)
def update_chart(self):
self.chart.removeAllSeries()
for member in load_members(MEMBERS_FILE)["members"]:
id_, name = [(id_, name) for id_, name in member.items()][0]
series = QLineSeries()
series.setName(name)
for timestamp, weight in get_user_weights(WEIGHT_FILE, id_):
timestamp = (
QDateTime()
.fromString(timestamp, "dd.MM.yyyy - hh:mm")
.toMSecsSinceEpoch()
)
series.append(timestamp, float(weight))
self.chart.addSeries(series)
axis_x = QDateTimeAxis()
axis_x.setTickCount(10)
axis_x.setFormat("dd.MM (hh:mm)")
axis_x.setTitleText("Datum (Uhrzeit)")
self.chart.addAxis(axis_x, Qt.AlignBottom)
series.attachAxis(axis_x)
axis_y = QValueAxis()
axis_y.applyNiceNumbers()
axis_y.setTickCount(10)
axis_y.setLabelFormat("%.2f")
axis_y.setTitleText("Gewicht [kg]")
self.chart.addAxis(axis_y, Qt.AlignLeft)
series.attachAxis(axis_y)
def load_members(file):
return loads(file.read_text(encoding="UTF-8"))
def get_user_weights(file, id_):
with open(file, newline="") as csvfile:
reader = DictReader(csvfile)
return [(row["timestamp"], row["weight"]) for row in reader if row["id"] == id_]
def main():
app = QApplication(sys.argv)
widget = Example()
widget.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()
Dennis
Edit: `create_chart` ist nicht in der `__init__` und das macht man ja eigentlich nicht. Ich hatte keinen besseren Weg gefunden um das Diagramm bei einem Update neu zu zeichnen. Wenn es da was besseres gibt, würde mich das auch freuen.