Как создать подкласс QPointF и установить пользовательский атрибут? - PullRequest
1 голос
/ 02 ноября 2019

В моем графике мне нужно хранить много информации в каждом QPointF, но когда я делаю подкласс QPointF, кажется, что это не имеет никакого эффекта, может кто-нибудь дать мне хорошее решение или идею?

Код:

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtPrintSupport import *
from PyQt5.QtChart import *
import random

class MyPoint(QPointF):
    def __init__(self, *args):
        super().__init__(*args)

    def set_name(self, name):
        self.name = name

    def set_info(self, info):
        self.info = info


class DemoChar(QChartView):
    def __init__(self):
        super().__init__()
        self.setRenderHint(QPainter.Antialiasing)
        self.chart = QChart()
        self.chart.setTitle('Demo')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.setChart(self.chart)
        self.lineItem = QGraphicsLineItem(self.chart)

        series = QLineSeries(name="random serie")
        series.setPointsVisible(True)
        series.clicked.connect(self.on_click)

        self.series = series

        for i in range(20):
            #series << QPointF(0.1 * i, random.uniform(-10, 10))
            pt = MyPoint( 0.1 * i, random.uniform(-10, 10) )
            pt.set_name(str(pt))
            pt.set_info(str(random.randint(1, 100)))
            series << pt

        self.chart.addSeries(series)
        self.chart.createDefaultAxes()

    def on_click(self, pt):
        one_pt = self.series.pointsVector()[0]
        print(one_pt)
       # print(one_pt.name)  #the point have no name, info attribute

app = QApplication([])
demo = DemoChar()
demo.show()
app.exec()

1 Ответ

1 голос
/ 02 ноября 2019

Когда вы передаете QPointF в QLineSeries, используется конструктор копирования, который копирует только значения x и y, то есть он не копирует объект, а только некоторые атрибуты.

Поэтому вместо реализациипользовательский QPointF лучше реализовать модель, которая отображается на QLineSeries с использованием QVXYModelMapper:

import random

from PyQt5.QtCore import pyqtSlot, QPointF, Qt
from PyQt5.QtGui import QPainter, QStandardItem, QStandardItemModel
from PyQt5.QtWidgets import QApplication
from PyQt5.QtChart import QChart, QChartView, QLineSeries, QVXYModelMapper


class CustomModel(QStandardItemModel):
    def add_point(self, pt, name="", info=""):
        items = []
        for value in (pt.x(), pt.y(), name, info):
            it = QStandardItem()
            it.setData(value, Qt.DisplayRole)
            items.append(it)
        self.appendRow(items)

    def get_data(self, row):
        if 0 <= row < self.rowCount():
            pt = QPointF(
                self.item(row, 0).data(Qt.DisplayRole),
                self.item(row, 1).data(Qt.DisplayRole),
            )
            name = self.item(row, 2).data(Qt.DisplayRole)
            info = self.item(row, 3).data(Qt.DisplayRole)
            return pt, name, info


class DemoChar(QChartView):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setRenderHint(QPainter.Antialiasing)
        self.chart = QChart()
        self.chart.setTitle("Demo")
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.setChart(self.chart)

        self.model = CustomModel()
        self.series = QLineSeries(name="random serie")
        self.series.setPointsVisible(True)
        self.series.clicked.connect(self.on_click)

        self.mapper = QVXYModelMapper(xColumn=0, yColumn=1)
        self.mapper.setModel(self.model)
        self.mapper.setSeries(self.series)

        for i in range(20):
            pt = QPointF(0.1 * i, random.uniform(-10, 10))
            name = "name-{}".format(i)
            info = str(random.randint(1, 100))
            self.model.add_point(pt, name, info)

        self.chart.addSeries(self.series)
        self.chart.createDefaultAxes()

    @pyqtSlot(QPointF)
    def on_click(self, pt):
        # first point
        index = 0
        value = self.model.get_data(index)
        if value is not None:
            pt, name, info = value
            print(pt, name, info)


def main(args):
    app = QApplication(args)
    demo = DemoChar()
    demo.show()
    ret = app.exec()


if __name__ == "__main__":
    import sys

    sys.exit(main(sys.argv))
...