文本编辑器

一、QTextDocument 与框架(Frame)

  • QTextDocumentQTextEdit 的文档对象,存储所有文本与结构。
  • QTextFrame:文档中的“框架容器”,可以包含文本、表格、图片等。
  • 根框架通过 doc->rootFrame() 获取。

示例:设置根框架边框

QTextFrame * root_frame = doc->rootFrame();
QTextFrameFormat format;
format.setBorderBrush(Qt::blue);  // 边框颜色
format.setBorder(3);              // 边框宽度
root_frame->setFrameFormat(format);

插入子框架

QTextFrameFormat frameFormat;
frameFormat.setBackground(Qt::lightGray);
frameFormat.setMargin(10);
frameFormat.setPadding(5);
frameFormat.setBorder(2);
frameFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Dashed);

QTextCursor cursor = ui->textEdit->textCursor();
cursor.insertFrame(frameFormat);

二、文本块(Block)

  • QTextBlock:代表文档中的一个段落。
  • 遍历所有文本块:
QTextBlock block = document->firstBlock();
for(int i = 0; i < document->blockCount(); ++i){
    qDebug() << "文本块" << i 
             << "首行行号" << block.firstLineNumber() 
             << "长度" << block.length() 
             << "内容" << block.text();
    block = block.next();
}

三、字体与字符格式

  • 通过 QTextBlockFormat 设置段落属性(对齐方式等)。
  • 通过 QTextCharFormat 设置文字样式(颜色、字体、下划线等)。

示例:设置字体

QTextCursor cursor = ui->textEdit->textCursor();

// 设置居中段落
QTextBlockFormat blockFormat;
blockFormat.setAlignment(Qt::AlignCenter);
cursor.insertBlock(blockFormat);

// 设置字符样式
QTextCharFormat charFormat;
charFormat.setBackground(Qt::lightGray);
charFormat.setForeground(Qt::blue);
charFormat.setFont(QFont("宋体", 12, QFont::Bold, true));
charFormat.setFontUnderline(true);

cursor.setCharFormat(charFormat);
cursor.insertText("插入字体");

四、表格、列表、图片

1. 插入表格

QTextTableFormat format;
format.setCellSpacing(2);   // 单元格间距
format.setCellPadding(10);  // 单元格内边距
cursor.insertTable(2, 2, format); // 插入 2x2 表格

2. 插入有序列表

QTextListFormat format;
format.setStyle(QTextListFormat::ListDecimal); // 数字编号
ui->textEdit->textCursor().insertList(format);

3. 插入图片

QTextImageFormat format;
format.setName("C:/Users/lyx/Pictures/shuita.jpg"); // 图片路径
ui->textEdit->textCursor().insertImage(format);

⚠️ 注意::xxx 表示 Qt 资源文件,C:/xxx 才是本地路径。


五、查找功能

  • 创建查找对话框:
findDialog = new QDialog(this);
lineEdit = new QLineEdit(findDialog);
QPushButton * btn = new QPushButton("查找下一个", findDialog);
connect(btn, &QPushButton::clicked, this, &MainWindow::findNext);

QVBoxLayout * layout = new QVBoxLayout();
layout->addWidget(lineEdit);
layout->addWidget(btn);
findDialog->setLayout(layout);
  • 查找文本:
QString string = lineEdit->text();
bool isFind = ui->textEdit->find(string, QTextDocument::FindBackward);
if(isFind) {
    qDebug() << "行号:" << ui->textEdit->textCursor().blockNumber()
             << "列号:" << ui->textEdit->textCursor().columnNumber();
}

六、工具栏动作(QAction)

通过 QAction 把功能按钮添加到 QToolBar

QAction * action_textBlock = new QAction("文本块", this);
connect(action_textBlock, &QAction::triggered, this, &MainWindow::showTextBlock);
ui->toolBar->addAction(action_textBlock);
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTextDocument>
#include <QTextFrame>
#include <QTextFrameFormat>
#include <QTextBlockFormat>
#include <QTextCursor>
#include <QAction>
#include <QDebug>
#include <QTextCharFormat>
#include <QTextTableFormat>
#include <QTextImageFormat>
#include <QTextListFormat>
#include <QPushButton>
#include <QVBoxLayout>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this); // 初始化 UI 界面

    // 获取 QTextEdit 的文档对象
    QTextDocument * doc = ui->textEdit->document();
    QTextFrame * root_frame = doc->rootFrame(); // 文档的根框架

    // 设置根框架的边框样式
    QTextFrameFormat format;
    format.setBorderBrush(Qt::blue);  // 边框颜色
    format.setBorder(3);              // 边框宽度
    root_frame->setFrameFormat(format);

    // 创建一个子框架的格式
    QTextFrameFormat frameFormat;
    frameFormat.setBackground(Qt::lightGray);              // 背景色
    frameFormat.setMargin(10);                             // 外边距
    frameFormat.setPadding(5);                             // 内边距
    frameFormat.setBorder(2);                              // 边框宽度
    frameFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Dashed); // 虚线边框

    // 在光标位置插入新框架
    QTextCursor cursor = ui->textEdit->textCursor();
    cursor.insertFrame(frameFormat);

    // 向框架中插入文字
    ui->textEdit->insertPlainText("inner text!\n");
    ui->textEdit->insertPlainText("Hello inner text !\n");

    // 工具栏动作:显示框架结构
    QAction * action_frame = new QAction("Frame", this);
    connect(action_frame, &QAction::triggered, this, &MainWindow::showTextFrame);
    ui->toolBar->addAction(action_frame);

    // 工具栏动作:显示文档的文本块
    QAction * action_textBlock = new QAction(tr("文本块"), this);
    connect(action_textBlock, &QAction::triggered, this, &MainWindow::showTextBlock);
    ui->toolBar->addAction(action_textBlock);

    // 工具栏动作:设置字体(可切换)
    QAction * action_font = new QAction(tr("字体"), this);
    action_font->setCheckable(true); // 允许勾选
    connect(action_font, &QAction::toggled, this, &MainWindow::setTextFont);
    ui->toolBar->addAction(action_font);

    // 工具栏动作:插入表格
    QAction * action_textTable = new QAction(tr("表格"), this);
    connect(action_textTable, &QAction::triggered, this, &MainWindow::insertTable);
    ui->toolBar->addAction(action_textTable);

    // 工具栏动作:插入列表
    QAction * action_textList = new QAction(tr("列表"), this);
    connect(action_textList, &QAction::triggered, this, &MainWindow::insertList);
    ui->toolBar->addAction(action_textList);

    // 工具栏动作:插入图片
    QAction * action_textImage = new QAction(tr("图片"), this);
    connect(action_textImage, &QAction::triggered, this, &MainWindow::insertImage);
    ui->toolBar->addAction(action_textImage);

    // 工具栏动作:查找功能
    QAction * action_textFind = new QAction(tr("查找"), this);
    connect(action_textFind, &QAction::triggered, this, &MainWindow::textFind);
    ui->toolBar->addAction(action_textFind);

    // 查找对话框
    findDialog = new QDialog(this);
    lineEdit = new QLineEdit(findDialog);   // 输入查找内容的行编辑框
    QPushButton * btn = new QPushButton(findDialog);
    btn->setText(tr("查找下一个"));
    connect(btn, &QPushButton::clicked, this, &MainWindow::findNext);

    // 设置查找对话框布局
    QVBoxLayout * layout = new QVBoxLayout();
    layout->addWidget(lineEdit);
    layout->addWidget(btn);
    findDialog->setLayout(layout);
}

MainWindow::~MainWindow()
{
    delete ui; // 释放 UI
}

// 遍历根框架,输出其中的子框架和文本块
void MainWindow::showTextFrame()
{
    auto doc = ui->textEdit->document();
    auto rootFrame = doc->rootFrame();
    for(auto iter = rootFrame->begin(); iter != rootFrame->end(); iter++){
        auto cur_frame = iter.currentFrame();  // 当前是否是 frame
        auto cur_block = iter.currentBlock();  // 当前是否是 block
        if(cur_frame){
            qDebug() << "cur node is frame";  // 节点是框架
        } else if (cur_block.isValid()){
            qDebug() << "cur node is text block, text is " << cur_block.text(); // 节点是文本块
        }
    }
}

// 遍历所有文本块,输出内容与属性
void MainWindow::showTextBlock()
{
    QTextDocument * document = ui->textEdit->document();
    QTextBlock block = document->firstBlock();
    for(int i = 0; i < document->blockCount(); ++i){
        qDebug() << tr("文本块%1, 文本块首行行号%2, 长度%3, 内容%4 ")
                        .arg(i)                       // 文本块编号
                        .arg(block.firstLineNumber()) // 首行行号
                        .arg(block.length())          // 文本块长度
                        .arg(block.text());           // 文本内容
        block = block.next();
    }
}

// 设置字体样式
void MainWindow::setTextFont(bool checked)
{
    QTextCursor cursor = ui->textEdit->textCursor();
    if(checked){
        // 插入居中文本块
        QTextBlockFormat blockFormat;
        blockFormat.setAlignment(Qt::AlignCenter);
        cursor.insertBlock(blockFormat);

        // 设置字符格式
        QTextCharFormat charFormat;
        charFormat.setBackground(Qt::lightGray);                 // 背景色
        charFormat.setForeground(Qt::blue);                      // 前景色
        charFormat.setFont(QFont(tr("宋体"), 12, QFont::Bold, true)); // 字体设置:宋体 12号 粗体 斜体
        charFormat.setFontUnderline(true);                       // 下划线
        cursor.setCharFormat(charFormat);

        cursor.insertText(tr("插入字体")); // 插入文字
    } else {
        // 恢复左对齐、默认字体
        QTextBlockFormat blockFormat;
        blockFormat.setAlignment(Qt::AlignLeft);
        cursor.insertBlock(blockFormat);
        QTextCharFormat charFormat;
        cursor.setCharFormat(charFormat);
        cursor.insertText(tr("微软雅黑"));
    }
}

// 插入表格
void MainWindow::insertTable()
{
    QTextCursor cursor = ui->textEdit->textCursor();
    QTextTableFormat format;
    format.setCellSpacing(2);   // 单元格间距
    format.setCellPadding(10);  // 单元格内边距
    cursor.insertTable(2, 2, format); // 插入 2x2 表格
}

// 插入图片
void MainWindow::insertImage()
{
    QTextImageFormat format;
    // 注意:这里路径写法有误,:/ 开头是资源文件,C:/ 开头是本地路径
    format.setName(":/C:/Users/lyx/Pictures/shuita.jpg");
    ui->textEdit->textCursor().insertImage(format);
}

// 插入有序列表
void MainWindow::insertList()
{
    QTextListFormat format;
    format.setStyle(QTextListFormat::ListDecimal); // 数字编号列表
    ui->textEdit->textCursor().insertList(format);
}

// 显示查找对话框
void MainWindow::textFind()
{
    findDialog->show();
}

// 查找下一个匹配项
void MainWindow::findNext()
{
    QString string = lineEdit->text();
    // 向后查找
    bool isFind = ui->textEdit->find(string, QTextDocument::FindBackward);
    if(isFind) {
        qDebug() << tr("行号:%1 列号:%2")
                        .arg(ui->textEdit->textCursor().blockNumber()) // 当前光标行号
                        .arg(ui->textEdit->textCursor().columnNumber()); // 当前光标列号
    }
}


posted @ 2025-08-17 19:34  xiaoluosibky  阅读(51)  评论(0)    收藏  举报