QPlainTextEdit多行纯文本编辑器

  • 描述
  • QPlainText和QTextEdit大致功能实现差不多,但针对纯文本处理进行了优化
  • 与QTextEdit相同
    • 适用于段落和字符
      • 段落是一个格式化的字符串,为了适应控件的宽度, 会自动换行
      • 默认情况下,在读取纯文本时,一个换行符表示一个段落。
      • 文档由零个或多个段落组成。段落由硬线断开分隔。
      • 段落中的每个字符都有自己的属性,例如字体和颜色。
    • 内容的编辑
      • 文本的选择由QTextCursor类处理,该类提供创建选择,检索文本内容或删除选择的功能
      • QPlainTextEdit包含一个QTextDocument对象,可以使用document()方法检索该对象
  • 与QTextEdit的差异
    • QPlainTextEdit是一个简略版本的类(使用QTextEdit和QTextDocument作为背后实现的技术支撑)
    • 它的性能优于QTextEdit, 主要是因为在文本文档中使用QPlainTextDocumentLayout简化文本布局
    • 纯文本文档布局不支持表格或嵌入框架,并使用逐行逐段滚动方法替换像素精确高度计算。
  • 继承自:QAbstractScrollArea
  • 功能作用
  • 创建
    QPlainTextEdit(parent: QWidget = None)          # 创建对象的同时设置父对象
    QPlainTextEdit(str, parent: QWidget = None)     # 创建对象的同时添加提示文本和设置父对象
    
  • 占位提示文本
    setPlaceholderText(str)                         # 设置占位提示文本
    placeholderText() -> str                        # 获取占位提示文本
    
  • 只读设置
    setReadOnly(bool)                               # 设置是否只读
    isReadOnly() -> bool                            # 判断是否只读
    
  • 格式设置
    currentCharFormat() -> QTextCharFormat          # 获取当前字符格式
    setCurrentCharFormat(QTextCharFormat)           # 设置当前字符格式
    mergeCurrentCharFormat(QTextCharFormat)         # 合并当前字符格式
    
    # 补充
    QTextCharFormat
        描述
            提供了一种字符格式信息
            文档中文本的字符格式指定文本的可视属性,以及有关其在超文本文档中的角色的信息
        设置字体格式
            setFont(QFont)                                  # 通过QFont对象统一设置字体格式
            font() -> QFont                                 # 获取字体格式的QFont对象
            setFontFamily(family_str)                       # 设置字体家族
            fontFamily() -> str                             # 获取字体家族
            setFontPointSize(float)                         # 设置字体大小
            fontPointSize() -> float                        # 获取字体大小
            setFontWeight(int)                              # 设置字体粗细
            fontWeight() -> int                             # 获取字体粗细
            setFontOverline(bool)                           # 设置字体上划线
            fontOverline() -> bool                          # 获取字体是否设置上划线
            setFontStrikeOut(bool)                          # 设置字体中划线(删除线)
            fontStrikeOut() -> bool                         # 获取字体是否设置中划线
            setFontUnderline(bool)                          # 获取字体下划线
            fontUnderline() -> bool                         # 获取字体是否设置下划线
        字体大小写
            setFontCapitalization(QFont.Capitalization)     # 设置字体大小写格式
            fontCapitalization() -> QFont.Capitalization    # 获取字体大小写格式
                # 参数:QFont.Capitalization
                        QFont.MixedCase                     # 正常的文本呈现
                        QFont.AllUppercase                  # 以全大写类型呈现的文本
                        QFont.AllLowercase                  # 以全小写类型呈现的文本
                        QFont.SmallCaps                     # 以小型大写字母呈现的文本
                        QFont.Capitalize                    # 单词的首字符为大写字符
        颜色
            setForeground(QColor(100, 200, 150))            # 通过QColor对象设置字体颜色
        超链接
            setAnchorHref("http://www.itlike.com")          # 设置超链接
            anchorHref() -> str                             # 获取超链接
    
  • 软换行模式
    setLineWrapMode(QPlainTextEdit.LineWrapMode)    # 设置软换行模式
    lineWrapMode() -> QPlainTextEdit.LineWrapMode   # 获取软换行模式
    
    # 补充
    QPlainTextEdit.LineWrapMode
         QPlainTextEdit.NoWrap                   # 没有软换行
         QPlainTextEdit.WidgetWidth              # 超出控件宽度进行自动换行
    
  • 覆盖模式
    • 只能是单个字符操作才可以覆盖,中文不能覆盖
    setOverwriteMode(bool)                          # 设置是否覆盖模式
    overwriteMode() -> bool                         # 获取是否覆盖模式
    
  • Tab控制
    setTabChangesFocus(bool)                        # 设置Tab键是否为切换焦点
    tabChangesFocus() -> bool                       # 获取Tab键是否为切换焦点
    
    setTabStopDistance(distance_float)              # 设置一个Tab键的宽度
    tabStopDistance() -> float                      # 获取一个Tab键的宽度
    
  • 文本操作
    setPlainText(text_str)                          # 设置普通文本内容
    insertPlainText(text_str)                       # 插入普通文本
    appendPlainText(text_str)                       # 追加普通文本
    appendHtml(html_str)                            # 追加HTML字符串
                                                    # 注意:有些标签不支持(表格、列表、图片、...)
    toPlainText()                                   # 获取文本内容,转换成纯文本
    
  • 文本块数操作
    • 限制当前文本编辑器中的文本块个数(其实就是限制文本段落个数)
    blockCount() -> int                             # 获取当前编辑器中文本块个数(段落数)
    maximumBlockCount() -> int                      # 获取当前编辑器最大文本块个数(段落数)
    setMaximumBlockCount(int)                       # 设置当前编辑器可以输入最大文本块个数(段落数)
    
    # 当编辑器不设置最大文本块个数时,获取到最大文本块数为0
    # 如果输入内容的段落超过最大段落数,则会自动删除最前面的段落
    
  • 常用编辑操作
    selectAll()                                     # 选中所有
    copy()                                          # 复制选中文本
    cut()                                           # 剪切选中文本
    paste()                                         # 粘贴文本
    canPaste() -> bool                              # 判定是否可以粘贴
    clear()                                         # 清空内容
    redo()                                          # 重做
    isUndoRedoEnabled() -> bool                     # 判定撤销重做是否可用
    setUndoRedoEnabled(bool)                        # 设置撤销重做是否可用
    undo()                                          # 撤销
    find(str, QTextDocument.FindFlags) -> bool      # 查找指定内容
        QTextDocument.FindBackward                  # 向后搜索而不是向前搜索。
        QTextDocument.FindCaseSensitively           # 区分大小写的查找操作。
        QTextDocument.FindWholeWords                # 使查找匹配仅完整的单词。
    zoomIn(int range = 1)                           # 设置放大缩小
                range > 0                           # 放大
                range < 0                           # 缩小
    zoomOut(int range = 1)                          # 已过期,效果和上面的方法相反
    
  • 滚动(定位光标行)
    centerCursor()                              # 光标所在行定位到编辑器中间位置
    ensureCursorVisible()                       # 光标所在行不在编辑范围时,将光标行定位到顶部/底部
    setCenterOnScroll(bool)                     # 传递True,表示, 控制光标(文本最后一行),显示时能够展示在中间位置
                                                # 注意:必须事先设置好,其实就是在后面添加一些空文本块
    centerOnScroll() -> bool                    # 获取是否设置最后一行光标能滚动到中间位置
    
  • 光标设置
    textCursor() -> QTextCursor                 # 获取文本光标对象
    cursorForPosition(QPoint) -> QTextCursor    # 获取指定位置的文本光标对象
    cursorWidth() -> int                        # 获取文本光标对象的宽度
    setCursorWidth(int)                         # 设置文本光标对象的宽度
    cursorRect() -> QRect                       # 获取文本光标对象的矩形
    cursorRect(QTextCursor)                     # 获取指定光标对象的矩形
    
    moveCursor(QTextCursor.MoveOperation,QTextCursor.MoveMode)     # 移动文本光标
        # 参数
        QTextCursor.MoveOperation
            QTextCursor.NoMove                      # 将光标保持在原位
            QTextCursor.Start                       # 移至文档的开头。
            QTextCursor.StartOfLine                 # 移动到当前行的开头。
            QTextCursor.StartOfBlock                # 移动到当前块的开头。
            QTextCursor.StartOfWord                 # 移动到当前单词的开头。
            QTextCursor.PreviousBlock               # 移动到上一个块的开头。
            QTextCursor.PreviousCharacter           # 移至上一个字符。
            QTextCursor.PreviousWord                # 移到上一个单词的开头。
            QTextCursor.Up                          # 向上移动一行。
            QTextCursor.Left                        # 向左移动一个字符。
            QTextCursor.WordLeft                    # 向左移动一个单词。
            QTextCursor.End                         # 移到文档的末尾。
            QTextCursor.EndOfLine                   # 移动到当前行的末尾。
            QTextCursor.EndOfWord                   # 移到当前单词的末尾。
            QTextCursor.EndOfBlock                  # 移动到当前块的末尾。
            QTextCursor.NextBlock                   # 移动到下一个块的开头。
            QTextCursor.NextCharacter               # 移动到下一个角色。
            QTextCursor.NextWord                    # 转到下一个单词。
            QTextCursor.Down                        # 向下移动一行。
            QTextCursor.Right                       # 向右移动一个角色。
            QTextCursor.WordRight                   # 向右移动一个单词。
    
        
        QTextCursor.MoveMode
            QTextCursor.MoveAnchor                  # 将锚点移动到与光标本身相同的位置。
            QTextCursor.KeepAnchor                  # 将锚固定在原处。
    

  • 可用信号
    textChanged()                                   # 文本改变时
    selectionChanged()                              # 选中内容改变时
    modificationChanged(bool)                       # 编辑状态改变时,发送是否是编辑状态
    cursorPositionChanged()                         # 光标位置改变时
    blockCountChanged(int)                          # 块的个数发生改变时,发送块的个数
    updateRequest(QRect rect, int dy)               # 内容更新请求时
    # 文本框内内容太多时,滚动滚动条时候,文本框显示的内容发生改变,那么就需要重新绘制,重新请求当前需要展示什么内容
    # 此时就会触发更新请求信号,此时会对更新区域矩形、垂直方向滚动步长进行发送
    copyAvailable(bool)                             # 复制可用时
    redoAvailable(bool)                             # 重做可用时
    undoAvailable(bool)                             # 撤销可用时
    

  • 代码示例
  • 示例1:创建和功能作用
    from PyQt5.Qt import *
    import sys
    
    class Windows(QWidget):
        def __init__(self):
            super().__init__()
            self.setWindowTitle('QPlainTextEdit-创建使用')
            self.resize(500, 500)
            self.widget_list()
    
        def widget_list(self):
            self.add_widget()
            self.占位提示文本()
            # self.只读设置()
            # self.格式设置()
            # self.软换行()
            # self.覆盖模式()
            # self.Tab键设置()
            # self.文本操作()
            # self.文本操作区别()
            # self.文本块数操作()
            # self.常用操作_放大缩小()
            self.滚动操作()
    
        def add_widget(self):
            pte1 = QPlainTextEdit(self)
            # pte2 = QPlainTextEdit('提示文本', self)
            pte2 = QPlainTextEdit(self)
            pte1.resize(480, 200)
            pte1.move(10, 20)
    
            pte2.resize(480, 200)
            pte2.move(pte1.x(), pte1.y()+pte1.height()+10)
    
            btn = QPushButton(self)
            btn.move(pte2.x(), pte2.y()+pte2.height()+10)
            btn.setVisible(False)
    
            self.pte1 = pte1
            self.pte2 = pte2
            self.btn = btn
    
        def 占位提示文本(self):
            self.pte1.setPlaceholderText('请输入你的个人信息')
            self.pte2.setPlaceholderText('请输入相关内容!')
    
        def 只读设置(self):
            self.pte1.setPlainText('我喜欢Python ' * 2)
            self.pte2.setPlainText('我喜欢Python ' * 2)
            self.pte1.setReadOnly(True)
    
        def 格式设置(self):
            tcf = QTextCharFormat()
            tcf.setFontPointSize(20)
            tcf.setFontFamily('华文行楷')
            tcf.setToolTip('提示信息')
            self.pte1.setCurrentCharFormat(tcf)
            self.pte2.setCurrentCharFormat(tcf)
    
            tcf2=QTextCharFormat()
            tcf2.setFontOverline(True)
            tcf2.setFontUnderline(True)
    
            self.pte1.setCurrentCharFormat(tcf2)
            self.pte2.mergeCurrentCharFormat(tcf2)
    
        def 软换行(self):
            self.pte1.setLineWrapMode(QPlainTextEdit.NoWrap)
            self.pte2.setLineWrapMode(QPlainTextEdit.WidgetWidth)
    
            self.pte1.setPlainText('没有软换行 ' * 20)
            self.pte2.setPlainText('自动软换行 ' * 20)
    
        def 覆盖模式(self):
            self.pte1.setOverwriteMode(True)
    
            print(self.pte1.overwriteMode())
            print(self.pte2.overwriteMode())
    
        def Tab键设置(self):
            self.pte1.setTabChangesFocus(True)
            self.pte2.setTabStopDistance(160)
    
        def 文本操作(self):
            self.btn.setVisible(True)
            self.btn.setText('文本操作')
            self.btn.resize(100, 30)
    
            self.i = 0
    
            def text_oper():
                self.i += 1
                if self.i == 1:
                    self.pte1.insertPlainText('插入普通文本')
                elif self.i == 2:
                    self.pte1.appendPlainText('追加普通文本')
                else:
                    self.pte1.appendHtml('<a href="https://www.baidu.com">追加HTML文本</a>')
                    self.i = 0
    
            self.btn.clicked.connect(text_oper)
    
    
            pass
    
        def 文本操作区别(self):
            # 首先添加一个QTextEdit对象,用来进行对比
            te = QTextEdit(self)
            te.resize(480, 200)
            # 放置在pte2上面
            te.move(self.pte1.x(), self.pte1.y() + self.pte1.height() + 10)
    
            self.btn.setVisible(True)
            self.btn.setText('插入表格')
            self.btn.resize(100, 30)
    
            table_str = """
            <table border=1>
                <tr>
                    <td>A1</td>
                    <td>B1</td>
                    <td>C1</td>
                </tr>
                <tr>
                    <td>A2</td>
                    <td>B2</td>
                    <td>C2</td>
                </tr>
            </table>
            """
    
            # table_str = '<table><tr><td>A1</td></tr></table>'
            def append_table():
                self.pte1.insertPlainText('这是QPlainTextEdit对象')
                te.insertPlainText('这是QTextEdit对象')
                self.pte1.appendHtml(table_str)
                te.insertHtml(table_str)
    
            self.btn.clicked.connect(append_table)
    
        def 文本块数操作(self):
            self.btn.setVisible(True)
            self.btn.setText('获取文本块数')
            self.btn.resize(150, 30)
    
            def test():
                n = self.pte1.blockCount()
                m = self.pte1.maximumBlockCount()
    
                self.pte2.insertPlainText('上面文本编辑器当前段落数:' + str(n) + '\n')
                self.pte2.insertPlainText('上面文本编辑器最大段落数:' + str(m) +'\n')
    
                self.pte1.setMaximumBlockCount(3)
    
            self.btn.clicked.connect(test)
    
        def 常用操作_放大缩小(self):
            self.pte1.zoomIn(5)
            self.pte2.zoomIn(-2)
    
        def 滚动操作(self):
            self.pte1.appendPlainText('定位光标所在行\n' * 50)
    
            def btn_test():
                self.pte1.setCenterOnScroll(True)       # 设置可以将最后一行定位到中间位置
                self.pte1.centerCursor()                # 将光标所在行定位到中间
                # self.pte1.ensureCursorVisible()       # 光标所在行超出编辑范围时,将光标所在行定位到顶部/底部
                self.pte1.setFocus()
    
            self.btn.setVisible(True)
            self.btn.resize(150, 30)
            self.btn.setText('定位光标')
            self.btn.clicked.connect(btn_test)
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        window = Windows()
    
        window.show()
        sys.exit(app.exec_())
    
  • 示例2:光标操作
    from PyQt5.Qt import *
    import sys
    
    app = QApplication(sys.argv)
    window = QWidget()
    window.resize(500, 550)
    window.setWindowTitle('QPlainTextEdit-光标操作')
    
    pte = QPlainTextEdit(window)
    te = QTextEdit(window)
    pte.resize(480, 200)
    pte.move(10, 10)
    
    te.resize(480,200)
    te.move(pte.x(), pte.y()+pte.height()+10)
    
    tc = pte.textCursor()
    tc2 = te.textCursor()
    
    def insert_img():
        pte.clear()
        te.clear()
    
        img = QTextImageFormat()
        img.setName('../images/jpg/1.jpg')
        img.setWidth(460)
        img.setHeight(180)
    
        tc.insertImage(img)
        tc2.insertImage(img)
    
    def insert_tab():
        pte.clear()
        te.clear()
    
        tbf = QTextTableFormat()
        tbf.setBorder(2)
        tbf.setWidth(200)
        tbf.setBackground(QColor(255,0,0))
    
        tc.insertTable(3, 5, tbf)
        tc2.insertTable(3, 5, tbf)
    
    def insert_text():
        pte.clear()
        te.clear()
    
        tc.insertText('插入文本内容 \n' * 20 )
        tc2.insertText('插入文本内容 \n' * 20 )
    
    def get_cursor():
        pte.clear()
        te.clear()
    
        pte.insertPlainText('获取指定坐标位置的光标\n' * 20)
        # 获取指定坐标位置的光标对象
        new_tc = pte.cursorForPosition(QPoint(100, 80))
        new_tc.insertText('在光标位置插入内容')
    
    def cursor_width():
        pte.setCursorWidth(10)
        te.setCursorWidth(20)
        pte.setFocus()
        te.setFocus()
    
    def move_cursor():
        pte.clear()
        pte.insertPlainText('插入文本内容\n' * 50)
    
        # 移动光标到开头位置,并且锚点固定在原处
        pte.moveCursor(QTextCursor.Start, QTextCursor.KeepAnchor)
    
        # 移动光标到下一行,并且锚点跟随移动到光标位置
        pte.moveCursor(QTextCursor.Down, QTextCursor.MoveAnchor)
    
        pte.setFocus()
    
    
    
    
    btn = QPushButton(window)
    btn.move(te.x(),te.y()+te.height()+10)
    btn.resize(150,30)
    btn.setText('插入文本')
    btn.clicked.connect(insert_text)
    
    btn1 = QPushButton(window)
    btn1.resize(150,30)
    btn1.move(btn.x() + btn.width() + 10,btn.y())
    btn1.setText('插入图片')
    btn1.clicked.connect(insert_img)
    
    btn2 = QPushButton(window)
    btn2.resize(150,30)
    btn2.move(btn1.x() + btn1.width() + 10,btn1.y())
    btn2.setText('插入表格')
    btn2.clicked.connect(insert_tab)
    
    btn3 = QPushButton(window)
    btn3.resize(150,30)
    btn3.move(btn.x(),btn.y() + btn.height()+10)
    btn3.setText('获取光标')
    btn3.clicked.connect(get_cursor)
    
    btn4 = QPushButton(window)
    btn4.resize(150,30)
    btn4.move(btn1.x(),btn1.y()+btn1.height()+10)
    btn4.setText('光标宽度')
    btn4.clicked.connect(cursor_width)
    
    btn5 = QPushButton(window)
    btn5.resize(150,30)
    btn5.move(btn2.x(),btn2.y() + btn2.height()+10)
    btn5.setText('移动光标')
    btn5.clicked.connect(move_cursor)
    
    window.show()
    sys.exit(app.exec_())
    
  • 示例3:QPlainTextEdit可用信号1
    from PyQt5.Qt import *
    import sys
    
    class Windows(QWidget):
        def __init__(self):
            super().__init__()
            self.setWindowTitle('QPlainTextEdit-可用信号')
            self.resize(500, 500)
            self.widget_list()
    
        def widget_list(self):
            self.add_widget()
    
        def textchanged_btn(self):
            self.pte.textChanged.connect(lambda : print('文本内容发生了改变'))
    
        def selection_changed(self):
            tc = self.pte.textCursor()          # 获取文本光标
            text = tc.selectedText()            # 通过文本光标获取当前选中文本内容
            print('当前选中内容:', text)
    
        def selectionChanged_btn(self):
            # self.pte.selectionChanged.connect(lambda : print('选择的内容发生了改变'))
            # 通过文本光标,可用获取到当前选中的内容
            self.pte.selectionChanged.connect(self.selection_changed)
    
        def modification_Changed(self, val):
            if val:
                print('当前处于编辑状态', val)
            # 后期可以判断用户按下了保存,再设置文本文档的编辑状态为False
            doc = self.pte.document()
            doc.setModified(False)
    
        def modificationChanged_btn(self):
            self.pte.modificationChanged.connect(self.modification_Changed)
    
        def cursorPositionChanged_btn(self):
            self.pte.cursorPositionChanged.connect(lambda :print('光标位置发生了改变'))
    
        def blockCount_Changed(self, i):
            print('新增了一个段落,当前段落是第【' + str(i) + '】段')
    
        def blockCountChanged_btn(self):
            self.pte.blockCountChanged.connect(self.blockCount_Changed)
    
        def add_widget(self):
            pte = QPlainTextEdit(self)      # 实例化QPlainTextEdit对象
            self.pte = pte
            pte.resize(480, 200)
            pte.move(10, 10)
    
            frame = QFrame(self)
            frame.resize(480, 200)
            frame.move(pte.x(), pte.y() + pte.height()+10)
    
            for i in range(1, 4):
                for j in range(1, 4):
                    btn = QPushButton(frame)
                    btn.resize(150, 30)
                    btn.setObjectName(str(i)+str(j))
                    # print(btn.objectName())
                    btn.move((btn.width() + 10) * (j - 1), (btn.height()  + 10) * (i - 1))
    
    
            frame.findChild(QPushButton,'11').setText('文本内容改变信号')
            frame.findChild(QPushButton,'11').clicked.connect(self.textchanged_btn)
    
            frame.findChild(QPushButton,'12').setText('选中内容改变信号')
            frame.findChild(QPushButton,'12').clicked.connect(self.selectionChanged_btn)
    
            frame.findChild(QPushButton, '13').setText('编辑状态改变信号')
            frame.findChild(QPushButton, '13').clicked.connect(self.modificationChanged_btn)
    
            frame.findChild(QPushButton, '21').setText('光标位置改变信号')
            frame.findChild(QPushButton, '21').clicked.connect(self.cursorPositionChanged_btn)
    
            frame.findChild(QPushButton, '22').setText('块的个数改变信号')
            frame.findChild(QPushButton, '22').clicked.connect(self.blockCountChanged_btn)
    
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        window = Windows()
    
        window.show()
        sys.exit(app.exec_())
    
  • 示例4:QPlainTextEdit可用信号2
    • 模拟行号根据内容增加而移动
    from PyQt5.Qt import *
    import sys
    
    class Windows(QWidget):
        def __init__(self):
            super().__init__()
            self.setWindowTitle('QPlainTextEdit-可用信号2')
            self.resize(500, 500)
            self.widget_list()
            self.old_count = 0
    
        def widget_list(self):
            self.add_widget()
    
        def update_rows(self):
            max_num = self.pte.blockCount() + 20
            num_list = '\n'.join([str(i) for i in range(1, max_num)])
            self.labe.setText(num_list)
            self.labe.adjustSize()   # 设置标签大小跟随文本内容(跟随内容)改变
            self.labe.setAlignment(Qt.AlignRight)  # 设置文本内容居右排列
    
        def update_Request(self, str, i):
            self.labe.move(0, self.labe.y() + i)
            if self.old_count == self.pte.blockCount():
                return None
            self.update_rows()
            self.old_count = self.pte.blockCount()
    
    
        def add_widget(self):
            pte = QPlainTextEdit(self)
            self.pte = pte
            pte.resize(450, 300)
            pte.move(40, 10)
    
            num_parent = QWidget(self)
            num_parent.resize(30, 300)
            num_parent.move(10, 10)
            num_parent.setStyleSheet('background-color: #d4d4d4;')
    
            self.labe = QLabel(num_parent)
            self.labe.move(0, 5)
            self.update_rows()
    
            pte.updateRequest.connect(self.update_Request)      # QPlainTextEdit内容更新事件
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        window = Windows()
    
        window.show()
        sys.exit(app.exec_())
Logo

鸿蒙生态一站式服务平台。

更多推荐