Qt基础项目篇——Qt版Word字处理软件

一、核心功能

本软件为多文档型程序,界面是标准的 Windows 主从窗口

拥有:主菜单、工具栏、文档显示区 和 状态栏。

所要实现的东西,均在下图了。

开发该软件,主要分为下面三个阶段

1)界面设计开发

  • 多窗口 MDI 程序框架的建立
  • 菜单设计
  • 工具栏设计
  • 工具按钮
  • 状态栏的帮助提示文本
  • 多个文档子窗口的管理和控制

2)文本编辑功能实现

  • 建立、打开和保存
  • 剪切、复制和粘贴
  • 撤销和恢复

3)排版美化功能实现

  • 字体选择
  • 字形
  • 字号
  • 文字颜色
  • 文档段落标号和标号的添加
  • 段落对齐方式

二、界面设计与开发

新建项目,MyselfWord。

1. 建立 MDI 程序框架

1.1 多文档区域的创建

在头文件 “myword.h” 中添加 QMdiArea 类的声明和定义变量:

#ifndef MYWORD_H
#define MYWORD_H

#include <QMainWindow>

//申明
class QMdiArea;

class MyWord : public QMainWindow
{
    Q_OBJECT

public:
    MyWord(QWidget *parent = nullptr);
    ~MyWord();

private:
    //定义变量
    QMdiArea *mdiArea;
};
#endif // MYWORD_H

在 “myword.cpp” 的构造函数编写如下:

#include "myword.h"
#include <QtWidgets>

MyWord::MyWord(QWidget *parent)
    : QMainWindow(parent)
{
    mdiArea = new QMdiArea; // 创建一个新的QMdiArea实例
    mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); // 设置水平滚动条策略为根据需要显示
    mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); // 设置垂直滚动条策略为根据需要显示
    setCentralWidget(mdiArea); // 将QMdiArea设置为窗口的中心部件

    move(200,150);
    resize(800,500);

    setWindowTitle(tr("Myself Word"));
}

MyWord::~MyWord()
{
}

1.2 子窗口类的创建

        为了实现多文档操作和管理,需要向 QMdiArea 中添加子窗口。为了可以更好地操作子窗口,则必须实例化子窗口的中心部件。而子窗口的中心部件使用了 QTextEdit 类,所以要实现自己的类,它必须继承自 QTextEdit 类。

        添加新的类,具体如下:

在 “mychild.h” 中添加:

#ifndef MYCHILD_H
#define MYCHILD_H

#include <QWidget>
#include <QTextEdit>

class MyChild : public QTextEdit
{
    Q_OBJECT
public:
    MyChild();
    void newFile(); //新建操作
    QString userFriendlyCurrentFile();  //提取文件名
    QString currentFile() { return curFile; }   //返回当前文件路径
protected:
    void closeEvent(QCloseEvent *event);    //关闭事件
private slots:
    void documentWasModified(); //文档被更改时,窗口显示更改状态标识
private:
    QString strippedName(const QString &fullFileName);  //获取较短的绝对路径

    QString curFile;    //保存当前文件路径
    bool isUntitled;    //作为当前文件是否被保存到硬盘上的标识
};

#endif // MYCHILD_H

声明了许多函数和定义了几个变量。其实可以一边实现功能,一边添加需要的函数。现在先实现新建功能,首先声明函数 newFile()。

1.3 新建文件操作

(1)newFile() 设计思路

  • 设置窗口编号
  • 设置文件未被保存过 “isUntitiled = true;”
  • 保存文件路径,为 curFile 赋初值,用 strippedName 函数修改为绝对路径
  • 设置子窗口标题
  • 关联文档内容改变信号 contentsChanged() 到显示文档更改状态标志槽documentWasModified()。

(2)newFile() 实现

子窗口的初始化

在“mychild.cpp”文件中添加:

#include "mychild.h"
#include <QtWidgets>

MyChild::MyChild()
{
    setAttribute(Qt::WA_DeleteOnClose); //设置在子窗口关闭时销毁这个类的对象
    isUntitled = true;  //初始 isUntitled 为 true
}

newFile() 的实现


void MyChild::newFile()
{
    //设置窗口编号,因为编号会一直保存,所以需要使用静态变量
    static int sequenceNumber = 1;
    //新建的文档默认为命名
    isUntitled = true;
    //将当前文件命名为"文档+编号"的形式,编号先使用再1
    curFile = tr("文档 %1").arg(sequenceNumber++);
    //设置窗口标题,使用[*]可以在文档被更改后在文件名称后显示"*"号
    setWindowTitle(curFile + "[*]" + tr(" - Myself Word"));
    //文档更改时发送 contentsChanged()信号,执行 documentWasModified() 曹函数
    connect(document(),SIGNAL(contentsChanged()),this,SLOT(documentWasModified()));
}

这里在设置窗口标题时添加了“[*]”字符,它可以保证编辑器内容被更改后,在文档标题中显示“*”号。

(3)文件更改标记

下面是 documentWasModified() 槽函数的定义:

void MyChild::documentWasModified()
{   
    //根据文档的 isModified() 函数的返回值,判断编辑器内容是否被更改
    setWindowModified(document()->isModified());
}

编辑器内容是否被更改,可以使用 QTextDocument 类的 isModified() 函数得知。

设置文档子窗口标题

QString MyChild::userFriendlyCurrentFile()
{
    return strippedName(curFile);
}

strippedName 函数用于修改文件名为较短的绝对路径。接收一个完整的文件名(包括路径)作为参数(类型为 QString),然后返回这个文件名中的基本文件名部分(即去除路径后的文件名)。

QString MyChild::strippedName(const QString &fullFileName)
{
    return QFileInfo(fullFileName).fileName();
}

先不考虑关闭文档时的保存逻辑,在 closeEvent() 中无条件地接收关闭事件。

void MyChild::closeEvent(QCloseEvent *event)
{
    event->accept();
}

2. 菜单系统设计

MyselfWord 的菜单系统包括主菜单、菜单栏和子菜单三级。

在 “myword.h” 中声明以及系统动作和菜单的实现:

#ifndef MYWORD_H
#define MYWORD_H

#include <QMainWindow>

class QMdiArea;
class QAction;//
class QMenu;//

class MyWord : public QMainWindow
{
    Q_OBJECT

public:
    MyWord(QWidget *parent = nullptr);
    ~MyWord();

private:
    QMdiArea *mdiArea;
    void createActions();//
    void createMenus();//
};
#endif // MYWORD_H

2.1 文件 主菜单

需要包括:新建N,打开O,保存S,另存为A,打印P,打印预览,退出X。

在“myword.h”文件中,定义“文件”菜单指针,定义“文件”主菜单下各个功能项的 QAction

private:
    void createActions();
    void createMenus();
    QMdiArea *mdiArea;
    //菜单
    QMenu *fileMenu;
    
    //动作(Action)
    QAction *newAct;            //【文件】主菜单
    QAction *openAct;
    QAction *saveAct;
    QAction *saveAsAct;
    QAction *printAct;
    QAction *printPreviewAct;
    QAction *exitAct;

在“myword.cpp”文件中编写函数 createActions() 的代码

记得在 images目录下搞点菜单图标。

const QString rsrcPath = ":/images";
void MyWord::createActions()
{
    /*【文件】菜单动作集*/
    //&N 表示这个菜单项可以使用快捷键 Alt+N 来访问
    newAct = new QAction(QIcon(rsrcPath + "/filenew.png"), tr("新建(&N)"), this);
    newAct->setShortcuts(QKeySequence::New);        //设置了快捷键
    newAct->setToolTip("新建");                   //设置工具栏按钮的提示文本
    newAct->setStatusTip(tr("创建一个新文档"));     //设置状态栏提示文本
    //connect(newAct, SIGNAL(triggered()), this, SLOT(fileNew()));

    openAct = new QAction(QIcon(rsrcPath + "/fileopen.png"), tr("打开(&O)..."), this);
    openAct->setShortcuts(QKeySequence::Open);
    openAct->setToolTip("打开");
    openAct->setStatusTip(tr("打开已存在的文档"));
    //connect(openAct, SIGNAL(triggered()), this, SLOT(fileOpen()));

    saveAct = new QAction(QIcon(rsrcPath + "/filesave.png"), tr("保存(&S)"), this);
    saveAct->setShortcuts(QKeySequence::Save);
    saveAct->setToolTip("保存");
    saveAct->setStatusTip(tr("将当前文档存盘"));
    //connect(saveAct, SIGNAL(triggered()), this, SLOT(fileSave()));

    saveAsAct = new QAction(tr("另存为(&A)..."), this);
    saveAsAct->setShortcuts(QKeySequence::SaveAs);
    saveAsAct->setStatusTip(tr("以一个新名字保存文档"));
    //connect(saveAsAct, SIGNAL(triggered()), this, SLOT(fileSaveAs()));

    printAct = new QAction(QIcon(rsrcPath + "/fileprint.png"), tr("打印(&P)..."), this);
    printAct->setShortcuts(QKeySequence::Print);
    printAct->setToolTip("打印");
    printAct->setStatusTip(tr("打印文档"));
    //connect(printAct, SIGNAL(triggered()), this, SLOT(filePrint()));

    printPreviewAct = new QAction(tr("打印预览..."), this);
    printPreviewAct->setStatusTip(tr("预览打印效果"));
    //connect(printPreviewAct, SIGNAL(triggered()), this, SLOT(filePrintPreview()));

    exitAct = new QAction(tr("退出(&X)"), this);
    exitAct->setShortcuts(QKeySequence::Quit);
    exitAct->setStatusTip(tr("退出应用程序"));
    //connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
}

上面所写的槽函数,后面会一一实现。

然后再编写函数 createMenus() 的代码

void MyWord::createMenus()
{
    //【文件】主菜单
    fileMenu = menuBar()->addMenu(tr("文件(&F)"));
    fileMenu->addAction(newAct);
    fileMenu->addAction(openAct);
    fileMenu->addSeparator();   //分隔线
    fileMenu->addAction(saveAct);
    fileMenu->addAction(saveAsAct);
    fileMenu->addSeparator();   //分隔线
    fileMenu->addAction(printAct);
    fileMenu->addAction(printPreviewAct);
    fileMenu->addSeparator();   //分隔线
    fileMenu->addAction(exitAct);
}

记得别忘记在“myword.cpp”的构造函数中添加这里两个函数

    createActions();
    createMe
### 使用Qt开发文字编辑器或Word处理软件的实战项目教程 #### 创建基本的文字编辑界面 为了构建一个简单的文字编辑器,可以从创建基础用户界面开始。这涉及到使用`QTextEdit`组件来提供文本输入区域。 ```cpp text_edit = new QTextEdit(this); setCentralWidget(text_edit); ``` 上述代码片段展示了如何初始化并设置中心窗口部件为`QTextEdit`实例[^1]。此方法能够快速搭建起具备基本文本编辑能力的应用程序框架。 #### 添加文件操作功能 对于任何完整的文字处理器而言,支持打开、保存文档等功能至关重要。可以通过菜单栏添加这些选项,并连接到相应的槽函数实现具体逻辑: ```cpp // 假设已经定义好了ui指针指向UI对象 connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::openFile); connect(ui->actionSave, &QAction::triggered, this, &MainWindow::saveFile); void MainWindow::openFile() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open Text file"), "", tr("Text files (*.txt *.docx)")); if (!fileName.isEmpty()) { QFile file(fileName); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream in(&file); ui->textEdit->setText(in.readAll()); file.close(); } } } void MainWindow::saveFile() { QString fileName = QFileDialog::getSaveFileName(this, tr("Save Text File As..."), "", tr("Text Files (*.txt);;Document Files (*.docx)")); if (!fileName.isEmpty()) { QFile file(fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); out << ui->textEdit->toPlainText(); file.close(); } } } ``` 这段C++代码实现了两个重要的文件管理特性——加载现有文档以及将当前编辑的内容另存为新文件的功能。 #### 集成报告引擎提升应用价值 如果希望进一步增强应用程序的能力,则可以考虑集成第三方库如qtrpt作为报表生成功能的一部分。该工具允许开发者轻松地向其Qt应用程序中加入强大的打印和导出PDF等高级特性[^2]。 #### 完善编译配置 当完成主要编码工作之后,还需要确保项目的构建系统正确无误。例如,在基于CMake的环境中,应该适当调整`CMakeLists.txt`文件以包含必要的资源文件声明,如下所示: ```cmake qt_add_executable(${PROJECT_NAME} WIN32 MACOSX_BUNDLE main.cpp ... ) target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/ico.rc) ``` 这里特别注意最后一行语句的作用在于指定额外的源码位置给目标可执行文件[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值