Pyside6。 qtextblock.qtextlayout.setformats

发布于 2025-02-12 10:20:05 字数 2250 浏览 1 评论 0原文

如何使用setFormats

程序显示qtextedit in qmainwindow
任务是找到“导入”一词,并在红色中使用block.lob.setformats 我不希望撤消redo历史记录到包括外观变化,我不想使用QSyntaxHighlighter )。

我不明白为什么在找到“导入”一词然后setFormats时,相应的块变得不可见。

from PySide6 import QtWidgets, QtCore, QtGui


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.central_widget = QtWidgets.QWidget(self)
        self.central_widget.setLayout(QtWidgets.QVBoxLayout(self.central_widget))
        self.text_editor = QtWidgets.QTextEdit(self.central_widget)
        self.central_widget.layout().addWidget(self.text_editor)
        self.setCentralWidget(self.central_widget)
        self.text_editor.setFont(QtGui.QFont('Arial', 14))
        self.text_editor.textChanged.connect(self.text_changed)

    @QtCore.Slot()
    def text_changed(self):
        word = 'import'
        text_cursor_before_find_op = self.text_editor.textCursor()

        self.text_editor.moveCursor(QtGui.QTextCursor.MoveOperation.Start)
        found = self.text_editor.find(word)
        if found:
            text_cursor = self.text_editor.textCursor()
            text_cursor.setPosition(text_cursor.position())
            block = text_cursor.block()
            position_in_block = text_cursor.positionInBlock() - len(word)
            format_range = QtGui.QTextLayout.FormatRange()
            format_range.start = position_in_block
            format_range.length = len(word)
            format_range.format = self.text_editor.currentCharFormat()
            format_range.format.setForeground(QtGui.QColor('#FF0000'))
            formats = [format_range]
            block.layout().setFormats(formats)
            print(position_in_block,
                  repr(block.text()),
                  (format_range.start, format_range.length, format_range.format),
                  block.isValid(), block.isVisible(),
                  sep='\n', end='\n\n')

        self.text_editor.setTextCursor(text_cursor_before_find_op)


app = QtWidgets.QApplication()
window = MainWindow()
window.show()
app.exec()

How to work with setFormats?

The program displays QTextEdit in QMainWindow.
The task is to find the word "import" and highlight it in red using block.layout.setFormats (I don't want the undo-redo history to include the appearance change, and I don't want to use QSyntaxHighlighter).

I don't understand why when finding the word "import" and then setFormats, the corresponding block becomes invisible.

from PySide6 import QtWidgets, QtCore, QtGui


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.central_widget = QtWidgets.QWidget(self)
        self.central_widget.setLayout(QtWidgets.QVBoxLayout(self.central_widget))
        self.text_editor = QtWidgets.QTextEdit(self.central_widget)
        self.central_widget.layout().addWidget(self.text_editor)
        self.setCentralWidget(self.central_widget)
        self.text_editor.setFont(QtGui.QFont('Arial', 14))
        self.text_editor.textChanged.connect(self.text_changed)

    @QtCore.Slot()
    def text_changed(self):
        word = 'import'
        text_cursor_before_find_op = self.text_editor.textCursor()

        self.text_editor.moveCursor(QtGui.QTextCursor.MoveOperation.Start)
        found = self.text_editor.find(word)
        if found:
            text_cursor = self.text_editor.textCursor()
            text_cursor.setPosition(text_cursor.position())
            block = text_cursor.block()
            position_in_block = text_cursor.positionInBlock() - len(word)
            format_range = QtGui.QTextLayout.FormatRange()
            format_range.start = position_in_block
            format_range.length = len(word)
            format_range.format = self.text_editor.currentCharFormat()
            format_range.format.setForeground(QtGui.QColor('#FF0000'))
            formats = [format_range]
            block.layout().setFormats(formats)
            print(position_in_block,
                  repr(block.text()),
                  (format_range.start, format_range.length, format_range.format),
                  block.isValid(), block.isVisible(),
                  sep='\n', end='\n\n')

        self.text_editor.setTextCursor(text_cursor_before_find_op)


app = QtWidgets.QApplication()
window = MainWindow()
window.show()
app.exec()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不必你懂 2025-02-19 10:20:05

我不知道为什么block.layout.setformats()不起作用。

但是,如果您的目的是突出显示“导入”一词,那么您可能需要使用类似的东西。

from PySide6 import QtWidgets, QtCore, QtGui


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.central_widget = QtWidgets.QWidget(self)
        self.central_widget.setLayout(QtWidgets.QVBoxLayout(self.central_widget))
        self.text_editor = QtWidgets.QTextEdit(self.central_widget)
        self.central_widget.layout().addWidget(self.text_editor)
        self.setCentralWidget(self.central_widget)
        self.text_editor.setFont(QtGui.QFont('Arial', 14))
        self.text_editor.textChanged.connect(self.text_changed)

    @QtCore.Slot()
    def text_changed(self):
        word = 'import'
        text_cursor = self.text_editor.document().find(word)
        if text_cursor:
            extraSelection = QtWidgets.QTextEdit.ExtraSelection()
            extraSelection.cursor = text_cursor
            extraSelection.format = self.text_editor.currentCharFormat()
            extraSelection.format.setForeground(QtGui.QColor('#FF0000'))
            self.text_editor.setExtraSelections([extraSelection])  
        else:     
            self.text_editor.setExtraSelections([])  


app = QtWidgets.QApplication()
window = MainWindow()
window.show()
app.exec()

当然,这有一些局限性,例如,仅查找整个文档中的第一次出现,而不是检查单词是否由Whitespace界定,在将单词更改为其他内容等之后保持格式。但是您需要自己解决这些问题。您的原始Coude将具有相同的限制。

I have no idea why block.layout.setFormats() does not work.

But if your intention is to highlight the word "import", then you might want to use something like this.

from PySide6 import QtWidgets, QtCore, QtGui


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.central_widget = QtWidgets.QWidget(self)
        self.central_widget.setLayout(QtWidgets.QVBoxLayout(self.central_widget))
        self.text_editor = QtWidgets.QTextEdit(self.central_widget)
        self.central_widget.layout().addWidget(self.text_editor)
        self.setCentralWidget(self.central_widget)
        self.text_editor.setFont(QtGui.QFont('Arial', 14))
        self.text_editor.textChanged.connect(self.text_changed)

    @QtCore.Slot()
    def text_changed(self):
        word = 'import'
        text_cursor = self.text_editor.document().find(word)
        if text_cursor:
            extraSelection = QtWidgets.QTextEdit.ExtraSelection()
            extraSelection.cursor = text_cursor
            extraSelection.format = self.text_editor.currentCharFormat()
            extraSelection.format.setForeground(QtGui.QColor('#FF0000'))
            self.text_editor.setExtraSelections([extraSelection])  
        else:     
            self.text_editor.setExtraSelections([])  


app = QtWidgets.QApplication()
window = MainWindow()
window.show()
app.exec()

Of course this has some limitations, e.g. finding only the first occurrence in the whole document, not checking if the word is delimited by whitespace, keeping format after changing the word to something else etc. But you will need to resolve these yourself. Your original coude would have the same limitations.

束缚m 2025-02-19 10:20:05

我认为这是一种错误。

在其他版本中,在Setadditionalformats的时代,我本可以毫无问题地为文本着色。

我执行了您的代码,并输入了“导入”。似乎没有调用块上的绘制函数(qtextlayout.draw函数),因为光标来停止闪烁。

qtextlayout.formatrange通常用于qabstractTextDocumentLayout的绘制函数。和光标(qtextlayout.drawcursor函数)在同一函数中绘制。

qtextlayout具有绘制功能,并且在该功能中也使用了功能。

class TextDocumentLayout(...


   def draw(self, ...):
       
       layout.draw(..., , formatRanges)
       layout.drawCursor(...)

This drawing seems that it doesn't work well by some reasons.
(I assume that setFormats is related to something flags).

无论如何,我发现我们可以通过通过鼠标手柄水平扩展文本deDEDIT的大小来避免此错误。

但这不是很好,我们使用鼠标句柄一一使用,我使用qtextedit的resizeevent。如果我们垂直扩大尺寸,这效果不佳。我不知道为什么...

resizeevent具有调用重新粉刷的副作用。但是,如果我直接使用RepAlt()函数,则不会发生重新粉刷...我不知道为什么...无论如何,我认为这个问题是一种QT错误。

from PySide6 import QtWidgets, QtCore, QtGui


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.central_widget = QtWidgets.QWidget(self)
        self.central_widget.setLayout(QtWidgets.QVBoxLayout(self.central_widget))
        self.text_editor = QtWidgets.QTextEdit(self.central_widget)
        self.central_widget.layout().addWidget(self.text_editor)
        self.setCentralWidget(self.central_widget)
        self.text_editor.setFont(QtGui.QFont('Arial', 14))
        self.text_editor.document().contentsChanged.connect(self.text_changed)

 

    @QtCore.Slot()
    def text_changed(self):
        word = 'import'
        text_cursor_before_find_op = self.text_editor.textCursor()

        self.text_editor.moveCursor(QtGui.QTextCursor.MoveOperation.Start)
        found = self.text_editor.find(word)
        if found:
            text_cursor = self.text_editor.textCursor()
            text_cursor.setPosition(text_cursor.position())
            block = text_cursor.block()
            position_in_block = text_cursor.positionInBlock() - len(word)
            format_range = QtGui.QTextLayout.FormatRange()
            format_range.start = position_in_block
            format_range.length = len(word)
            format_range.format = self.text_editor.currentCharFormat()
            format_range.format.setForeground(QtGui.QColor('#FF0000'))
            
            formats = [format_range]
            block.layout().setFormats(formats)
            
            print(position_in_block,
                  repr(block.text()),
                  (format_range.start, format_range.length, format_range.format),
                  block.isValid(), block.isVisible(),
                  sep='\n', end='\n\n')
            // expand to the right 1 px.
            resizeEvent = QtGui.QResizeEvent(self.text_editor.size(), self.text_editor.size() + QtCore.QSize(1, 0))
            self.text_editor.resizeEvent( resizeEvent )
            // shrink to the left 1 px.
            resizeEvent = QtGui.QResizeEvent(self.text_editor.size(), self.text_editor.size() + QtCore.QSize(-1, 0))
            self.text_editor.resizeEvent( resizeEvent )
        self.text_editor.setTextCursor(text_cursor_before_find_op)

        
        


app = QtWidgets.QApplication()
window = MainWindow()
window.show()
app.exec()

I think this is a kind of bug.

In other version, in the era of setAdditionalFormats, I could have colorized the text without problem.

I executed your code, and typed "import". It seemed that the draw function on the block(QTextLayout.draw function) isn't be called, since the cursor came to stop blinking.

QTextLayout.FormatRange is usually used in a draw function of QAbstractTextDocumentLayout. And cursor(QTextLayout.drawCursor function) is drawn in the same function.

QTextLayout has draw function and this is also used in that function.

class TextDocumentLayout(...


   def draw(self, ...):
       
       layout.draw(..., , formatRanges)
       layout.drawCursor(...)

This drawing seems that it doesn't work well by some reasons.
(I assume that setFormats is related to something flags).

At any rate, I found out that we can avoid this bug by expanding the size of textedit horizontally by mouse handle.

But it is not good we use mouse handle one by one, I use resizeEvent of QTextEdit. this doesn't work well if we expand the size vertically. I don't know why...

resizeEvent have a side effect of invoking repainting. But if I use repaint() function directly, repaint is not happend... I don't know why... Anyway, I think this problem is a kind of Qt bug.

from PySide6 import QtWidgets, QtCore, QtGui


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.central_widget = QtWidgets.QWidget(self)
        self.central_widget.setLayout(QtWidgets.QVBoxLayout(self.central_widget))
        self.text_editor = QtWidgets.QTextEdit(self.central_widget)
        self.central_widget.layout().addWidget(self.text_editor)
        self.setCentralWidget(self.central_widget)
        self.text_editor.setFont(QtGui.QFont('Arial', 14))
        self.text_editor.document().contentsChanged.connect(self.text_changed)

 

    @QtCore.Slot()
    def text_changed(self):
        word = 'import'
        text_cursor_before_find_op = self.text_editor.textCursor()

        self.text_editor.moveCursor(QtGui.QTextCursor.MoveOperation.Start)
        found = self.text_editor.find(word)
        if found:
            text_cursor = self.text_editor.textCursor()
            text_cursor.setPosition(text_cursor.position())
            block = text_cursor.block()
            position_in_block = text_cursor.positionInBlock() - len(word)
            format_range = QtGui.QTextLayout.FormatRange()
            format_range.start = position_in_block
            format_range.length = len(word)
            format_range.format = self.text_editor.currentCharFormat()
            format_range.format.setForeground(QtGui.QColor('#FF0000'))
            
            formats = [format_range]
            block.layout().setFormats(formats)
            
            print(position_in_block,
                  repr(block.text()),
                  (format_range.start, format_range.length, format_range.format),
                  block.isValid(), block.isVisible(),
                  sep='\n', end='\n\n')
            // expand to the right 1 px.
            resizeEvent = QtGui.QResizeEvent(self.text_editor.size(), self.text_editor.size() + QtCore.QSize(1, 0))
            self.text_editor.resizeEvent( resizeEvent )
            // shrink to the left 1 px.
            resizeEvent = QtGui.QResizeEvent(self.text_editor.size(), self.text_editor.size() + QtCore.QSize(-1, 0))
            self.text_editor.resizeEvent( resizeEvent )
        self.text_editor.setTextCursor(text_cursor_before_find_op)

        
        


app = QtWidgets.QApplication()
window = MainWindow()
window.show()
app.exec()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文