介绍
QPlainTextEdit 是 PySide2 中专为 多行纯文本编辑 设计的控件,继承自 QAbstractScrollArea,具备轻量渲染、高效编辑的特性,尤其适合处理代码、日志、配置文件等无格式文本。
功能
仅支持纯文本(无富格式),专注于多行文本的输入、编辑与展示;
优点
性能优化:采用
QPlainTextDocument存储文本,比支持富格式的QTextEdit更轻量,处理十万级行文本时卡顿感显著降低;滚动友好:内置垂直 / 水平滚动条,文本超出可视区域时自动适配;
编辑便捷:支持快捷键(复制 / 粘贴 / 撤销)、文本选中、行定位等基础编辑能力;
适用场景
代码编辑器、日志查看器、配置文件编辑、多行文本输入(如备注、反馈)。
基础用法
1. 控件创建与基础配置
from PySide2.QtWidgets import QApplication, QPlainTextEdit, QWidget, QVBoxLayout
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("QPlainTextEdit 基础示例")
layout = QVBoxLayout(window)
# 1. 初始化 QPlainTextEdit(默认空文本,支持多行)
plain_edit = QPlainTextEdit()
# 2. 基础配置
plain_edit.setPlaceholderText("请输入多行纯文本(如日志、代码)...") # 输入提示
plain_edit.setLineWrapMode(QPlainTextEdit.WidgetWidth) # 自动换行(按控件宽度折行)
# plain_edit.setLineWrapMode(QPlainTextEdit.NoWrap) # 禁止换行(适合代码编辑,需横向滚动)
# 3. 设置初始文本(支持 n 换行)
initial_text = """# 日志记录
[2025-10-01 09:00:00] 程序启动成功
[2025-10-01 09:01:30] 加载配置文件 config.ini
[2025-10-01 09:02:15] 连接数据库成功
[2025-10-01 09:03:40] 接收用户请求:/api/getData
"""
plain_edit.setPlainText(initial_text)
layout.addWidget(plain_edit)
window.show()
sys.exit(app.exec_())
2. 核心文本操作方法
| 方法 | 功能描述 | 示例代码 |
|---|---|---|
setPlainText(str) |
设置控件的纯文本内容(覆盖原有内容) | edit.setPlainText("新文本n第二行") |
toPlainText() |
获取当前所有文本内容(含换行符 n) |
content = edit.toPlainText() |
appendPlainText(str) |
在文本末尾追加新文本(自动换行) | edit.appendPlainText("[10:00] 新日志") |
clear() |
清空所有文本内容 | edit.clear() |
selectAll() |
全选当前文本 | edit.selectAll() |
cut()、copy()、paste() |
剪切 / 复制 / 粘贴文本(需绑定快捷键或按钮) | edit.copy()(复制选中内容) |
3. 文本选中与光标控制
QPlainTextEdit 通过 textCursor() 获取光标对象(QTextCursor),实现精准的文本选中与光标定位,适合需要 “局部编辑” 的场景(如代码高亮、文本替换):
# 1. 选中指定范围的文本(参数:起始位置,选中长度)
plain_edit.setPlainText("Hello PySide2nThis is QPlainTextEdit")
QTextCursor cursor = plain_edit.textCursor()
cursor.setPosition(6) # 光标移到索引 6("PySide2" 开头)
cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, 7) # 向右选中 7 个字符("PySide2")
plain_edit.setTextCursor(cursor) # 应用选中状态
# 2. 光标定位到文本末尾(常用于追加文本后自动滚动到底部)
def scroll_to_bottom():
cursor = plain_edit.textCursor()
cursor.movePosition(QTextCursor.End) # 光标移到末尾
plain_edit.setTextCursor(cursor)
plain_edit.ensureCursorVisible() # 确保光标所在行可见(自动滚动)
# 3. 获取选中的文本
def get_selected_text():
if plain_edit.textCursor().hasSelection():
print("选中的文本:", plain_edit.textCursor().selectedText())
else:
print("未选中任何文本")
# 绑定按钮触发选中与获取操作(示例)
from PySide2.QtWidgets import QPushButton
select_btn = QPushButton("选中 PySide2")
select_btn.clicked.connect(lambda: cursor_operation())
get_btn = QPushButton("获取选中文本")
get_btn.clicked.connect(get_selected_text)
layout.addWidget(select_btn)
layout.addWidget(get_btn)
进阶功能
文本搜索与替换
结合 QTextCursor 实现 “查找下一个”“替换” 功能,适合日志检索、代码修改场景:
from PySide2.QtWidgets import QHBoxLayout, QLineEdit, QPushButton, QMessageBox
class SearchReplaceWidget(QWidget):
def __init__(self, plain_edit):
super().__init__()
self.plain_edit = plain_edit
self.current_position = 0 # 当前搜索起始位置
self.init_ui()
def init_ui(self):
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
# 搜索输入框
self.search_edit = QLineEdit()
self.search_edit.setPlaceholderText("输入搜索文本...")
# 替换输入框
self.replace_edit = QLineEdit()
self.replace_edit.setPlaceholderText("输入替换文本...")
# 按钮
self.find_btn = QPushButton("查找下一个")
self.replace_btn = QPushButton("替换")
# 绑定事件
self.find_btn.clicked.connect(self.find_next)
self.replace_btn.clicked.connect(self.replace_current)
self.search_edit.returnPressed.connect(self.find_next) # 回车触发查找
layout.addWidget(self.search_edit)
layout.addWidget(self.replace_edit)
layout.addWidget(self.find_btn)
layout.addWidget(self.replace_btn)
# 查找下一个匹配项
def find_next(self):
search_text = self.search_edit.text().strip()
if not search_text:
QMessageBox.warning(self, "提示", "请输入搜索文本!")
return
# 获取全文
full_text = self.plain_edit.toPlainText()
# 从当前位置开始搜索
index = full_text.indexOf(search_text, self.current_position)
if index != -1:
# 选中找到的文本
cursor = self.plain_edit.textCursor()
cursor.setPosition(index)
cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, len(search_text))
self.plain_edit.setTextCursor(cursor)
self.plain_edit.ensureCursorVisible() # 滚动到可视区域
# 更新下一次搜索起始位置
self.current_position = index + len(search_text)
# 若已到文本末尾,重置位置
if self.current_position >= len(full_text):
self.current_position = 0
else:
QMessageBox.information(self, "提示", "已找到最后一个匹配项!")
self.current_position = 0
# 替换当前选中的匹配项
def replace_current(self):
search_text = self.search_edit.text().strip()
replace_text = self.replace_edit.text()
if not search_text:
QMessageBox.warning(self, "提示", "请输入搜索文本!")
return
cursor = self.plain_edit.textCursor()
if cursor.hasSelection() and cursor.selectedText() == search_text:
cursor.insertText(replace_text) # 替换选中文本
self.current_position = cursor.position() # 更新搜索位置
self.find_next() # 自动查找下一个
else:
# 未选中或选中内容不匹配,先查找
self.find_next()
# 应用搜索替换功能
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("QPlainTextEdit 搜索替换")
layout = QVBoxLayout(window)
plain_edit = QPlainTextEdit()
plain_edit.setPlainText("Python 是一门优雅的语言nPython 适合数据分析nPython 也适合 GUI 开发")
search_replace_widget = SearchReplaceWidget(plain_edit)
layout.addWidget(search_replace_widget)
layout.addWidget(plain_edit)
window.show()
sys.exit(app.exec_())
只读模式
设置 setReadOnly(True) 后,文本仅可查看、复制,无法修改,适合展示日志、报告等静态内容:
plain_edit = QPlainTextEdit()
plain_edit.setPlainText("[日志开始]n2025-10-01 09:00: 系统启动n2025-10-01 09:05: 连接成功")
plain_edit.setReadOnly(True) # 启用只读模式
# 可选:设置文本颜色(灰色,增强只读视觉效果)
plain_edit.setStyleSheet("color: #666666;")
样式定制(美化外观)
通过 setStyleSheet 定制控件样式,支持背景色、边框、字体等,适配整体界面风格:
plain_edit.setStyleSheet("""
QPlainTextEdit {
background-color: #f8f9fa; /* 背景色(浅灰) */
border: 1px solid #dee2e6; /* 边框(淡蓝灰) */
border-radius: 6px; /* 圆角 */
padding: 8px; /* 内边距(避免文本贴边) */
font-family: "Consolas", "Microsoft YaHei"; /* 字体(适合代码/日志) */
font-size: 14px; /* 字体大小 */
color: #212529; /* 文本颜色(深灰) */
}
QPlainTextEdit:focus {
border-color: #80bdff; /* 获焦时边框色(淡蓝) */
outline: none; /* 清除默认获焦外框 */
}
QPlainTextEdit:read-only {
background-color: #e9ecef; /* 只读时背景色(更浅的灰) */
}
""")