PySide6从0开始学习的笔记(七) 控件(Widget)之文字输入类控件

文字输入类控件用于接收用户文本 / 数值输入,是表单、设置界面的核心组件。

1. QLineEdit(单行文本框)

核心作用:单行文本输入(如用户名、密码、搜索框)。

关键特性

  • 密码模式:setEchoMode(QLineEdit.Password);
  • 输入验证:通过 QValidator 限制输入格式(整数、浮点数、正则);
  • 占位符提示:setPlaceholderText("请输入用户名");
  • 信号:textChanged(str)(实时变化)、editingFinished()(输入完成)。

输入验证示例

python 复制代码
import sys

from PySide6.QtWidgets import QLineEdit, QApplication

app = QApplication(sys.argv)
line_edit = QLineEdit()
# 仅允许输入数字
line_edit.setPlaceholderText("请输入数字")  # 设置占位符

def on_text_changed(text):
    if not text.isdigit():
        print("输入错误,请修改")
        line_edit.setStyleSheet("color: red")
    else:
        line_edit.setStyleSheet("color: black")

line_edit.textChanged.connect(on_text_changed)

line_edit.show()
app.exec()

2. QPlainTextEdit(纯文本框)

QPlainTextEdit 是 PySide6 中用于编辑和显示纯文本的控件,专为处理大文本文件优化(相比 QTextEdit 更轻量,无富文本渲染开销),支持行号、语法高亮、撤销 / 重做、文本选择、滚动等核心功能,是编写日志查看器、代码编辑器、纯文本编辑器的首选控件。

核心特性
  1. 轻量级纯文本处理:仅处理纯文本,无富文本(如字体 / 颜色 / 图片)渲染,性能优于 QTextEdit;
  2. 行级操作:便捷的行增删、行内容获取 / 修改;
  3. 编辑功能:默认支持撤销、重做、复制、粘贴、剪切;
  4. 滚动与视图:支持自动滚动、光标定位、可见区域控制;
  5. 信号与槽:文本变化、光标移动、选择变化等信号,便于交互逻辑实现;
  6. 自定义扩展:可结合 QSyntaxHighlighter 实现语法高亮,结合 QAbstractScrollArea 自定义滚动条 / 行号。
基本使用
1. 基础初始化与布局
复制代码
import sys
from PySide6.QtWidgets import (QApplication, QMainWindow, QPlainTextEdit,
                               QVBoxLayout, QWidget)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QPlainTextEdit 示例")
        self.resize(800, 600)

        # 1. 创建 QPlainTextEdit 实例
        self.text_edit = QPlainTextEdit()

        # 2. 基础配置
        self.text_edit.setPlaceholderText("请输入纯文本内容...")  # 占位提示
        self.text_edit.setReadOnly(False)  # 是否只读(True 则无法编辑)
        self.text_edit.setLineWrapMode(QPlainTextEdit.NoWrap)   # NoWrap:不自动换行(默认)
                                                                # QPlainTextEdit.WidgetWidth:按控件宽度自动换行

        # 3. 设置中心部件
        central_widget = QWidget()
        layout = QVBoxLayout(central_widget)
        layout.addWidget(self.text_edit)
        self.setCentralWidget(central_widget)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())
2. 文本操作核心方法
方法 功能 示例
setPlainText(text) 设置全部文本(覆盖原有内容) self.text_edit.setPlainText("Hello PySide6!")
toPlainText() 获取全部文本(返回字符串) text = self.text_edit.toPlainText()
insertPlainText(text) 在光标位置插入文本(不覆盖) self.text_edit.insertPlainText("插入的内容")
appendPlainText(text) 在末尾追加文本(自动换行) self.text_edit.appendPlainText("新行内容")
clear() 清空所有文本 self.text_edit.clear()
undo()/redo() 撤销 / 重做操作 self.text_edit.undo()
copy()/cut()/paste() 复制 / 剪切 / 粘贴 self.text_edit.copy()
行级操作(高频需求)
复制代码
import sys

from PySide6.QtGui import QTextCursor
from PySide6.QtWidgets import (QApplication, QMainWindow, QPlainTextEdit,
                               QVBoxLayout, QWidget)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QPlainTextEdit 示例")
        self.resize(800, 600)

        # 1. 创建 QPlainTextEdit 实例
        self.text_edit = QPlainTextEdit()

        # 2. 基础配置
        self.text_edit.setPlainText("line0\n"
                                    "line1\n"
                                    "line2\n"
                                    "line3\n"
                                    "line4\n"
                                    "line5\n"
                                    "line6\n")
        self.text_edit.setReadOnly(False)  # 是否只读(True 则无法编辑)
        self.text_edit.setLineWrapMode(QPlainTextEdit.NoWrap)   # NoWrap:不自动换行(默认)
                                                                # QPlainTextEdit.WidgetWidth:按控件宽度自动换行

        # 获取当前光标所在行号(从 0 开始)
        # current_line = self.text_edit.textCursor().blockNumber()
        # print(current_line)

        # 3. 设置中心部件
        central_widget = QWidget()
        layout = QVBoxLayout(central_widget)
        layout.addWidget(self.text_edit)
        self.setCentralWidget(central_widget)

    # 获取指定行内容(行号从 0 开始)
    def get_line_content(self, line_num):
        block = self.text_edit.document().findBlockByNumber(line_num)
        return block.text() if block.isValid() else ""

    # 修改指定行内容
    def set_line_content(self, line_num, new_text):
        cursor = self.text_edit.textCursor()
        block = self.text_edit.document().findBlockByNumber(line_num)
        if block.isValid():
            cursor.setPosition(block.position())  # 定位到行首
            cursor.select(QTextCursor.SelectionType.BlockUnderCursor)  # 选中整行
            cursor.insertText(new_text)  # 替换内容

    # 删除指定行
    def delete_line(self, line_num):
        cursor = self.text_edit.textCursor()
        block = self.text_edit.document().findBlockByNumber(line_num)
        if block.isValid():
            cursor.setPosition(block.position())
            cursor.select(QTextCursor.SelectionType.BlockUnderCursor)
            cursor.removeSelectedText()  # 删除选中内容
            # 移除多余的换行符(可选)
            # cursor.deleteChar()




if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    print(f"第一行内容:", window.get_line_content(1))  # 获取第二行内容
    window.set_line_content(1, "\n新内容1")  # 修改第二行内容
    print(f"第一行内容:", window.get_line_content(1))  # 获取第二行内容
    window.delete_line(3)
    window.show()
    sys.exit(app.exec())
光标与选择控制

QPlainTextEdit 的光标操作依赖 QTextCursor,可实现精准的文本定位、选择、编辑:

复制代码
# 获取当前光标对象
cursor = self.text_edit.textCursor()

# 1. 光标定位
cursor.movePosition(cursor.Start)  # 移到文本开头
cursor.movePosition(cursor.End)    # 移到文本结尾
cursor.movePosition(cursor.Down, cursor.MoveAnchor, 5)  # 向下移动5行
self.text_edit.setTextCursor(cursor)  # 应用光标位置

# 2. 文本选择
cursor.setPosition(10)  # 起始位置
cursor.movePosition(cursor.Right, cursor.KeepAnchor, 5)  # 向右选择5个字符
selected_text = cursor.selectedText()  # 获取选中的文本

# 3. 替换选中的文本
cursor.insertText("替换后的内容")

# 4. 选中所有文本
self.text_edit.selectAll()
信号与槽(核心交互)

QPlainTextEdit 提供丰富的信号,用于响应文本变化、光标移动等事件:

信号 触发条件
textChanged() 文本内容发生变化时(每次输入 / 删除字符都会触发)
cursorPositionChanged() 光标位置改变时
selectionChanged() 选中的文本范围改变时
undoAvailable(bool) 撤销操作可用 / 不可用时
redoAvailable(bool) 重做操作可用 / 不可用时
示例:响应文本变化和光标移动
复制代码
import sys

from PySide6.QtCore import QMetaObject, Slot
from PySide6.QtWidgets import QPlainTextEdit, QApplication


class MyTextEdit(QPlainTextEdit):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUI()
        QMetaObject.connectSlotsByName(self)

    def setupUI(self):
        self.textChanged.connect(self.on_textChanged)
        self.cursorPositionChanged.connect(self.on_cursorPositionChanged)

    @Slot()
    def on_textChanged(self):
        """文本变化时触发:统计字符数和行数"""
        text = self.toPlainText()
        char_count = len(text)
        line_count = self.document().blockCount()
        self.setWindowTitle(f"字符数:{char_count} | 行数:{line_count}")

    @Slot()
    def on_cursorPositionChanged(self):
        """光标移动时触发:显示当前行/列"""
        cursor = self.textCursor()
        line = cursor.blockNumber() + 1  # 行号从1开始显示
        col = cursor.columnNumber() + 1  # 列号从1开始显示
        print(f"当前位置:第 {line} 行,第 {col} 列")

app = QApplication(sys.argv)
text_edit = MyTextEdit()
text_edit.show()
sys.exit(app.exec())
高级配置
1. 换行模式

控制文本超出控件宽度时的换行行为:

复制代码
# 可选模式:
# NoWrap:不换行(横向滚动条出现)
# WidgetWidth:按控件宽度自动换行(默认)
# FixedPixelWidth:按固定像素宽度换行
# FixedColumnWidth:按固定字符数换行
self.text_edit.setLineWrapMode(QPlainTextEdit.WidgetWidth)
2. 滚动控制
复制代码
# 自动滚动到末尾(如日志输出场景)
self.text_edit.verticalScrollBar().setValue(
    self.text_edit.verticalScrollBar().maximum()
)

# 滚动到指定行
def scroll_to_line(line_num):
    block = self.text_edit.document().findBlockByNumber(line_num)
    if block.isValid():
        self.text_edit.scrollToBlock(block)
3. 只读模式与编辑权限
复制代码
self.text_edit.setReadOnly(True)  # 只读(无法编辑,可选中/复制)
self.text_edit.setUndoRedoEnabled(False)  # 禁用撤销/重做
self.text_edit.setAcceptRichText(False)  # 拒绝粘贴富文本(仅保留纯文本)
4. 语法高亮(扩展)

结合 QSyntaxHighlighter 实现代码 / 日志的语法高亮,示例(Python 关键字高亮):

复制代码
import sys

from PySide6.QtGui import QSyntaxHighlighter, QTextCharFormat, QColor
from PySide6.QtWidgets import QTextEdit, QApplication


class PythonHighlighter(QSyntaxHighlighter):
    def __init__(self, parent=None):
        super().__init__(parent)
        # 定义高亮格式
        keyword_format = QTextCharFormat()
        keyword_format.setForeground(QColor("#FF7F00"))  # 橙色
        keyword_format.setFontWeight(75)  # 加粗

        # Python 关键字列表
        self.keywords = [
            "and", "as", "assert", "break", "class", "continue",
            "def", "del", "elif", "else", "except", "False",
            "finally", "for", "from", "global", "if", "import",
            "in", "is", "lambda", "None", "nonlocal", "not",
            "or", "pass", "raise", "return", "True", "try",
            "while", "with", "yield"
        ]

        # 存储高亮规则(正则表达式 + 格式)
        self.highlight_rules = []
        for keyword in self.keywords:
            pattern = rf"\b{keyword}\b"  # 单词边界匹配
            self.highlight_rules.append((pattern, keyword_format))

    def highlightBlock(self, text):
        """对每一行文本应用高亮规则"""
        for pattern, format in self.highlight_rules:
            import re
            for match in re.finditer(pattern, text):
                start, end = match.span()
                self.setFormat(start, end - start, format)

class myTextEdit(QTextEdit):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUI()

    def setupUI(self):
        self.highlighter = PythonHighlighter(self.document())


if __name__ == "__main__":
    app = QApplication(sys.argv)
    text_edit = myTextEdit()
    text_edit.show()
    sys.exit(app.exec())
常见场景示例
1. 日志输出窗口(自动滚动 + 只读)
复制代码
class LogWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.text_edit = QPlainTextEdit()
        self.text_edit.setReadOnly(True)
        self.text_edit.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.setCentralWidget(self.text_edit)

    def append_log(self, log_text):
        """追加日志并自动滚动到末尾"""
        self.text_edit.appendPlainText(log_text)
        # 自动滚动
        scroll_bar = self.text_edit.verticalScrollBar()
        scroll_bar.setValue(scroll_bar.maximum())

# 使用
log_window = LogWindow()
log_window.append_log("[INFO] 程序启动成功")
log_window.append_log("[ERROR] 数据库连接失败")
2. 带行号的代码编辑器(简化版)
复制代码
import sys

from PySide6.QtGui import QPainter, QColor
from PySide6.QtWidgets import QWidget, QTextEdit, QHBoxLayout, QPlainTextEdit, QApplication
from PySide6.QtCore import Qt

class LineNumberWidget(QWidget):
    """行号显示控件"""
    def __init__(self, text_edit, parent=None):
        super().__init__(parent)
        self.text_edit = text_edit
        self.text_edit.cursorPositionChanged.connect(self.update)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.fillRect(event.rect(), QColor("#F0F0F0"))  # 行号背景色

        # 获取可见的行范围
        block = self.text_edit.firstVisibleBlock()
        block_number = block.blockNumber()
        top = self.text_edit.blockBoundingGeometry(block).translated(self.text_edit.contentOffset()).top()
        bottom = top + self.text_edit.blockBoundingRect(block).height()

        # 绘制行号
        while block.isValid() and top <= event.rect().bottom():
            if block.isVisible() and bottom >= event.rect().top():
                number = str(block_number + 1)
                painter.drawText(0, int(top), self.width() - 5, self.text_edit.fontMetrics().height(),
                                 Qt.AlignRight, number)
            block = block.next()
            top = bottom
            bottom = top + self.text_edit.blockBoundingRect(block).height()
            block_number += 1

# 组合行号和编辑区
class CodeEditor(QWidget):
    def __init__(self):
        super().__init__()
        layout = QHBoxLayout(self)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)

        self.text_edit = QPlainTextEdit()
        self.line_number = LineNumberWidget(self.text_edit)
        self.line_number.setFixedWidth(40)  # 行号宽度

        layout.addWidget(self.line_number)
        layout.addWidget(self.text_edit)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    editor = CodeEditor()
    editor.show()
    sys.exit(app.exec())
注意事项
  1. 性能优化 :处理超大型文本(如 10 万行以上)时,建议关闭实时更新(如 textChanged 信号),批量操作后再刷新;
  2. 编码问题:读取 / 保存文本时需指定编码(如 UTF-8),避免乱码;
  3. 与 QTextEdit 区分:QTextEdit 支持富文本,但性能低;QPlainTextEdit 仅纯文本,适合大文本场景;
  4. 撤销 / 重做 :默认开启,可通过 setUndoRedoEnabled(False) 禁用,避免内存占用过高;
  5. 换行符兼容 :不同系统换行符(\n/\r\n)可通过 document().setPlainText() 自动适配。

总结

QPlainTextEdit 是 PySide6 中处理纯文本的核心控件,通过基础文本操作、光标控制、信号响应可满足大部分纯文本编辑需求,结合语法高亮、行号控件等扩展可实现代码编辑器、日志查看器等复杂功能。重点掌握其轻量级特性、行级操作和信号槽机制,即可灵活应用于各类文本处理场景。


3. QTextEdit(多行文本框)

QTextEdit 是 PySide6 中功能强大的多行富文本编辑控件,支持纯文本、HTML 富文本的输入 / 显示,还提供文本格式化、撤销 / 重做、查找替换等高级功能,是实现记事本、富文本编辑器、聊天框、文档预览等场景的核心组件。

  • 核心作用:多行富文本 / 纯文本输入(如备注、编辑器)。

核心特性:

  1. 双模式支持 :可作为纯文本编辑器(类似 QPlainTextEdit)或富文本编辑器(支持字体、颜色、段落格式);
  2. 内容操作:支持文本插入、删除、替换,以及撤销 / 重做、复制 / 粘贴;
  3. 格式控制:可设置选中文本的字体、颜色、对齐方式、列表样式等;
  4. 布局与滚动:自动换行、水平 / 垂直滚动,支持自定义页边距;
  5. 信号反馈:文本变化、光标移动、选择范围变更等信号,满足交互需求;
  6. 只读模式:可切换为只读,用于富文本内容展示(如帮助文档)。
基础用法

基本初始化与布局

python 复制代码
import sys
from PySide6.QtWidgets import (
    QApplication, QWidget, QTextEdit, 
    QVBoxLayout, QPushButton, QHBoxLayout
)
from PySide6.QtGui import QFont, QColor
from PySide6.QtCore import Qt

class TextEditDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("QTextEdit 详解")
        self.resize(800, 600)
        
        # 1. 创建核心控件
        self.text_edit = QTextEdit()
        
        # 2. 基础配置
        self.text_edit.setPlaceholderText("请输入内容(支持富文本)")  # 占位提示
        self.text_edit.setFont(QFont("Microsoft YaHei", 12))  # 默认字体
        self.text_edit.setLineWrapMode(QTextEdit.WidgetWidth)  # 按控件宽度自动换行
        self.text_edit.setTabStopDistance(40)  # Tab 缩进距离(像素)

        # 3. 功能按钮布局
        btn_layout = QHBoxLayout()
        # 纯文本/富文本切换
        self.btn_plain = QPushButton("纯文本模式")
        self.btn_plain.clicked.connect(self.switch_plain_mode)
        # 设置选中文本颜色
        btn_color = QPushButton("选中文本设为红色")
        btn_color.clicked.connect(self.set_text_color)
        # 插入图片
        btn_image = QPushButton("插入图片")
        btn_image.clicked.connect(self.insert_image)
        # 清空内容
        btn_clear = QPushButton("清空")
        btn_clear.clicked.connect(self.text_edit.clear)

        btn_layout.addWidget(self.btn_plain)
        btn_layout.addWidget(btn_color)
        btn_layout.addWidget(btn_image)
        btn_layout.addWidget(btn_clear)

        # 4. 主布局
        main_layout = QVBoxLayout()
        main_layout.addLayout(btn_layout)
        main_layout.addWidget(self.text_edit)
        self.setLayout(main_layout)

        # 5. 绑定信号(监听文本变化)
        self.text_edit.textChanged.connect(self.on_text_changed)

    def switch_plain_mode(self):
        """切换纯文本/富文本模式"""
        if self.text_edit.acceptRichText():
            self.text_edit.setAcceptRichText(False)  # 禁用富文本(纯文本模式)
            self.btn_plain.setText("富文本模式")
        else:
            self.text_edit.setAcceptRichText(True)   # 启用富文本
            self.btn_plain.setText("纯文本模式")

    def set_text_color(self):
        """设置选中文本颜色为红色"""
        # 获取文本光标(操作选中文本的核心)
        cursor = self.text_edit.textCursor()
        if cursor.hasSelection():  # 有选中内容
            # 设置选中文本格式
            char_format = cursor.charFormat()
            char_format.setForeground(QColor(255, 0, 0))  # 红色
            cursor.setCharFormat(char_format)

    def insert_image(self):
        """插入图片到光标位置"""
        # 替换为本地图片路径(支持 PNG/JPG 等)
        img_path = "demo.png"
        # 插入图片(参数:图片路径、替代文本、尺寸)
        self.text_edit.insertHtml(f'<img src="{img_path}" width="200" height="150"/>')

    def on_text_changed(self):
        """文本变化时触发(实时统计字符数)"""
        # 获取纯文本内容(排除富文本标签)
        plain_text = self.text_edit.toPlainText()
        char_count = len(plain_text)
        self.setWindowTitle(f"QTextEdit 详解 - 字符数:{char_count}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    demo = TextEditDemo()
    demo.show()
    sys.exit(app.exec())
核心功能与 API 详解
1. 内容操作(文本 / 富文本)
方法 说明 示例
setPlainText(text) 设置纯文本内容(覆盖原有内容) text_edit.setPlainText("Hello World")
toPlainText() 获取纯文本内容(忽略富文本格式) text = text_edit.toPlainText()
setHtml(html) 设置富文本内容(HTML 格式) text_edit.setHtml("<h1>标题</h1><p>段落</p>")
toHtml() 获取富文本的 HTML 源码 html = text_edit.toHtml()
insertPlainText(text) 在光标位置插入纯文本 text_edit.insertPlainText("插入内容")
insertHtml(html) 在光标位置插入富文本 text_edit.insertHtml("<b>加粗</b>")
append(text) 追加文本(自动换行,支持富文本) text_edit.append("新的一行")
clear() 清空所有内容 text_edit.clear()
undo()/redo() 撤销 / 重做操作 text_edit.undo()
copy()/cut()/paste() 复制 / 剪切 / 粘贴 text_edit.copy()
2. 格式控制(选中文本 / 全局)

(1)字符格式(字体、颜色、样式)

python 复制代码
from PySide6.QtWidgets import QApplication, QMainWindow, QTextEdit
from PySide6.QtGui import QFont, QColor, QTextCursor
import sys

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("富文本编辑器")
        self.resize(800, 600)  # 设置窗口大小(避免控件太小看不到效果)

        # 1. 创建核心控件
        self.text_edit = QTextEdit()

        # 2. 基础配置
        self.text_edit.setPlaceholderText("请输入内容(支持富文本)")
        self.text_edit.setLineWrapMode(QTextEdit.LineWrapMode.WidgetWidth)
        self.text_edit.setTabStopDistance(40)
        self.text_edit.setAcceptRichText(True)

        # 3. 设置默认字符格式
        # 方式1:直接给 QTextEdit 设置默认格式(推荐,对所有新输入文本生效)
        # default_format = self.text_edit.currentCharFormat()  # 获取控件默认格式
        # default_format.setFont(QFont("Microsoft YaHei UI", 36, QFont.Weight.Bold))  # 字体
        # default_format.setForeground(QColor("#ff0000"))  # 字体颜色
        # default_format.setBackground(QColor("#EEEE00"))  # 背景色
        # self.text_edit.setCurrentCharFormat(default_format)  # 应用到控件

        # (可选)方式2:通过光标设置后,将光标放回控件
        cursor = self.text_edit.textCursor()
        char_format = cursor.charFormat()
        char_format.setFont(QFont("Microsoft YaHei UI", 36, QFont.Weight.Bold))
        char_format.setForeground(QColor("#ff0000"))
        char_format.setBackground(QColor("#EEEEaa"))
        cursor.setCharFormat(char_format)
        self.text_edit.setTextCursor(cursor)  # 关键:将修改后的光标放回控件

        # 4. 将控件设置为主窗口中心部件(必须,否则控件不显示)
        self.setCentralWidget(self.text_edit)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

(2)段落格式(对齐、缩进、行距)

通过 QTextBlockFormat 控制段落样式:

python 复制代码
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QMainWindow, QTextEdit
from PySide6.QtGui import QFont, QColor, QTextCursor, QTextBlockFormat
import sys

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("富文本编辑器")
        self.resize(800, 600)  # 设置窗口大小(避免控件太小看不到效果)

        # 1. 创建核心控件
        self.text_edit = QTextEdit()

        # 2. 基础配置
        self.text_edit.setPlaceholderText("请输入内容(支持富文本)")
        self.text_edit.setLineWrapMode(QTextEdit.LineWrapMode.WidgetWidth)
        self.text_edit.setTabStopDistance(40)
        self.text_edit.setAcceptRichText(True)

        # 1. 创建段落格式对象
        block_format = QTextBlockFormat()
        block_format.setAlignment(Qt.AlignCenter)  # 居中对齐
        block_format.setLeftMargin(20)  # 左缩进
        block_format.setLineHeight(200.0, QTextBlockFormat.ProportionalHeight.value)   # 行距150%

        # 2. 应用到当前段落
        cursor = self.text_edit.textCursor()
        cursor.setBlockFormat(block_format)

        # 4. 将控件设置为主窗口中心部件(必须,否则控件不显示)
        self.setCentralWidget(self.text_edit)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

(3)列表样式(有序 / 无序列表)

python 复制代码
import sys

from PySide6.QtWidgets import QApplication, QMainWindow, QTextEdit
from PySide6.QtGui import QTextCursor, QTextListFormat

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.text_edit = QTextEdit(self)
        self.setCentralWidget(self.text_edit)

        # 获取当前文本光标
        cursor = self.text_edit.textCursor()

        # 设置列表模式
        list_format = QTextListFormat()
        # list_format.setStyle(QTextListFormat.ListDecimal)  # 设置列表样式为有序数字列表,或者:
        list_format.setStyle(QTextListFormat.ListDisc)  # 设置列表样式为无序圆点列表
        cursor.createList(list_format)


if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

(4) 光标与选择操作

QTextCursor 是操作 QTextEdit 内容的核心工具,用于定位光标、选择文本、修改格式:

python 复制代码
import sys

from PySide6.QtWidgets import QApplication, QMainWindow, QTextEdit
from PySide6.QtGui import QTextCursor, QTextListFormat

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.text_edit = QTextEdit(self)
        self.setCentralWidget(self.text_edit)
        self.text_edit.setText("0123456789abcdefg")

        # 获取当前文本光标
        # 1. 获取当前光标
        cursor = self.text_edit.textCursor()

        # 2. 光标定位
        cursor.movePosition(QTextCursor.Start)  # 移到文本开头(End/NextLine/PreviousWord 等)
        cursor.setPosition(10)  # 移到第10个字符位置

        # 3. 选择文本(从位置5到位置15)
        cursor.setPosition(5)
        cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, 10)

        # 4. 判断是否有选中内容
        if cursor.hasSelection():
            selected_text = cursor.selectedText()  # 获取选中的文本
            print(f"选中内容:{selected_text}")

        # 5. 替换选中内容
        cursor.insertText("替换后的内容")


if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    sys.exit(app.exec())
3. 布局与显示配置
方法 说明 可选值
setLineWrapMode(mode) 自动换行模式 QTextEdit.NoWrap(不换行)、QTextEdit.WidgetWidth(按控件宽度)、QTextEdit.FixedPixelWidth(固定像素宽度)
setWordWrapMode(mode) 单词换行规则 QTextOption.WrapAnywhere(任意位置换行)、QTextOption.WrapAtWordBoundaryOrAnywhere(单词边界优先)
setReadOnly(bool) 只读模式(仅显示,不可编辑) True/False
setContentsMargins(left, top, right, bottom) 内容页边距 text_edit.setContentsMargins(10, 10, 10, 10)
setVerticalScrollBarPolicy(policy) 垂直滚动条策略 Qt.ScrollBarAlwaysOn/Qt.ScrollBarAsNeeded/Qt.ScrollBarAlwaysOff
4. 常用信号
信号 触发场景
textChanged() 文本内容发生任何变化(插入 / 删除 / 格式修改)
cursorPositionChanged() 光标位置移动或选择范围变更
selectionChanged() 选中的文本范围变更
editingFinished() 编辑完成(失去焦点 / 回车)
copyAvailable(bool) 可复制内容状态变化(True = 有可复制内容)
典型应用场景
1. 简单富文本编辑器
python 复制代码
import sys

from PySide6.QtGui import QFont
from PySide6.QtWidgets import QApplication, QMainWindow, QTextEdit


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.text_edit = QTextEdit(self)
        self.setCentralWidget(self.text_edit)

        # 获取当前文本光标
        # 1. 获取当前光标和字符格式
        self.cursor = self.text_edit.textCursor()
        self.char_format = self.cursor.charFormat()

        # 2. 设置字体加粗
        if not self.char_format.font().bold():
            self.char_format.setFontWeight(QFont.Bold)
            self.cursor.setCharFormat(self.char_format)
            self.text_edit.setTextCursor(self.cursor)
            print(self.char_format.font().bold())

        # 3. 设置斜体
        if not self.char_format.font().italic():
            self.char_format.setFontItalic(True)
            self.cursor.setCharFormat(self.char_format)
            self.text_edit.setTextCursor(self.cursor)
            print(self.char_format.font().italic())

        # 4. 设置下划线
        if not self.char_format.font().underline():
            self.char_format.setFontUnderline(True)
            self.cursor.setCharFormat(self.char_format)
            self.text_edit.setTextCursor(self.cursor)
            print(self.char_format.font().underline())



if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    sys.exit(app.exec())
2. 聊天消息框(只读 + 富文本展示)
python 复制代码
import sys

from PySide6.QtGui import QFont, QTextCursor
from PySide6.QtWidgets import QApplication, QMainWindow, QTextEdit


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.text_edit = QTextEdit(self)
        self.setCentralWidget(self.text_edit)

        # 获取当前文本光标
        # 1. 获取当前光标和字符格式
        self.cursor = self.text_edit.textCursor()
        self.char_format = self.cursor.charFormat()

# 示例:展示带头像和昵称的聊天消息
def add_chat_msg(nickname, content, avatar_path, text_edit):
    # 构造富文本消息
    html = f"""
           <div style="margin: 5px 0;">
               <img src="{avatar_path}" width="30" height="30" style="border-radius: 50%; vertical-align: middle;"/>
               <span style="font-weight: bold; margin: 0 5px;">{nickname}:</span>
               <span>{content}</span>
           </div>
       """
    text_edit.append(html)
    # 自动滚动到底部
    text_edit.moveCursor(QTextCursor.End)


if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()

    nickname = "拯救地球的怪兽"
    content = "你好,世界!"
    avatar_path = "avatar.png"
    text_edit = window.text_edit

    add_chat_msg(nickname, content, avatar_path, text_edit)

    window.show()
    sys.exit(app.exec())
3. 文本查找与替换
python 复制代码
from PySide6.QtGui import QTextDocument

# 查找文本
def find_text(text):
    # 从当前光标位置查找
    found = text_edit.find(text, QTextDocument.FindWholeWords)  # 匹配整词
    if not found:
        # 未找到则回到开头重新查找
        text_edit.moveCursor(QTextCursor.Start)
        found = text_edit.find(text)
    return found

# 替换选中的文本
def replace_text(old_text, new_text):
    if find_text(old_text):
        cursor = text_edit.textCursor()
        cursor.insertText(new_text)
4. 样式定制(StyleSheet)

通过 CSS 样式表自定义 QTextEdit 外观:

复制代码
text_edit.setStyleSheet("""
    QTextEdit {
        border: 1px solid #CCCCCC;  /* 边框 */
        border-radius: 6px;         /* 圆角 */
        padding: 8px;               /* 内边距 */
        background-color: #FFFFFF;  /* 背景色 */
        color: #333333;             /* 文本颜色 */
        font-size: 12px;
    }
    QTextEdit:focus {
        border-color: #0066CC;      /* 聚焦时边框变色 */
        outline: none;              /* 去除默认聚焦外框 */
    }
    QTextEdit:read-only {
        background-color: #F5F5F5;  /* 只读模式背景色 */
        color: #666666;
    }
""")

与 QPlainTextEdit 的区别

特性 QTextEdit QPlainTextEdit
核心定位 富文本编辑(支持 HTML、图片、格式) 纯文本编辑(轻量、高性能)
性能 大量纯文本时性能较低 适合大文本(如日志、代码)
格式支持 字符 / 段落 / 列表 / 图片 / 表格 仅基础文本(无富文本)
适用场景 富文本编辑器、聊天框、文档预览 代码编辑器、日志查看器

最佳实践

  1. 性能优化
    • 处理大文本(10 万 + 字符)时优先用 QPlainTextEdit
    • 批量修改文本时先调用 text_edit.blockSignals(True) 关闭信号,修改后恢复,避免频繁触发 textChanged
  2. 富文本兼容性
    • 自定义富文本时尽量使用标准 HTML 标签(<b>/<i>/<img> 等),避免兼容问题;
    • 读取富文本时优先用 toHtml(),写入时用 setHtml() 保证格式完整。
  3. 用户体验
    • 只读模式下设置 setCursor(Qt.IBeamCursor),保持光标样式一致;
    • 长文本场景添加 "自动滚动到底部" 选项,提升阅读体验。
  4. 资源管理

插入的图片若为本地文件,需保证路径有效;也可将图片嵌入 HTML(base64 编码)避 免路径依赖。

相关推荐
free-elcmacom8 小时前
机器学习高阶教程<4>因果机器学习:因果推断、可解释AI与科学发现的新革命
人工智能·python·机器学习·因果机器学习
smile_Iris8 小时前
Day 41 早停策略和模型权重的保存
开发语言·python
重生之我在番茄自学网安拯救世界8 小时前
网络安全中级阶段学习笔记(八):upload靶场实战(1-13关)-文件上传漏洞绕过1
笔记·学习·网络安全·文件上传漏洞·靶场实战
一过菜只因8 小时前
Git入门学习
git·学习
MediaTea8 小时前
Python:接口隔离原则(ISP)
开发语言·网络·python·接口隔离原则
承渊政道8 小时前
C++学习之旅【C++内存管理、模板初阶以及STL简介】
c++·学习·visual studio
遇印记8 小时前
java期末复习(构造方法和成员方法,重写和重载)
java·开发语言·学习
郝学胜-神的一滴8 小时前
使用Qt OpenGL开发俄罗斯方块:从零到一实现经典游戏
c++·qt·程序人生·游戏·设计模式·系统架构·图形渲染
破烂pan8 小时前
Elasticsearch 8.x + Python 官方客户端实战教程
python·elasticsearch