使用自定义格式,不要 select 在 qplaintextedit 中完成文本

use custom format and do not select complete text in qplaintextedit

我写了小程序,我想使用下划线格式而不是 QplainTextEditselected 文本

  1. 效果很好,当我点击鼠标左键时
  2. 但是当我使用 shift+左键单击时,qplaintextedit select 完整的文本和下划线格式消失了。
  3. 我试图只使用下划线格式而不是 select 文本。

Shift+左键单击的预期行为

#!/usr/bin/python3.6
from PySide2.QtCore import Qt, QEvent
from PySide2.QtWidgets import QApplication
from PySide2.QtGui import (QTextCharFormat, QIcon, QKeySequence,
                           QBrush, QColor, QTextDocument, QFont,
                           QTextCursor, QTextBlockFormat, QFontDatabase)
from PySide2.QtWidgets import (QPlainTextEdit, QSizePolicy, QApplication, QLabel, QGridLayout, QMessageBox, QToolBar, QTextEdit, QCheckBox, QAction,
                               QTableWidget, QTableWidgetItem, QHeaderView, QMenu,
                               QWidget)
from PySide2.QtCore import Qt, QSize, QRegExp, QFile, QTextStream, QRect
from PySide2.QtWidgets import (QMainWindow, QVBoxLayout,
                               QPlainTextEdit, QGridLayout, QGroupBox,
                               QListWidget, QHBoxLayout, QLabel, QLineEdit,
                               QMenuBar, QPushButton, QMessageBox, QDialog,
                               QTextEdit, QVBoxLayout, QWidget, QFormLayout,
                               QCheckBox, QDialogButtonBox,
                               QTableWidget, QTableWidgetItem, QHeaderView)
import sys


class Window(QMainWindow):
    def __init__(self, app):
        super().__init__()
        self.shift_left_click_cursor = []

    def create_widget(self):
        self.plain_textedit = QPlainTextEdit()
        self.plain_textedit.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.plain_textedit.setStyleSheet(
            """QPlainTextEdit {font-size: 14pt;
                               font-family: Courier;}""")
        self.plain_textedit.setMouseTracking(True)
        self.plain_textedit_format = self.plain_textedit.currentCharFormat()
        self.plain_textedit.setCursorWidth(5)
        self.plain_textedit.viewport().installEventFilter(self)
        main_layout = QVBoxLayout()
        main_layout.addWidget(self.plain_textedit)
        self.window = QWidget()
        self.window.setLayout(main_layout)
        self.setCentralWidget(self.window)

    def eventFilter(self, obj, event):
        if obj is self.plain_textedit.viewport() and event.type() == QEvent.MouseButtonPress:
            #Reseting format for single click when user use shift+click select data
            if event.button() == Qt.LeftButton:
                text_cursor = self.plain_textedit.cursorForPosition(event.pos())
                text_cursor.select(QTextCursor.LineUnderCursor)
                format = QTextCharFormat()
                format.setForeground(QBrush(QColor("blue")))
                format.setUnderlineStyle(QTextCharFormat.SingleUnderline)
                text_cursor.mergeCharFormat(format)
                modifiers = QApplication.keyboardModifiers()
                if modifiers == Qt.ShiftModifier:
                    self.shift_left_click_cursor.append(text_cursor)
                    self.change_summary_block_format()

    def change_summary_block_format(self):
        start_line = self.shift_left_click_cursor[0].blockNumber()
        end_line = self.shift_left_click_cursor[-1].blockNumber()
        index = 0
        plain_textcursor = self.plain_textedit.textCursor()
        plain_textcursor.select(QTextCursor.Document)
        plain_textcursor.setCharFormat(self.plain_textedit_format)
        plain_textcursor.clearSelection()

        for line in range(start_line, end_line + 1):
            text_data = self.plain_textedit.document().findBlockByLineNumber(line)
            print(text_data.text())
            text_cursor = QTextCursor(text_data)
            # self.plaintext_cursor_multiselection(text_data)
            print(text_data)



def main():
    app = QApplication([])
    window = Window(app)
    window.create_widget()
    window.show()
    app.exec_()


if __name__ == "__main__":
    sys.exit(main())

如果您将事件发送到 QPlainTextEdit,那么您可以获得所选内容的位置和锚点并将它们移动到覆盖整行。

class Window(QMainWindow):
    def __init__(self, app):
        super().__init__()
        self.shift_left_click_cursor = []

    def create_widget(self):
        self.plain_textedit = QPlainTextEdit()
        self.plain_textedit.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.plain_textedit.setStyleSheet(
            """QPlainTextEdit {font-size: 14pt;
                               font-family: Courier;}""")
        self.plain_textedit.setMouseTracking(True)
        self.plain_textedit_format = self.plain_textedit.currentCharFormat()
        self.plain_textedit.setCursorWidth(5)
        self.plain_textedit.viewport().installEventFilter(self)
        main_layout = QVBoxLayout()
        main_layout.addWidget(self.plain_textedit)
        self.window = QWidget()
        self.window.setLayout(main_layout)
        self.setCentralWidget(self.window)

    def eventFilter(self, obj, event):
        if obj is self.plain_textedit.viewport() and event.type() == QEvent.MouseButtonPress:
            #Reseting format for single click when user use shift+click select data
            
            if event.button() == Qt.LeftButton and event.modifiers() & Qt.ShiftModifier:
                self.plain_textedit.mousePressEvent(event)
                
                text_cursor = self.plain_textedit.textCursor()
                positions = (text_cursor.anchor(), text_cursor.position())
                text_cursor.setPosition(min(positions))            
                text_cursor.movePosition(QTextCursor.StartOfLine)
                text_cursor.setPosition(max(positions), QTextCursor.KeepAnchor)
                text_cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor)

                format = QTextCharFormat()
                format.setForeground(QBrush(QColor("blue")))
                format.setUnderlineStyle(QTextCharFormat.SingleUnderline)
                text_cursor.mergeCharFormat(format)
                
                text_cursor.clearSelection()
                text_cursor.setPosition(positions[1])
                self.plain_textedit.setTextCursor(text_cursor)
                return True
            
        return super().eventFilter(obj, event)

请注意,您可以改为子类化 QPlainTextEdit 并重新实现 mousePressEvent

class PlainTextEdit(QPlainTextEdit):

    def mousePressEvent(self, event):
        super().mousePressEvent(event)
        if event.button() == Qt.LeftButton and event.modifiers() & Qt.ShiftModifier:
            text_cursor = self.textCursor()
            positions = (text_cursor.anchor(), text_cursor.position())
            text_cursor.setPosition(min(positions))            
            text_cursor.movePosition(QTextCursor.StartOfLine)
            text_cursor.setPosition(max(positions), QTextCursor.KeepAnchor)
            text_cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor)

            format = QTextCharFormat()
            format.setForeground(QBrush(QColor("blue")))
            format.setUnderlineStyle(QTextCharFormat.SingleUnderline)
            text_cursor.mergeCharFormat(format)
            
            text_cursor.clearSelection()
            text_cursor.setPosition(positions[1])
            self.setTextCursor(text_cursor)