如何通过鼠标移动QChart中的系列?

How to move series in QChart by mouse?

我用PyQtChart画了一个图表,想用鼠标移动一个系列。按右键select一个系列,然后将其移动到目标位置,释放右键后将系列移动到目标位置。 我可以得到 update_select_series 中的 selected 系列,如果我可以在按下右键和目标坐标时得到原始坐标,那么我可以将系列移动到 update_series 中的目标位置,但是不知道怎么实现。

import sys
from PyQt5.QtChart import QAreaSeries, QChart, QChartView, QLineSeries, QValueAxis, QCategoryAxis
from PyQt5.QtCore import QPointF, Qt, QTimer
from PyQt5.QtGui import QColor, QGradient, QLinearGradient, QPainter, QPen
from PyQt5.QtWidgets import QApplication, QMainWindow

app = QApplication(sys.argv)

series0 = QLineSeries()

series0 << QPointF(1, 15) << QPointF(3, 17) << QPointF(7, 16) << QPointF(9, 17) \
        << QPointF(12, 16) << QPointF(16, 17) << QPointF(18, 15)

chart = QChart()
chart.addSeries(series0)
chart.createDefaultAxes()
chartView = QChartView(chart)

def update_select_series():
    print('update_select_series')

def update_series():
    print('update_series')

series0.pressed.connect(update_select_series)
series0.released.connect(update_series)

window = QMainWindow()
window.setCentralWidget(chartView)
window.resize(400, 300)
window.show()

sys.exit(app.exec_())

pressed信号包含了按下点的信息,released信号也一样,就是两个点是一样的,所以release信号只会告诉我们什么时候鼠标松开,但放不下

要解决这个问题,你必须获得以下鼠标释放点,为此你可以使用事件mouseReleaseEvent,这个returns坐标中的点QGraphicsView , 那么我们必须将其更改为绘图的坐标,以便我们可以使用此 .

那你就必须给系列传给它了你可以创建一个自定义事件通过postEvent()发送,系列中使用方法customEvent()获取端点的信息。

要移动系列,您将获得点并添加位移,您必须再次插入它。

import sys
from PyQt5.QtChart import QChart, QChartView, QLineSeries
from PyQt5.QtCore import QPointF, QEvent
from PyQt5.QtWidgets import QApplication, QMainWindow

class ReleasePosEvent(QEvent):  
    EventType = QEvent.Type(QEvent.registerEventType())
    def __init__(self, point):
        QEvent.__init__(self, ReleasePosEvent.EventType)
        self.point = point


class ChartView(QChartView):
    def mouseReleaseEvent(self, event):
        p1 = event.pos()
        p2 = self.mapToScene(p1)
        p3 = self.chart().mapFromScene(p2)
        p4 = self.chart().mapToValue(p3)
        if self.chart():
            for serie in self.chart().series():
                QApplication.postEvent(serie, ReleasePosEvent(p4))
        QChartView.mouseReleaseEvent(self, event)


class LineSeries(QLineSeries):
    def __init__(self, *args, **kwargs):
        QLineSeries.__init__(self, *args, **kwargs)
        self.start = QPointF()
        self.pressed.connect(self.on_pressed)

    def on_pressed(self, point):
        self.start = point
        print("on_pressed", point)

    def shift(self, delta):
        if not delta.isNull():
            for ix in range(self.count()):
                p = self.at(ix)
                p += delta
                self.replace(ix, p)

    def customEvent(self, event):
        if event.type() == ReleasePosEvent.EventType:
            if not self.start.isNull():
                dpoint = event.point - self.start
                self.shift(dpoint)
                self.start = QPointF()

app = QApplication(sys.argv)
series0 = LineSeries()

series0 << QPointF(1, 15) << QPointF(3, 17) << QPointF(7, 16) << QPointF(9, 17) \
        << QPointF(12, 16) << QPointF(16, 17) << QPointF(18, 15)

chart = QChart()
chart.addSeries(series0)
chart.createDefaultAxes()
chartView = ChartView(chart)

window = QMainWindow()
window.setCentralWidget(chartView)
window.resize(400, 300)
window.show()

sys.exit(app.exec_())