diff --git a/PyQtChart练习/charts/README.md b/PyQtChart练习/charts/README.md new file mode 100644 index 0000000..4b7e5bd --- /dev/null +++ b/PyQtChart练习/charts/README.md @@ -0,0 +1,8 @@ +# PyQtChart练习 + +[百度 echarts 折线图demo](http://echarts.baidu.com/examples.html#chart-type-line) + +### [Python3.5 or latter][PyQt5 PyQtChart] + +### [1.折线图](line/) + - [1.折线图堆叠](line/LineStack.py) \ No newline at end of file diff --git a/PyQtChart练习/charts/line/LineStack.py b/PyQtChart练习/charts/line/LineStack.py index eabeee2..d8cf704 100644 --- a/PyQtChart练习/charts/line/LineStack.py +++ b/PyQtChart练习/charts/line/LineStack.py @@ -12,10 +12,12 @@ Created on 2017年12月28日 import sys -from PyQt5.QtChart import QChartView, QChart, QLineSeries -from PyQt5.QtCore import Qt, QPointF +from PyQt5.QtChart import QChartView, QChart, QLineSeries, QLegend,\ + QCategoryAxis +from PyQt5.QtCore import Qt, QPointF, QRectF, QPoint from PyQt5.QtGui import QPainter, QPen -from PyQt5.QtWidgets import QApplication, QGraphicsLineItem +from PyQt5.QtWidgets import QApplication, QGraphicsLineItem, QWidget, \ + QHBoxLayout, QLabel, QVBoxLayout, QGraphicsProxyWidget __Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com" @@ -23,14 +25,86 @@ __Copyright__ = "Copyright (c) 2017 Irony.\"[讽刺]" __Version__ = "Version 1.0" +class ToolTipItem(QWidget): + + def __init__(self, color, text, parent=None): + super(ToolTipItem, self).__init__(parent) + layout = QHBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + clabel = QLabel(self) + clabel.setMinimumSize(12, 12) + clabel.setMaximumSize(12, 12) + clabel.setStyleSheet("border-radius:6px;background: rgba(%s,%s,%s,%s);" % ( + color.red(), color.green(), color.blue(), color.alpha())) + layout.addWidget(clabel) + self.textLabel = QLabel(text, self, styleSheet="color:white;") + layout.addWidget(self.textLabel) + + def setText(self, text): + self.textLabel.setText(text) + + +class ToolTipWidget(QWidget): + + Cache = {} + + def __init__(self, *args, **kwargs): + super(ToolTipWidget, self).__init__(*args, **kwargs) + self.setAttribute(Qt.WA_StyledBackground, True) + self.setStyleSheet( + "ToolTipWidget{background: rgba(50, 50, 50, 100);}") + layout = QVBoxLayout(self) + self.titleLabel = QLabel(self, styleSheet="color:white;") + layout.addWidget(self.titleLabel) + + def updateUi(self, title, points): + self.titleLabel.setText(title) + for serie, point in points: + if serie not in self.Cache: + item = ToolTipItem( + serie.color(), + (serie.name() or "-") + ":" + str(point.y()), self) + self.layout().addWidget(item) + self.Cache[serie] = item + else: + self.Cache[serie].setText( + (serie.name() or "-") + ":" + str(point.y())) + + +class GraphicsProxyWidget(QGraphicsProxyWidget): + + def __init__(self, *args, **kwargs): + super(GraphicsProxyWidget, self).__init__(*args, **kwargs) + self.setZValue(999) + self.tipWidget = ToolTipWidget() + self.setWidget(self.tipWidget) + self.hide() + + def width(self): + return self.size().width() + + def height(self): + return self.size().height() + + def show(self, title, points, pos): + self.setGeometry(QRectF(pos, self.size())) + self.tipWidget.updateUi(title, points) + super(GraphicsProxyWidget, self).show() + + class ChartView(QChartView): def __init__(self, *args, **kwargs): super(ChartView, self).__init__(*args, **kwargs) self.resize(800, 600) self.setRenderHint(QPainter.Antialiasing) # 抗锯齿 + # 自定义x轴label + self.category = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"] self.initChart() + # 提示widget + self.toolTipWidget = GraphicsProxyWidget(self._chart) + # line self.lineItem = QGraphicsLineItem(self._chart) pen = QPen(Qt.gray) @@ -39,29 +113,110 @@ class ChartView(QChartView): self.lineItem.setZValue(998) self.lineItem.hide() - def mouseMoveEvent(self, event): - super(ChartView, self).mouseMoveEvent(event) + # 一些固定计算,减少mouseMoveEvent中的计算量 # 获取x和y轴的最小最大值 axisX, axisY = self._chart.axisX(), self._chart.axisY() - min_x, max_x = axisX.min(), axisX.max() - min_y, max_y = axisY.min(), axisY.max() + self.min_x, self.max_x = axisX.min(), axisX.max() + self.min_y, self.max_y = axisY.min(), axisY.max() # 坐标系中左上角顶点 - point_top = self._chart.mapToPosition(QPointF(min_x, max_y)) + self.point_top = self._chart.mapToPosition( + QPointF(self.min_x, self.max_y)) # 坐标原点坐标 - point_bottom = self._chart.mapToPosition(QPointF(min_x, min_y)) - step_x = (max_x - min_x) / (axisX.tickCount() - 1) + self.point_bottom = self._chart.mapToPosition( + QPointF(self.min_x, self.min_y)) + self.step_x = (self.max_x - self.min_x) / (axisX.tickCount() - 1) + + def mouseMoveEvent(self, event): + super(ChartView, self).mouseMoveEvent(event) + pos = event.pos() # 把鼠标位置所在点转换为对应的xy值 - x = self._chart.mapToValue(event.pos()).x() - index = round((x - min_x) / step_x) - pos_x = self._chart.mapToPosition( - QPointF(index * step_x + min_x, min_y)) - self.lineItem.setLine(pos_x.x(), point_top.y(), - pos_x.x(), point_bottom.y()) - self.lineItem.show() + x = self._chart.mapToValue(pos).x() + y = self._chart.mapToValue(pos).y() + index = round((x - self.min_x) / self.step_x) + # 得到在坐标系中的所有series的类型和点 + points = [(serie, serie.at(index)) + for serie in self._chart.series() if self.min_x <= x <= self.max_x and self.min_y <= y <= self.max_y] + if points: + pos_x = self._chart.mapToPosition( + QPointF(index * self.step_x + self.min_x, self.min_y)) + self.lineItem.setLine(pos_x.x(), self.point_top.y(), + pos_x.x(), self.point_bottom.y()) + self.lineItem.show() + try: + title = self.category[index] + except: + title = "" + t_width = self.toolTipWidget.width() + t_height = self.toolTipWidget.height() + # 如果鼠标位置离右侧的距离小于tip宽度 + x = pos.x() - t_width if self.width() - \ + pos.x() - 20 < t_width else pos.x() + # 如果鼠标位置离底部的高度小于tip高度 + y = pos.y() - t_height if self.height() - \ + pos.y() - 20 < t_height else pos.y() + self.toolTipWidget.show( + title, points, QPoint(x, y)) + else: + self.toolTipWidget.hide() + self.lineItem.hide() + + def handleMarkerClicked(self): + marker = self.sender() # 信号发送者 + if not marker: + return + visible = not marker.series().isVisible() +# # 隐藏或显示series + marker.series().setVisible(visible) + marker.setVisible(True) # 要保证marker一直显示 + # 透明度 + alpha = 1.0 if visible else 0.4 + # 设置label的透明度 + brush = marker.labelBrush() + color = brush.color() + color.setAlphaF(alpha) + brush.setColor(color) + marker.setLabelBrush(brush) + # 设置marker的透明度 + brush = marker.brush() + color = brush.color() + color.setAlphaF(alpha) + brush.setColor(color) + marker.setBrush(brush) + # 设置画笔透明度 + pen = marker.pen() + color = pen.color() + color.setAlphaF(alpha) + pen.setColor(color) + marker.setPen(pen) + + def handleMarkerHovered(self, status): + # 设置series的画笔宽度 + marker = self.sender() # 信号发送者 + if not marker: + return + series = marker.series() + if not series: + return + pen = series.pen() + if not pen: + return + pen.setWidth(pen.width() + (1 if status else -1)) + series.setPen(pen) + + def handleSeriesHoverd(self, point, state): + # 设置series的画笔宽度 + series = self.sender() # 信号发送者 + pen = series.pen() + if not pen: + return + pen.setWidth(pen.width() + (1 if state else -1)) + series.setPen(pen) def initChart(self): self._chart = QChart(title="折线图堆叠") self._chart.setAcceptHoverEvents(True) + # Series动画 + self._chart.setAnimationOptions(QChart.SeriesAnimations) dataTable = [ ["邮件营销", [120, 132, 101, 134, 90, 230, 210]], ["联盟广告", [220, 182, 191, 234, 290, 330, 310]], @@ -75,6 +230,7 @@ class ChartView(QChartView): series.append(j, v) series.setName(series_name) series.setPointsVisible(True) # 显示圆点 + series.hovered.connect(self.handleSeriesHoverd) # 鼠标悬停 self._chart.addSeries(series) self._chart.createDefaultAxes() # 创建默认的轴 axisX = self._chart.axisX() # x轴 @@ -83,6 +239,27 @@ class ChartView(QChartView): axisY = self._chart.axisY() axisY.setTickCount(7) # y轴设置7个刻度 axisY.setRange(0, 1500) # 设置y轴范围 + # 自定义x轴 + axis_x = QCategoryAxis( + self._chart, labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue) + axis_x.setTickCount(7) + axis_x.setGridLineVisible(False) + min_x = axisX.min() + max_x = axisX.max() + step = (max_x - min_x) / (7 - 1) # 7个tick + for i in range(0, 7): + axis_x.append(self.category[i], min_x + i * step) + self._chart.setAxisX(axis_x, self._chart.series()[-1]) + # chart的图例 + legend = self._chart.legend() + # 设置图例由Series来决定样式 + legend.setMarkerShape(QLegend.MarkerShapeFromSeries) + # 遍历图例上的标记并绑定信号 + for marker in legend.markers(): + # 点击事件 + marker.clicked.connect(self.handleMarkerClicked) + # 鼠标悬停事件 + marker.hovered.connect(self.handleMarkerHovered) self.setChart(self._chart) diff --git a/PyQtChart练习/charts/line/README.md b/PyQtChart练习/charts/line/README.md new file mode 100644 index 0000000..e4ac2eb --- /dev/null +++ b/PyQtChart练习/charts/line/README.md @@ -0,0 +1,4 @@ +# 折线图 + +### [1.折线图堆叠](LineStack.py) +![折线图堆叠](ScreenShot/LineStack.gif) \ No newline at end of file diff --git a/PyQtChart练习/charts/line/ScreenShot/LineStack.gif b/PyQtChart练习/charts/line/ScreenShot/LineStack.gif new file mode 100644 index 0000000..3c11f2d Binary files /dev/null and b/PyQtChart练习/charts/line/ScreenShot/LineStack.gif differ diff --git a/PyQtChart练习/test/LineChart.py b/PyQtChart练习/test/LineChart.py index 579a00f..526c651 100644 --- a/PyQtChart练习/test/LineChart.py +++ b/PyQtChart练习/test/LineChart.py @@ -1,36 +1,36 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -''' -Created on 2017年12月19日 -@author: Irony."[讽刺] -@site: http://alyl.vip, http://orzorz.vip, http://coding.net/u/892768447, http://github.com/892768447 -@email: 892768447@qq.com -@file: LineChart -@description: -''' -import sys - -from PyQt5.QtChart import QChartView, QLineSeries, QChart -from PyQt5.QtGui import QPainter -from PyQt5.QtWidgets import QApplication - - -__version__ = "0.0.1" - - -if __name__ == "__main__": - app = QApplication(sys.argv) - chart = QChart() - chart.setTitle("Line Chart 1") - series = QLineSeries(chart) - series.append(0, 6) - series.append(2, 4) - chart.addSeries(series) - chart.createDefaultAxes() # 创建默认轴 - - view = QChartView(chart) - view.setRenderHint(QPainter.Antialiasing) # 抗锯齿 - view.resize(800, 600) - view.show() - sys.exit(app.exec_()) +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +''' +Created on 2017年12月19日 +@author: Irony."[讽刺] +@site: http://alyl.vip, http://orzorz.vip, http://coding.net/u/892768447, http://github.com/892768447 +@email: 892768447@qq.com +@file: LineChart +@description: +''' +import sys + +from PyQt5.QtChart import QChartView, QLineSeries, QChart +from PyQt5.QtGui import QPainter +from PyQt5.QtWidgets import QApplication + + +__version__ = "0.0.1" + + +if __name__ == "__main__": + app = QApplication(sys.argv) + chart = QChart() + chart.setTitle("Line Chart 1") + series = QLineSeries(chart) + series.append(0, 6) + series.append(2, 4) + chart.addSeries(series) + chart.createDefaultAxes() # 创建默认轴 + + view = QChartView(chart) + view.setRenderHint(QPainter.Antialiasing) # 抗锯齿 + view.resize(800, 600) + view.show() + sys.exit(app.exec_()) diff --git a/PyQtChart练习/test/LineChart自定义xy轴.py b/PyQtChart练习/test/LineChart自定义xy轴.py index 0f8904a..cf8ecd5 100644 --- a/PyQtChart练习/test/LineChart自定义xy轴.py +++ b/PyQtChart练习/test/LineChart自定义xy轴.py @@ -1,147 +1,147 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -''' -Created on 2017年12月19日 -@author: Irony."[讽刺] -@site: http://alyl.vip, http://orzorz.vip, http://coding.net/u/892768447, http://github.com/892768447 -@email: 892768447@qq.com -@file: LineChart自定义xy轴 -@description: -''' -import random -import sys - -from PyQt5.QtChart import QChartView, QLineSeries, QChart, QCategoryAxis -from PyQt5.QtCore import Qt -from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout - - -__version__ = "0.0.1" - -m_listCount = 3 -m_valueMax = 10 -m_valueCount = 7 - - -def generateRandomData(listCount, valueMax, valueCount): - random.seed() - dataTable = [] - for i in range(listCount): - dataList = [] - yValue = 0.0 - f_valueCount = float(valueCount) - for j in range(valueCount): - yValue += random.uniform(0, valueMax) / f_valueCount - value = j + random.random() * m_valueMax / f_valueCount, yValue - label = "Slice " + str(i) + ":" + str(j) - dataList.append((value, label)) - dataTable.append(dataList) - return dataTable - - -m_dataTable = generateRandomData(m_listCount, m_valueMax, m_valueCount) - - -def getChart(title): - chart = QChart(title=title) - for i, data_list in enumerate(m_dataTable): - series = QLineSeries(chart) - for value, _ in data_list: - series.append(*value) - series.setName("Series " + str(i)) - chart.addSeries(series) - chart.createDefaultAxes() # 创建默认的轴 - return chart - - -def customAxisX(chart): - # 自定义x轴(均分) - series = chart.series() - if not series: - return - axisx = QCategoryAxis( - chart, labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue) - minx = chart.axisX().min() - maxx = chart.axisX().max() - tickc = chart.axisX().tickCount() - if tickc < 2: - axisx.append("lable0", minx) - else: - step = (maxx - minx) / (tickc - 1) # tickc>=2 - for i in range(0, tickc): - axisx.append("lable%s" % i, minx + i * step) - chart.setAxisX(axisx, series[-1]) - - -def customTopAxisX(chart): - # 自定义top x轴 - series = chart.series() - if not series: - return - category = ["%d月" % i for i in range(1, 9)] # 1-8月 - axisx = QCategoryAxis( - chart, labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue) - axisx.setGridLineVisible(False) # 隐藏网格线条 - axisx.setTickCount(len(category)) # 设置刻度个数 - chart.axisX().setTickCount(len(category)) # 强制修改x轴的刻度个数一致 - minx = chart.axisX().min() - maxx = chart.axisX().max() - tickc = chart.axisX().tickCount() - step = (maxx - minx) / (tickc - 1) # tickc>=2 - for i in range(0, tickc): - axisx.append(category[i], minx + i * step) - chart.addAxis(axisx, Qt.AlignTop) # 添加到右侧 - series[-1].attachAxis(axisx) # 附加到series上 - - -def customAxisY(chart): - # 自定义y轴(不等分) - series = chart.series() - if not series: - return - category = ["周一", "周二", "周三", "周四", - "周五", "周六", "周日"] - axisy = QCategoryAxis( - chart, labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue) - axisy.setGridLineVisible(False) # 隐藏网格线条 - axisy.setTickCount(len(category)) # 设置刻度个数 - miny = chart.axisY().min() - maxy = chart.axisY().max() - tickc = axisy.tickCount() - if tickc < 2: - axisy.append(category[0]) - else: - step = (maxy - miny) / (tickc - 1) # tickc>=2 - for i in range(0, tickc): - axisy.append(category[i], miny + i * step) - chart.addAxis(axisy, Qt.AlignRight) # 添加到右侧 - series[-1].attachAxis(axisy) # 附加到series上 - - -class Window(QWidget): - - def __init__(self, *args, **kwargs): - super(Window, self).__init__(*args, **kwargs) - layout = QHBoxLayout(self) - - # 自定义x轴(和原来的x轴值对应等分) - chart = getChart("自定义x轴(和原来的x轴值对应等分)") - customAxisX(chart) - layout.addWidget(QChartView(chart, self)) - # 自定义添加右侧y轴(等分,与左侧不对应) - chart = getChart("自定义添加右侧y轴(等分,与左侧不对应)") - customAxisY(chart) - layout.addWidget(QChartView(chart, self)) - # 自定义top x轴(按现有新的x轴划分) - chart = getChart("自定义top x轴(按现有新的x轴划分)") - customTopAxisX(chart) - layout.addWidget(QChartView(chart, self)) - - -if __name__ == "__main__": - app = QApplication(sys.argv) - view = Window() - view.resize(800, 600) - view.show() - sys.exit(app.exec_()) +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +''' +Created on 2017年12月19日 +@author: Irony."[讽刺] +@site: http://alyl.vip, http://orzorz.vip, http://coding.net/u/892768447, http://github.com/892768447 +@email: 892768447@qq.com +@file: LineChart自定义xy轴 +@description: +''' +import random +import sys + +from PyQt5.QtChart import QChartView, QLineSeries, QChart, QCategoryAxis +from PyQt5.QtCore import Qt +from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout + + +__version__ = "0.0.1" + +m_listCount = 3 +m_valueMax = 10 +m_valueCount = 7 + + +def generateRandomData(listCount, valueMax, valueCount): + random.seed() + dataTable = [] + for i in range(listCount): + dataList = [] + yValue = 0.0 + f_valueCount = float(valueCount) + for j in range(valueCount): + yValue += random.uniform(0, valueMax) / f_valueCount + value = j + random.random() * m_valueMax / f_valueCount, yValue + label = "Slice " + str(i) + ":" + str(j) + dataList.append((value, label)) + dataTable.append(dataList) + return dataTable + + +m_dataTable = generateRandomData(m_listCount, m_valueMax, m_valueCount) + + +def getChart(title): + chart = QChart(title=title) + for i, data_list in enumerate(m_dataTable): + series = QLineSeries(chart) + for value, _ in data_list: + series.append(*value) + series.setName("Series " + str(i)) + chart.addSeries(series) + chart.createDefaultAxes() # 创建默认的轴 + return chart + + +def customAxisX(chart): + # 自定义x轴(均分) + series = chart.series() + if not series: + return + axisx = QCategoryAxis( + chart, labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue) + minx = chart.axisX().min() + maxx = chart.axisX().max() + tickc = chart.axisX().tickCount() + if tickc < 2: + axisx.append("lable0", minx) + else: + step = (maxx - minx) / (tickc - 1) # tickc>=2 + for i in range(0, tickc): + axisx.append("lable%s" % i, minx + i * step) + chart.setAxisX(axisx, series[-1]) + + +def customTopAxisX(chart): + # 自定义top x轴 + series = chart.series() + if not series: + return + category = ["%d月" % i for i in range(1, 9)] # 1-8月 + axisx = QCategoryAxis( + chart, labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue) + axisx.setGridLineVisible(False) # 隐藏网格线条 + axisx.setTickCount(len(category)) # 设置刻度个数 + chart.axisX().setTickCount(len(category)) # 强制修改x轴的刻度个数一致 + minx = chart.axisX().min() + maxx = chart.axisX().max() + tickc = chart.axisX().tickCount() + step = (maxx - minx) / (tickc - 1) # tickc>=2 + for i in range(0, tickc): + axisx.append(category[i], minx + i * step) + chart.addAxis(axisx, Qt.AlignTop) # 添加到右侧 + series[-1].attachAxis(axisx) # 附加到series上 + + +def customAxisY(chart): + # 自定义y轴(不等分) + series = chart.series() + if not series: + return + category = ["周一", "周二", "周三", "周四", + "周五", "周六", "周日"] + axisy = QCategoryAxis( + chart, labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue) + axisy.setGridLineVisible(False) # 隐藏网格线条 + axisy.setTickCount(len(category)) # 设置刻度个数 + miny = chart.axisY().min() + maxy = chart.axisY().max() + tickc = axisy.tickCount() + if tickc < 2: + axisy.append(category[0]) + else: + step = (maxy - miny) / (tickc - 1) # tickc>=2 + for i in range(0, tickc): + axisy.append(category[i], miny + i * step) + chart.addAxis(axisy, Qt.AlignRight) # 添加到右侧 + series[-1].attachAxis(axisy) # 附加到series上 + + +class Window(QWidget): + + def __init__(self, *args, **kwargs): + super(Window, self).__init__(*args, **kwargs) + layout = QHBoxLayout(self) + + # 自定义x轴(和原来的x轴值对应等分) + chart = getChart("自定义x轴(和原来的x轴值对应等分)") + customAxisX(chart) + layout.addWidget(QChartView(chart, self)) + # 自定义添加右侧y轴(等分,与左侧不对应) + chart = getChart("自定义添加右侧y轴(等分,与左侧不对应)") + customAxisY(chart) + layout.addWidget(QChartView(chart, self)) + # 自定义top x轴(按现有新的x轴划分) + chart = getChart("自定义top x轴(按现有新的x轴划分)") + customTopAxisX(chart) + layout.addWidget(QChartView(chart, self)) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + view = Window() + view.resize(800, 600) + view.show() + sys.exit(app.exec_()) diff --git a/PyQtChart练习/test/ToolTip2.py b/PyQtChart练习/test/ToolTip2.py index 458a428..3faeb14 100644 --- a/PyQtChart练习/test/ToolTip2.py +++ b/PyQtChart练习/test/ToolTip2.py @@ -137,16 +137,18 @@ class ChartView(QChartView): self.lineItem = QGraphicsLineItem(self._chart) self.lineItem.setZValue(998) self.lineItem.hide() - + # 一些固定计算,减少mouseMoveEvent中的计算量 # 获取x和y轴的最小最大值 axisX, axisY = self._chart.axisX(), self._chart.axisY() self.min_x, self.max_x = axisX.min(), axisX.max() self.min_y, self.max_y = axisY.min(), axisY.max() # 坐标系中左上角顶点 - self.point_top = self._chart.mapToPosition(QPointF(self.min_x, self.max_y)) + self.point_top = self._chart.mapToPosition( + QPointF(self.min_x, self.max_y)) # 坐标原点坐标 - self.point_bottom = self._chart.mapToPosition(QPointF(self.min_x, self.min_y)) + self.point_bottom = self._chart.mapToPosition( + QPointF(self.min_x, self.min_y)) self.step_x = (self.max_x - self.min_x) / (axisX.tickCount() - 1) # self.step_y = (self.max_y - self.min_y) / (axisY.tickCount() - 1) @@ -176,7 +178,7 @@ class ChartView(QChartView): name = self.sender().name() except: name = "" - QToolTip.showText(QCursor.pos(), "%s\nx: %s\ny: %s" % + QToolTip.showText(QCursor.pos(), "%s\nx: %s\ny: %s" % (name, point.x(), point.y())) def initChart(self):