qgraphicstextitem over QChartview
-
Hello, I'm trying to add some labels to a qchart to go along with the qscatterseries in order to add labels to the points. I set the labels position in "label.setPos(g[pos], s[pos])" and then try to get the scene from qchartsview and add the label. for some reason all the labels end up at the top left corner. I've done a bit of googling and can't get it to work. Thanks in advance for any help!
import sys from PySide2.QtUiTools import QUiLoader from PySide2.QtWidgets import QApplication, QAction, QFileDialog, QLabel, QLineEdit, \ QMainWindow, QVBoxLayout, QWidget, QHBoxLayout, QInputDialog, QGraphicsTextItem from PySide2.QtCore import QFile, QObject from PySide2.QtCharts import QtCharts from PySide2.QtGui import QPixmap, QImage, QIntValidator, QDoubleValidator, QPainter import numpy as np class Chart(QMainWindow): def __init__(self): super().__init__() # chart creation hierarchy: # chartview-->charts-->series-->set(or points) # create chart widget self.chart = QtCharts.QChart() self.chart.legend().setVisible(False) self.chart.setTitle("Phasor Plot") self.setGeometry(0,0,800,500) # create chartview self.chartView = QtCharts.QChartView(self.chart) self.chartView.setRenderHint(QPainter.Antialiasing) g = [0.94058736, 0.79830002, 0.49735222, 0.3054408, 0.19831079, 0.1366765, 0.09905082, 0.074736, 0.0582399, 0.04658614, 0.03807176] s = [0.23639539, 0.40126936, 0.49999299, 0.46059387, 0.3987275, 0.34350551, 0.29873024, 0.26296489, 0.23419652, 0.21075073, 0.19136954] lifetime_labels = ['0.5ns', '1ns', '2ns', '3ns', '4ns', '5ns', '6ns', '7ns', '8ns', '9ns', '10ns'] # series - lifetime labels series_lifetime_markers = QtCharts.QScatterSeries() for pos in np.arange(len(lifetime_labels)): # add label to scene label = QGraphicsTextItem(lifetime_labels[pos]) label.setPos(g[pos], s[pos]) self.chart.scene().addItem(label) # add point to chart series_lifetime_markers.append(g[pos], s[pos]) print(f"scene pos {label.scenePos()}") print(f"{lifetime_labels[pos]}: {g[pos], s[pos]}") ''' chart - add series''' self.chart.addSeries(series_lifetime_markers) # self.chart.createDefaultAxes() # x_axis self.axis_x = QtCharts.QValueAxis() self.axis_x.setRange(0, 1) self.axis_x.setTickCount(15) self.axis_x.setLabelFormat("%.2f") self.axis_x.setTitleText("g") self.chart.setAxisX(self.axis_x, series_lifetime_markers) # y_axis self.axis_y = QtCharts.QValueAxis() self.axis_y.setRange(0, 0.7) self.axis_y.setTickCount(15) self.axis_y.setLabelFormat("%.2f") self.axis_y.setTitleText("s") self.chart.setAxisY(self.axis_y, series_lifetime_markers) ''' LAYOUTS ''' layout = QVBoxLayout() layout.addWidget(self.chartView) self.setCentralWidget(QWidget(self)) self.centralWidget().setLayout(layout) if __name__ == "__main__": app = QApplication(sys.argv) window = Chart() window.show() sys.exit(app.exec_())
-
I think you are setting the labels x and y coordinates too small, g[pos],s[pos] are very small values thats why they all seem to be concentrated near the origin. try to scale your values by setting
label.setPos(g[pos]*500, s[pos]*500)
Also try editing this to see default labels:
''' chart - add series''' series_lifetime_markers.setPointLabelsVisible(True) self.chart.addSeries(series_lifetime_markers)
then you will get what I mean.
-
I think you are setting the labels x and y coordinates too small, g[pos],s[pos] are very small values thats why they all seem to be concentrated near the origin. try to scale your values by setting
label.setPos(g[pos]*500, s[pos]*500)
Also try editing this to see default labels:
''' chart - add series''' series_lifetime_markers.setPointLabelsVisible(True) self.chart.addSeries(series_lifetime_markers)
then you will get what I mean.
@erudite-monkey thanks for taking a look at this. I did come across that post while trying to find an answer. If nothing else works then i'll subclass qchartview and try reimplementing the drawSeriesPointLabels function, but it seems like one of the "mapTo" functions should take care of it, I just can't figure out which one. It looks like the qgraphicstextitem and the qchart are on separate coordinate systems.I did multiply by 500 the g and s values and I can see that it does stretch the values but changing window size resizes the qchart but not the labels, and unfortunately I can't seem to find a way to map label to the qchart coordinates. If using the same coordinate system, the labels should fall right on top of the blue circles.
-
After a couple weeks of trying to figure this out on and off I finally got something working, I'm sure others will benefit from it
import sys from PySide2.QtUiTools import QUiLoader from PySide2.QtWidgets import QApplication, QAction, QFileDialog, QLabel, QLineEdit, \ QMainWindow, QVBoxLayout, QWidget, QHBoxLayout, QInputDialog, QGraphicsTextItem from PySide2.QtCore import QFile, QObject, QPointF from PySide2.QtCharts import QtCharts from PySide2.QtGui import QPixmap, QImage, QIntValidator, QDoubleValidator, QPainter import numpy as np class Chart(QMainWindow): def __init__(self): super().__init__() # chart creation hierarchy: # chartview-->charts-->series-->set(or points) # create chart widget self.chart = QtCharts.QChart() self.chart.legend().setVisible(False) self.chart.setTitle("Phasor Plot") self.setGeometry(0, 0, 800, 500) self.list_label_graphics_text_item = [] # create chartview self.chartView = QtCharts.QChartView(self.chart) self.chartView.setRenderHint(QPainter.Antialiasing) self.chart.scene().changed.connect(self.update_label_position) self.g = [0.94058736, 0.79830002, 0.49735222, 0.3054408, 0.19831079, 0.1366765, 0.09905082, 0.074736, 0.0582399, 0.04658614, 0.03807176] self.s = [0.23639539, 0.40126936, 0.49999299, 0.46059387, 0.3987275, 0.34350551, 0.29873024, 0.26296489, 0.23419652, 0.21075073, 0.19136954] self.lifetime_labels = ['0.5ns', '1ns', '2ns', '3ns', '4ns', '5ns', '6ns', '7ns', '8ns', '9ns', '10ns'] # series - lifetime labels series_lifetime_markers = QtCharts.QScatterSeries() for pos in np.arange(len(self.lifetime_labels)): series_lifetime_markers.append(self.g[pos], self.s[pos]) ''' chart - add series''' self.chart.addSeries(series_lifetime_markers) # x_axis self.axis_x = QtCharts.QValueAxis() self.axis_x.setRange(0, 1) self.axis_x.setTickCount(15) self.axis_x.setLabelFormat("%.2f") self.axis_x.setTitleText("g") self.chart.setAxisX(self.axis_x, series_lifetime_markers) # y_axis self.axis_y = QtCharts.QValueAxis() self.axis_y.setRange(0, 0.7) self.axis_y.setTickCount(15) self.axis_y.setLabelFormat("%.2f") self.axis_y.setTitleText("s") self.chart.setAxisY(self.axis_y, series_lifetime_markers) ''' LAYOUTS ''' layout = QVBoxLayout() layout.addWidget(self.chartView) self.setCentralWidget(QWidget(self)) self.centralWidget().setLayout(layout) def update_label_position(self): ''' position labels over chart ''' # https://www.qtcentre.org/threads/68981-QChart-QDateTiemAxis-mapTo-and-mapFrom # https://stackoverflow.com/questions/44067831/get-mouse-coordinates-in-qchartviews-axis-system # populate list of labels graphicsTextItems if len(self.list_label_graphics_text_item) == 0: for pos in np.arange(len(self.g)): # iterate through g coordinates label = QGraphicsTextItem(self.lifetime_labels[pos]) self.list_label_graphics_text_item.append(label) self.chart.scene().addItem(label) # position the labels for pos, label in enumerate(self.list_label_graphics_text_item): point_in_series = QPointF(self.g[pos], self.s[pos]) # position in series point_series_to_chart = self.chart.mapToPosition(point_in_series, self.chart.series()[0]) point_chart_to_scene = self.chart.mapToScene(point_series_to_chart) label.setPos(point_chart_to_scene) print(f'{self.lifetime_labels[pos]}: pos in series {point_in_series}\n' f'pos in chart: {point_series_to_chart}\n' f'pos in scene: {point_chart_to_scene}\n') if __name__ == "__main__": app = QApplication(sys.argv) window = Chart() window.show() sys.exit(app.exec_())