pythonpyside2qtextdocument

Hover effect for QTextDocument


I wanted to have some hover effect over p tag inside QTextDocument.

I have tried to set QSS for QTextDocument using QTextDocument().setDefaultStyleSheet(). Here's what the result I have obtained;

output

Script;

from PySide2 import QtWidgets


class Test(QtWidgets.QTextBrowser):
    def __init__(self):
        super().__init__()

        self.document().setDefaultStyleSheet(
            """
p.out{
    background-color: "orange";
    color: "black";
}

p.out:hover{
    background-color: "yellow";
}
"""
        )

        self.setStyleSheet(
            """
QTextBrowser{
    background-color: "black";
    color: "white";
}
""")

        self.setHtml(
            """
<p class='out'> Checking this </p>
"""
        )


test = QtWidgets.QApplication([])

sample = Test()
sample.show()

test.exec_()

Color attribute inside qss worked but the hover doesn't work.

Is there any way of achieving hover effect over fragments of text inside document?


Solution

  • After Understanding, QTextDocument's structure and Syntax Highlighter. We can modify QTextBlock's Format whenever we want. I tried to change it's format using enterEvent, and restore format in leaveEvent.

    we can modify box model using QTextFrame using QTextFrameFormat.

    from PySide2 import QtWidgets, QtGui
    
    
    class High(QtGui.QSyntaxHighlighter):
        def __init__(self, doc):
            super().__init__(doc)
    
            self._formats = tuple(
                QtGui.QTextCharFormat() for _ in range(2)
            )
    
            self._formats[1].setForeground(
                QtGui.QBrush(QtGui.QColor("orange"))
            )
    
            self._formats[1].setFontWeight(3)
            self._formats[1].setFontUnderline(True)
            self._formats[1].setFontPointSize(12)
    
        def highlightBlock(self, text: str):
            self.setFormat(
                0, len(text), self._formats[self.currentBlockState() if self.currentBlockState() > -1 else 0]
            )
    
    
    class Sample(QtWidgets.QTextBrowser):
        def __init__(self):
            super().__init__()
            self.lighter = High(self.document())
            self._prev = None
    
            self.insertBlock("This is a sample line\n")
            self.insertBlock("Can also be a\nparagraph thing\n")
            self.insertBlock("it's a block, Bye!")
    
        def insertBlock(self, text):
            cur = self.textCursor()
            cur.block().setUserState(0)  # default: -1
    
            cur.insertText(text)
    
        def mouseMoveEvent(self, eve):
            super().mouseMoveEvent(eve)
    
            cur = self.cursorForPosition(eve.pos())
    
            if cur.block() == self._prev:
                return
    
            self.restore()
            cur.block().setUserState(1)
            self.lighter.rehighlightBlock(cur.block())
    
            self._prev = cur.block()
    
        def restore(self):
            if not self._prev:
                return
    
            self._prev.setUserState(0)
            self.lighter.rehighlightBlock(self._prev)
            self._prev = None
    
        def leaveEvent(self, eve):
            self.restore()
            super().leaveEvent(eve)
    
    
    testing = QtWidgets.QApplication([])
    sample = Sample()
    sample.show()
    testing.exec_()