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_())