QChartView soll eine y-Achse für mehrere Datensätze anzeigen.

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Benutzeravatar
Dennis89
User
Beiträge: 1516
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

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()
Danke und Grüße
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.
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
Dennis89
User
Beiträge: 1516
Registriert: Freitag 11. Dezember 2020, 15:13

Guten Morgen,

habe mir jetzt mal so weiter geholfen, das ich alle Gewichte zusätzlich in eine Liste schreibe und die y-Achse dann mait `setMax()` und `setMin()` anpasse.

Code: Alles auswählen

    def update_chart(self):
        self.chart.removeAllSeries()
        weights = []
        for member in load_members(MEMBERS_FILE)["members"]:
            id_, name = list(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))
                weights.append(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.setMax(max(weights))
        axis_y.setMin(min(weights))
        axis_y.setTickCount(10)
        axis_y.setLabelFormat("%.2f")
        axis_y.setTitleText("Gewicht [kg]")
        self.chart.addAxis(axis_y, Qt.AlignLeft)
        series.attachAxis(axis_y)
Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Antworten