プログラムを中心とした個人的なメモ用のブログです。 タイトルは迷走中。
内容の保証はできませんのであしからずご了承ください。

2022/01/28

[PySide] QChart のグラフに Tooltip を追加する

event_note2022/01/28 8:21

グラフにマウスオーバーしたときにツールチップを表示するサンプルです。

とりあえず QToolTip を使って簡単に実装してみました。

他には以下のサンプルとかも見つかりましたが、ちょっと複雑なので・・・。

環境

  • PySide 6.2.2.1

サンプル

以前の記事をベースに作成してみました。

QBarSeriesQBarSet のどちらのマウスオーバーでツールチップを表示するかはお好みで。

import sys
from PySide6.QtWidgets import *
from PySide6.QtCore import Qt
from PySide6.QtCharts import *
from PySide6.QtGui import QPainter, QCursor

class BarChartSample(QChartView):
    __categories = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
    __samples = {
        'Hoge': [9, 7, 5, 3, 1, 2],
        'Piyo': [3, 5, 8, 13, 8, 5],
        'Fuga': [5, 0, 0, 4, 0, 7],
        'Foo': [1, 2, 3, 4, 5, 6],
        'Bar': [5, 6, 7, 3, 4, 5],
    }

    def __init__(self, parent = None):
        super().__init__(parent)

        series = QBarSeries()
        #series = QStackedBarSeries()
        for key, values in self.__samples.items():
            barset = QBarSet(key)
            #barset.hovered.connect(lambda state,index, x=key: self.__barset_hovered(x, index, state)) # 即時評価するため key を x に代入
            for value in values:
                barset.append(value)
            series.append(barset)
        series.hovered.connect(lambda state, index: self.__barseries_hovered(state, index))

        chart = QChart()
        chart.addSeries(series)
        chart.setTitle('Barchart example')
        chart.setAnimationOptions(QChart.SeriesAnimations)

        axis_x = QBarCategoryAxis()
        axis_x.append(self.__categories)
        chart.addAxis(axis_x, Qt.AlignBottom)
        series.attachAxis(axis_x)

        axis_y = QValueAxis()
        chart.addAxis(axis_y, Qt.AlignLeft)
        series.attachAxis(axis_y)

        chart.legend().setVisible(True)
        chart.legend().setAlignment(Qt.AlignBottom)

        self.setRenderHint(QPainter.Antialiasing)
        self.setChart(chart)

        self.__tooltip = QToolTip()
    
    def __barseries_hovered(self, state, index):
        print(f'barsetseries hovered, state={state}, index={index}')
        if state:
            texts = []
            for key, values in self.__samples.items():
                if values[index] > 0:
                    texts.append( f'{key}: {values[index]}')
            self.__tooltip.showText(QCursor().pos(), '\n'.join(texts))
        else:
            self.__tooltip.hideText()

    def __barset_hovered(self, key, index, state):
        print(f'{key} hovered index={index}, category={self.__categories[index]}, state={state}')
        if state:
            self.__tooltip.showText(QCursor().pos(), f'{key}: {self.__samples[key][index]}')
        else:
            self.__tooltip.hideText()

class MainWindows(QMainWindow):
    def __init__(self):
        super().__init__()

        barchart = BarChartSample(self)
        self.setCentralWidget(barchart)

if __name__ == "__main__":
    app = QApplication(sys.argv)

    window = MainWindows()
    window.show()
    window.resize(720, 480)
    sys.exit(app.exec())