用Qt6框架 实现一个简易的文本编辑器软件

首先分析需求,对于一个简单的文本编辑器,起码要实现以下功能和要求:
1. 主窗口菜单栏包括以下功能:新建文本文件、打开文本文件、保存文本文件、文本文件另存为、文本剪切、文本复制和文本粘贴;
2. 具有查找文本功能(通过主窗口菜单选择),设计一个对话框在正在编辑的文本中查找特定字符串;
3. 具有字体设置功能(通过主窗口菜单选择),弹出一个对话框让用户选择字体、尺寸、是否加粗、是否加下划线等字体设置,用户确认后应用到文本编辑区;

4. 当用户准备新建另一个编辑实例时,同时打开或者已保存的文件的内容存在变更时,提示用户是否保存更改。

说实话,这个玩意真心没有什么技术含量,主要就是考查对Qt的常用控件和实用类使用的熟练度、以及信号槽的处理。我来说一下要点:
创建菜单栏使用QMenuBar,打开/保存文件时弹出选择文件/路径对话框用QFileDialog实现,文本编辑区使用QTextEdit实现,复制粘贴和剪切直接调用QTextEdit的成员函数就好;

打开文件时用QTextStream从文件流读入文本字符串,写入文件时也是用它将字符串写入文件流,构造文件路径对象则采用QFile;

弹出查找文段和设置字体的对话框,可以直接采用Qt自带的QInputDialog和QFontDialog实现;

查找文段采用QTextDocument搜索,由于还要实现查找下一个功能,还需要记录当前查找的光标,用QTextCursor实现即可;

设置的字体选项采用QSettings进行持久化保存,下次打开程序时可以直接加载设置以设置默认字体;

记录文件是否变更,这个可以直接定义一个全局字符串变量,在每次文件打开和保存的时候用文本内容更新之,用户欲新建文本时,若当前文本和先前的不同,那么就说明更改了;

最后就是一堆信号槽的设置了,使用connect函数即可,第一个参数是信号发送者,第三个参数是信号接收者(一般为整个窗体的对象),这一点不要搞混淆了。

下面直接上代码,首先是源文件:

#include <QApplication>
#include <QtGui>
#include <QMenuBar>
#include <QFileDialog>
#include <QMessageBox>
#include <QInputDialog>
#include <QFontDialog>
#include <QTextCursor>
#include <QSettings>
#include <QScreen>
#include "QtTextEditor.h"

bool MainWindow::isTextChanged()
{
    QString currentText = textEdit1->toPlainText();
    return currentText != originalText;
}

void MainWindow::fileNew()
{
    if (!textEdit1->toPlainText().isEmpty()) {
        if (isTextChanged()) {
            QMessageBox::StandardButton reply = QMessageBox::question(nullptr,
                "Confirmation", "Do you want to save the changes of original text?", QMessageBox::Yes | QMessageBox::No);
            if (reply == QMessageBox::Yes) {
                fileSave();
            }
        }
    }
    textEdit1->clear();
}

void MainWindow::fileOpen()
{
    QFileDialog dialog(this, tr("Open File"));
    dialog.setFileMode(QFileDialog::ExistingFile);
    dialog.setNameFilter(tr("Text Files (*.txt);;All Files (*)"));
    dialog.setDirectory("");

    if (dialog.exec() == QDialog::Accepted) {
        QString fileName = dialog.selectedFiles().first();
        QFile file(fileName);
        if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            QTextStream in(&file);
            originalText = in.readAll();
            textEdit1->setPlainText(originalText);
            file.close();
            currentFile = fileName;
        }
        else {
            QMessageBox::warning(this, tr("Error"), tr("Could not open file."));
        }
    }
}


void MainWindow::fileSave()
{
    if (currentFile.isEmpty()) {
        fileSaveAs();
    } else {
        QFile file(currentFile);
        if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream out(&file);
            originalText = textEdit1->toPlainText();
            out << originalText;
            file.close();
        } else {
            QMessageBox::warning(this, tr("Error"), tr("Could not save file."));
        }
    }
}

void MainWindow::fileSaveAs()
{
    QFileDialog dialog(this, tr("Save File As"));
    dialog.setAcceptMode(QFileDialog::AcceptSave);
    dialog.setDefaultSuffix("txt");
    dialog.setFileMode(QFileDialog::AnyFile);
    dialog.setNameFilter(tr("Text Files (*.txt);;All Files (*)"));
    dialog.setDirectory("");

    if (dialog.exec() == QDialog::Accepted) {
        QString fileName = dialog.selectedFiles().first();
        currentFile = fileName;
        fileSave();
    }
}


void MainWindow::fileExit()
{
    this->close();
}

void MainWindow::editCut()
{
    textEdit1->cut();
}

void MainWindow::editCopy()
{
    textEdit1->copy();
}

void MainWindow::editPaste()
{
    textEdit1->paste();
}

void MainWindow::searchFind()
{
    QString searchString = QInputDialog::getText(this, tr("Find"), tr("Enter search string:"));
    if (!searchString.isEmpty()) {
        QTextCursor cursor = textEdit1->textCursor();
        QTextDocument* document = textEdit1->document();
        if (!cursor.isNull() && document) {
            QTextCursor searchCursor(document);
            while (!searchCursor.isNull() && !searchCursor.atEnd()) {
                searchCursor = document->find(searchString, searchCursor);
                if (!searchCursor.isNull()) {
                    if (searchCursor.hasSelection()) {
                        textEdit1->setTextCursor(searchCursor);
                        break;
                    }
                }
            }
            if (searchCursor.isNull() || searchCursor.atEnd()) {
                QMessageBox::information(this, tr("Find"), tr("No matching text found."));
            }
        }
    }
}

void MainWindow::searchFindNext()
{
    QString searchString = textEdit1->textCursor().selectedText();
    if (!searchString.isEmpty()) {
        QTextCursor cursor = textEdit1->textCursor();
        QTextDocument* document = textEdit1->document();
        if (!cursor.isNull() && document) {
            QTextCursor searchCursor = cursor;
            searchCursor.setPosition(cursor.position() + cursor.selectionStart());
            searchCursor = document->find(searchString, searchCursor);
            if (!searchCursor.isNull()) {
                textEdit1->setTextCursor(searchCursor);
            }
            else {
                QMessageBox::information(this, tr("Find"), tr("No more matching text found."));
            }
        }
    }
}

void MainWindow::formatFont()
{
    bool ok;
    QFont currentFont = textEdit1->currentFont();
    QFont font = QFontDialog::getFont(&ok, currentFont, this, tr("Select Font"));
    if (ok) {
        QSettings settings("Ernesto", "QtTextEditor");
        settings.setValue("font", font.toString());
        textEdit1->setFont(font);
    }
}

void MainWindow::loadFontSettings()
{
    QSettings settings("Ernesto", "QtTextEditor");
    QString fontString = settings.value("font").toString();

    if (!fontString.isEmpty()) {
        QFont font;
        font.fromString(fontString);
        textEdit1->setFont(font);
    }
}

MainWindow::MainWindow()
{
    fileMenu = this->menuBar()->addMenu(tr("&File"));
    fileNewAct = new QAction(tr("&New"), this);
    fileMenu->addAction(fileNewAct);
    fileOpenAct = new QAction(tr("&Open..."), this);
    fileMenu->addAction(fileOpenAct);
    fileSaveAct = new QAction(tr("&Save"), this);
    fileMenu->addAction(fileSaveAct);
    fileSaveAsAct = new QAction(tr("Save &As..."), this);
    fileMenu->addAction(fileSaveAsAct);
    fileExitAct = new QAction(tr("E&xit"), this);
    fileMenu->addAction(fileExitAct);

    editMenu = this->menuBar()->addMenu(tr("&Edit"));
    editCutAct = new QAction(tr("Cu&t"), this);
    editMenu->addAction(editCutAct);
    editCopyAct = new QAction(tr("&Copy"), this);
    editMenu->addAction(editCopyAct);
    editPasteAct = new QAction(tr("&Paste"), this);
    editMenu->addAction(editPasteAct);

    searchMenu = this->menuBar()->addMenu(tr("&Search"));
    searchFindAct = new QAction(tr("&Find..."), this);
    searchMenu->addAction(searchFindAct);
    searchFindNextAct = new QAction(tr("Find &Next"), this);
    searchMenu->addAction(searchFindNextAct);

    formatMenu = this->menuBar()->addMenu(tr("&Format"));
    formatFontAct = new QAction(tr("&Font..."), this);
    formatMenu->addAction(formatFontAct);

    textEdit1 = new QTextEdit;
    setCentralWidget(textEdit1);

    connect(fileNewAct, SIGNAL(triggered()), this, SLOT(fileNew()));
    connect(fileOpenAct, SIGNAL(triggered()), this, SLOT(fileOpen()));
    connect(fileSaveAct, SIGNAL(triggered()), this, SLOT(fileSave()));
    connect(fileSaveAsAct, SIGNAL(triggered()), this, SLOT(fileSaveAs()));
    connect(fileExitAct, SIGNAL(triggered()), this, SLOT(fileExit()));
    connect(editCutAct, SIGNAL(triggered()), this, SLOT(editCut()));
    connect(editCopyAct, SIGNAL(triggered()), this, SLOT(editCopy()));
    connect(editPasteAct, SIGNAL(triggered()), this, SLOT(editPaste()));
    connect(searchFindAct, SIGNAL(triggered()), this, SLOT(searchFind()));
    connect(searchFindNextAct, SIGNAL(triggered()), this, SLOT(searchFindNext()));
    connect(formatFontAct, SIGNAL(triggered()), this, SLOT(formatFont()));

    loadFontSettings();
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QCoreApplication::setOrganizationName("Ernesto");
    QCoreApplication::setApplicationName("QtTextEditor");

    MainWindow mainWin1;

    QScreen* screen = QGuiApplication::primaryScreen();
    int screenWidth = screen->geometry().width();
    int screenHeight = screen->geometry().height();
    int windowWidth = screenWidth / 2;
    int windowHeight = screenHeight / 2;
    int x = (screenWidth - windowWidth) / 2;
    int y = (screenHeight - windowHeight) / 2;

    mainWin1.setWindowTitle(QObject::tr("Text Editor Sample"));
    mainWin1.resize(windowWidth, windowHeight);
    mainWin1.move(x, y);
    mainWin1.show();

    return app.exec();
}

最后是头文件:

#include <QMainWindow>
#include <QMenu>
#include <QAction>
#include <QTextEdit>

class MainWindow : public QMainWindow
{
	Q_OBJECT

private slots:
	void fileNew();
	void fileOpen();
	void fileSave();
	void fileSaveAs();
	void fileExit();

	void editCut();
	void editCopy();
	void editPaste();

	void searchFind();
	void searchFindNext();

	void formatFont();

private:
	QString currentFile;
	QString originalText;

	QMenu *fileMenu;
	QAction *fileNewAct;
	QAction *fileOpenAct;
	QAction *fileSaveAct;
	QAction *fileSaveAsAct;
	QAction *fileExitAct;

	QMenu *editMenu;
	QAction *editCutAct;
	QAction *editCopyAct;
	QAction *editPasteAct;

	QMenu *searchMenu;
	QAction *searchFindAct;
	QAction *searchFindNextAct;

	QMenu *formatMenu;
	QAction *formatFontAct;

	QTextEdit *textEdit1;

	bool isTextChanged();
	void loadFontSettings();

public:
	MainWindow();
};

效果如图所示:

 

  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值