Search code examples
pyqttooltipqtreeview

PyQt ToolTip for QTreeView


Please axplain how to enable and show a tooltip for each item in QTreeView. I found a sample of code class TreeModel(QAbstractItemModel) but due to my beginner's level I can't understand how to apply it to my needs.

Data for tooltip should be taken from value of key "note" in dictionary data_for_tree.

#!/usr/bin/env python -tt
# -*- coding: utf-8 -*-

from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

import sys
reload(sys)
sys.setdefaultencoding('utf8')

data_for_tree = {"tomato":{"color":"red","ammount":"10", "note":"a note for tomato"},"banana":{"color":"yellow","ammount":"1", "note":"b note for banana"}, "some fruit":{"color":"unknown","ammount":"100", "note":"some text"}}

class TreeModel(QAbstractItemModel):

    def data(self, index, role=Qt.DisplayRole):
        #...
        if role == Qt.ToolTipRole:
            return 'ToolTip'

    def flags(self, index):
        if not index.isValid():
            return Qt.NoItemFlags # 0
        return Qt.ItemIsSelectable # or Qt.ItemIsEnabled            

class ProxyModel(QSortFilterProxyModel):

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

    def lessThan(self, left, right):
        leftData = self.sourceModel().data(left)
        rightData = self.sourceModel().data(right)
        try:
            return float(leftData) < float(rightData)
        except ValueError:
            return leftData < rightData

class MainFrame(QWidget):
    def __init__(self):
        QWidget.__init__(self)

        self.MyTreeView = QTreeView()
        self.MyTreeViewModel = QStandardItemModel()
        self.MyTreeView.setModel(self.MyTreeViewModel)
        self.most_used_cat_header = ['Name', "ammount", "color"]
        self.MyTreeViewModel.setHorizontalHeaderLabels(self.most_used_cat_header)
        self.MyTreeView.setSortingEnabled(True)
        self.MyTreeView_Fill()

        MainWindow = QHBoxLayout(self)    
        MainWindow.addWidget(self.MyTreeView)
        self.setLayout(MainWindow)

    def MyTreeView_Fill(self):
        for k in data_for_tree:
            name = QStandardItem(k)
            ammount = QStandardItem(data_for_tree[k]["ammount"])
            note = QStandardItem(data_for_tree[k]["color"])
            tooltip = data_for_tree[k]["note"]
            item = (name, ammount, note)
            self.MyTreeViewModel.appendRow(item)
        self.MyTreeView.sortByColumn(1, Qt.DescendingOrder)
        proxyModel = ProxyModel(self)
        proxyModel.setSourceModel(self.MyTreeViewModel)
        self.MyTreeView.setModel(proxyModel)

        c = 0
        while c < len(self.most_used_cat_header):
            self.MyTreeView.resizeColumnToContents(c)
            c=c+1

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = MainFrame()
    main.show()
    main.move(app.desktop().screen().rect().center() - main.rect().center())
sys.exit(app.exec_())

Solution

  • As you are using the QStandardItem and QStandardItemModel classes (which is what I would recommend!) you don't need to bother with the TreeModel class you have found. Creating your own model is rarely necessary, but for some reason tutorials often encourage you to do so. If you find something encouraging you to subclass QAbstractItemModel, I suggest you check on stack overflow first to see if there is a simpler way to do it! In this case, there is a very simple way to add your tooltips.

    If you look at the C++ documentation (which I often find more useful than the PyQt documentation for finding out what methods are available), you will see that QStandardItem has a method called setToolTip().

    So all you need to do is call this method on each of the items you add to the model. For example, inside the loop in the MyTreeView_Fill method:

    name = QStandardItem(k)
    ammount = QStandardItem(data_for_tree[k]["ammount"])
    note = QStandardItem(data_for_tree[k]["color"])
    tooltip = data_for_tree[k]["note"]
    name.setToolTip(tooltip)
    ammount.setToolTip(tooltip)
    note.setToolTip(tooltip)
    

    Here I've set the tooltip to be the same for every cell in the row (name, amount and note) but you could easily change this to have a different tooltip for one of the cells (hopefully it is obvious how to do that)