3

I have a list in QPlainTextEdit and want to highlight a specific line, line number 5 say.

I looked at various tutorials and examples, but the documentation of PyQt5 seems rather sparse.

Workable code, I would like to highlight lines. For a suggestion of another widget I am also grateful. I don't want to edit this list, just show it and highlight lines.

import sys
from PyQt5.QtWidgets import *

app = QApplication(sys.argv)
main = QWidget()
main.resize(250, 150)
main.size
tbox = QPlainTextEdit(main)
for nr in range(1,5):
    tbox.appendPlainText('%d'%nr)

## highlight line 2
## wait a while
## unhighlight line 2
## highlight line 4
main.show()
sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
monos
  • 75
  • 1
  • 6

2 Answers2

3

If the highlighting depends on the text then the solution of @oetzi is the one indicated because although you delete lines the same text will remain highlighted, if instead the highlighting only depends on the position of the line then a possible solution is to use QSyntaxHighlighter.

In the following example you can enter whole numbers separated from spaces that indicate the position of the lines that will be highlighted (the position starts from 0):

import sys
from PyQt5.QtCore import pyqtSlot, QRegExp
from PyQt5.QtGui import QColor, QRegExpValidator, QSyntaxHighlighter, QTextCharFormat
from PyQt5.QtWidgets import (
    QApplication,
    QLineEdit,
    QPlainTextEdit,
    QVBoxLayout,
    QWidget,
)


class SyntaxHighlighter(QSyntaxHighlighter):
    def __init__(self, parent):
        super(SyntaxHighlighter, self).__init__(parent)
        self._highlight_lines = dict()

    def highlight_line(self, line, fmt):
        if isinstance(line, int) and line >= 0 and isinstance(fmt, QTextCharFormat):
            self._highlight_lines[line] = fmt
            tb = self.document().findBlockByLineNumber(line)
            self.rehighlightBlock(tb)

    def clear_highlight(self):
        self._highlight_lines = dict()
        self.rehighlight()

    def highlightBlock(self, text):
        line = self.currentBlock().blockNumber()
        fmt = self._highlight_lines.get(line)
        if fmt is not None:
            self.setFormat(0, len(text), fmt)


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

        self._lineedit = QLineEdit(textChanged=self.onTextChanged)
        regex_validator = QRegExpValidator(QRegExp(r"[0-9 ]+"))
        self._lineedit.setValidator(regex_validator)

        self._plaintextedit = QPlainTextEdit()

        self._highlighter = SyntaxHighlighter(self._plaintextedit.document())

        lay = QVBoxLayout(self)
        lay.addWidget(self._lineedit)
        lay.addWidget(self._plaintextedit)

        for i in range(10):
            self._plaintextedit.appendPlainText("line %d" % i)

        self.resize(320, 240)

    @pyqtSlot(str)
    def onTextChanged(self, text):
        fmt = QTextCharFormat()
        fmt.setBackground(QColor("yellow"))
        self._highlighter.clear_highlight()
        for e in text.split():
            line = int(e)
            self._highlighter.highlight_line(line, fmt)


if __name__ == "__main__":

    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

enter image description here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
1
import sys
from PyQt5.QtWidgets import (QPlainTextEdit, QApplication, QWidget)

app = QApplication(sys.argv)
main = QWidget()
main.resize(250, 150)
main.size
tbox = QPlainTextEdit(main)
condition = 0
for nr in range(1, 5):
    if condition % 2 == 0:
        tbox.appendHtml(f"<span style='background-color: yellow;'>{nr}</p>")
    else:
        tbox.appendHtml(f"<span style='background-color: white;'>{nr}</p>")
    # tbox.appendPlainText('%d' % nr)
    condition = condition + 1
main.show()
sys.exit(app.exec_())

screenshot

oetzi
  • 1,002
  • 10
  • 21