Search code examples
pythonpyqtpyqt5qtcharts

How to draw a vertical line at specified x value on QHorizontalBarSeries/QChart?


I've followed this example to create a horizontal bar chart. I'd like to draw a static vertical line at a specific value along the x-axis. I've tried adding a QLineSeries to the QChart, but nothing is showing up. I'm doing this in Python, but C++ works, too.


Solution

  • A possible solution is to override the drawForeground() method to paint the vertical line, to calculate the positions you must use the mapToPosition() method:

    import sys
    
    from PyQt5.QtCore import Qt, QPointF
    from PyQt5.QtGui import QColor, QPainter, QPen
    from PyQt5.QtWidgets import QApplication, QMainWindow
    from PyQt5.QtChart import (
        QBarCategoryAxis,
        QBarSet,
        QChart,
        QHorizontalBarSeries,
        QChartView,
        QValueAxis,
    )
    
    
    class ChartView(QChartView):
        _x = None
    
        @property
        def x(self):
            return self._x
    
        @x.setter
        def x(self, x):
            self._x = x
            self.update()
    
        def drawForeground(self, painter, rect):
            if self.x is None:
                return
            painter.save()
    
            pen = QPen(QColor("indigo"))
            pen.setWidth(3)
            painter.setPen(pen)
    
            p = self.chart().mapToPosition(QPointF(self.x, 0))
    
            r = self.chart().plotArea()
    
            p1 = QPointF(p.x(), r.top())
            p2 = QPointF(p.x(), r.bottom())
            painter.drawLine(p1, p2)
    
            painter.restore()
    
    
    def main():
        app = QApplication(sys.argv)
    
        set0 = QBarSet("Jane")
        set1 = QBarSet("John")
        set2 = QBarSet("Axel")
        set3 = QBarSet("Mary")
        set4 = QBarSet("Samantha")
    
        set0 << 1 << 2 << 3 << 4 << 5 << 6
        set1 << 5 << 0 << 0 << 4 << 0 << 7
        set2 << 3 << 5 << 8 << 13 << 8 << 5
        set3 << 5 << 6 << 7 << 3 << 4 << 5
        set4 << 9 << 7 << 5 << 3 << 1 << 2
    
        series = QHorizontalBarSeries()
        series.append(set0)
        series.append(set1)
        series.append(set2)
        series.append(set3)
        series.append(set4)
    
        chart = QChart()
        chart.addSeries(series)
        chart.setTitle("Simple horizontal barchart example")
        chart.setAnimationOptions(QChart.SeriesAnimations)
    
        categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
        axisY = QBarCategoryAxis()
        axisY.append(categories)
        chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        axisX = QValueAxis()
        chart.addAxis(axisX, Qt.AlignBottom)
        series.attachAxis(axisX)
        axisX.applyNiceNumbers()
    
        chart.legend().setVisible(True)
        chart.legend().setAlignment(Qt.AlignBottom)
    
        chartView = ChartView(chart)
        chartView.setRenderHint(QPainter.Antialiasing)
    
        chartView.x = 11.5
    
        window = QMainWindow()
        window.setCentralWidget(chartView)
        window.resize(420, 300)
        window.show()
    
        app.exec()
    
    
    if __name__ == "__main__":
        main()
    

    enter image description here