【Qt实战项目】记事本完整项目

效果图如下所示:
在这里插入图片描述
在这里插入图片描述
全部代码如下:
main.h

#include "notepad.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.showMaximized();
    return a.exec();
}

notepad.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <subtext.h>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

protected:
    void closeEvent(QCloseEvent *) override;

private:
    Ui::MainWindow *ui;

    void init();

private slots:
    // 文件
    void slot_newFile(bool);
    void slot_openFile(bool);
    void slot_saveFile(bool);
    void slot_saveAsFile(bool);

    // 编辑
    void slot_copy(bool);
    void slot_paste(bool);
    void slot_cut(bool);
    void slot_undo(bool);
    void slot_redo(bool);

    // 窗口
    void slot_closeFile(bool);
    void slot_closeAllFile(bool);
    void slot_tile(bool);
    void slot_cascade(bool);
    void slot_next(bool);
    void slot_former(bool);

    // 帮助
    void slot_about(bool);
    void slot_aboutQt(bool);

    subtext *getActiveChildForm();

private:
    QString codeName;
};
#endif // MAINWINDOW_H

notepad.cpp

#include "notepad.h"
#include "ui_notepad.h"
#include <QDebug>
#include <QMdiSubWindow>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QFont font;
    font.setBold(true);
    ui->actionnew->setFont(font);

    setWindowIcon(QIcon(":/pic/booknote.jpg"));

    // 初始化各种功能
    init();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::closeEvent(QCloseEvent *)
{
    ui->mdiArea->closeAllSubWindows();
    this->close();
}

void MainWindow::init()
{
    // 文件
    codeName = "UTF-8";
    connect(ui->actionnew,SIGNAL(triggered(bool)),this,SLOT(slot_newFile(bool)));
    connect(ui->actionOpen,SIGNAL(triggered(bool)),this,SLOT(slot_openFile(bool)));
    connect(ui->actionS2,&QAction::triggered,this,[=](){this->codeName = "UTF-8";});
    connect(ui->actionS1,&QAction::triggered,this,[=](){this->codeName = "GB18030";});
    connect(ui->actionSave,SIGNAL(triggered(bool)),this,SLOT(slot_saveFile(bool)));
    connect(ui->actionResave,SIGNAL(triggered(bool)),this,SLOT(slot_saveAsFile(bool)));
    connect(ui->actionExit,&QAction::triggered,[=](){
        ui->mdiArea->closeAllSubWindows();
        this->close();});

    // 编辑
    connect(ui->actionCopy,SIGNAL(triggered(bool)),this,SLOT(slot_copy(bool)));
    connect(ui->actionPaste,SIGNAL(triggered(bool)),this,SLOT(slot_paste(bool)));
    connect(ui->actionCut,SIGNAL(triggered(bool)),this,SLOT(slot_cut(bool)));
    connect(ui->actionRedo,SIGNAL(triggered(bool)),this,SLOT(slot_redo(bool)));
    connect(ui->actionUndo,SIGNAL(triggered(bool)),this,SLOT(slot_undo(bool)));


    // 窗口
    connect(ui->actionClose,SIGNAL(triggered(bool)),this,SLOT(slot_closeFile(bool)));
    connect(ui->actionCloseAll,SIGNAL(triggered(bool)),this,SLOT(slot_closeAllFile(bool)));
    connect(ui->actionTile,SIGNAL(triggered(bool)),this,SLOT(slot_tile(bool)));
    connect(ui->actionCascade,SIGNAL(triggered(bool)),this,SLOT(slot_cascade(bool)));
    connect(ui->actionNext,SIGNAL(triggered(bool)),this,SLOT(slot_next(bool)));
    connect(ui->actionFomer,SIGNAL(triggered(bool)),this,SLOT(slot_former(bool)));

    // 帮助
    connect(ui->actionAbout,SIGNAL(triggered(bool)),this,SLOT(slot_about(bool)));
    connect(ui->actionAboutQt,SIGNAL(triggered(bool)),this,SLOT(slot_aboutQt(bool)));


}

void MainWindow::slot_newFile(bool)
{
//    qDebug() << "新建文件";
    // 创建窗体
    // 如果subtext()里不传参则意味着子窗体没有父对象,是离开主窗体独立显示的,
    // 如果要在主窗口中显示多个窗体,则要使用MDI Area控件
    subtext * sub = new subtext();
    ui->mdiArea->addSubWindow(sub);
    sub->setCodeName(codeName);
    sub->newFile();
    sub->show();
}

void MainWindow::slot_openFile(bool)
{
    subtext * sub = new subtext();
    ui->mdiArea->addSubWindow(sub);
    sub->setCodeName(codeName);
    sub->openFile();
    sub->show();
}

void MainWindow::slot_saveFile(bool)
{
    QMdiSubWindow * subWin = ui->mdiArea->activeSubWindow();
    if(subWin == NULL)return;
    QWidget *win = subWin->widget();
    if(win == NULL)return;
    subtext *sub = (subtext *)win;
    if(sub == NULL)return;
    sub->saveFile();

}

void MainWindow::slot_saveAsFile(bool)
{
    QMdiSubWindow * subWin = ui->mdiArea->activeSubWindow();
    if(subWin == NULL)return;
    QWidget *win = subWin->widget();
    if(win == NULL)return;
    subtext *sub = (subtext *)win;
    if(sub == NULL)return;
    sub->saveAsFile();
}

void MainWindow::slot_copy(bool)
{
    subtext * sub = getActiveChildForm();
    if(sub != NULL){
        sub->copy();
    }
}

void MainWindow::slot_paste(bool)
{
    subtext * sub = getActiveChildForm();
    if(sub != NULL){
        sub->paste();
    }
}

void MainWindow::slot_cut(bool)
{
    subtext * sub = getActiveChildForm();
    if(sub != NULL){
        sub->cut();
    }
}

void MainWindow::slot_undo(bool)
{
    subtext * sub = getActiveChildForm();
    if(sub != NULL){
        sub->undo();
    }
}

void MainWindow::slot_redo(bool)
{
    subtext * sub = getActiveChildForm();
    if(sub != NULL){
        sub->redo();
    }
}

void MainWindow::slot_closeFile(bool)
{
    ui->mdiArea->closeActiveSubWindow();
}

void MainWindow::slot_closeAllFile(bool)
{
    ui->mdiArea->closeAllSubWindows();
}

void MainWindow::slot_tile(bool)
{
    ui->mdiArea->tileSubWindows();
}

void MainWindow::slot_cascade(bool)
{
    ui->mdiArea->cascadeSubWindows();
}

void MainWindow::slot_next(bool)
{
    ui->mdiArea->activateNextSubWindow();
}

void MainWindow::slot_former(bool)
{
    ui->mdiArea->activatePreviousSubWindow();
}

void MainWindow::slot_about(bool)
{
    QMessageBox::about(this,"关于作者","版权所有:***,2021年2月25日");
}

void MainWindow::slot_aboutQt(bool)
{
    QMessageBox::aboutQt(this,"关于Qt");
}

subtext *MainWindow::getActiveChildForm()
{
    subtext * sub = NULL;
    QMdiSubWindow *subwin = ui->mdiArea->activeSubWindow();
    if(subwin == NULL)return sub;
    QWidget *wid = subwin->widget();
    if(wid == NULL)return sub;
    sub = (subtext *)wid;
    return sub;
}


subtext.h

#ifndef SUBTEXT_H
#define SUBTEXT_H

#include <QWidget>
#include <QTextEdit>
#include <QFile>
#include <QCloseEvent>
#include <QContextMenuEvent>

class subtext : public QTextEdit
{
    Q_OBJECT
public:
    explicit subtext(QWidget *parent = nullptr); // 注意将QObject 转换成了QWidget

    void newFile(); // 窗体新建
    void openFile(); // 打开文件
    void setCodeName(const QString codeName); // 设置编码格式
    void saveFile(); // 保存文件
    void saveAsFile(); // 另存为文件

protected:
    void closeEvent(QCloseEvent *) override; // QCloseEvent 可以接受点击叉号的事件
    void contextMenuEvent(QContextMenuEvent *) override; // 重写右键菜单事件

private slots:
    void slot_contentChanged();

private:
    QString filename; // 文件名地址
    QFile *myFile;
    QString codeName; // 编码格式
    bool isEdit = false;

signals:

};

#endif // SUBTEXT_H

subtext.cpp

#include "subtext.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QTextStream> // 文本流 目的是便于修改文件内容
#include <QDebug>
#include <QMenu>

subtext::subtext(QWidget *parent) : QTextEdit(parent)
{
//    newFile();

    this->filename.clear(); // 清除字符串的内容并使其为空。
    myFile = new QFile(this);
}

void subtext::newFile()
{
    static int index = 1;
    QString str = QString("未命名文档[%1][*]").arg(index); // 使用中括号将*包括,隐藏*
    this->setWindowTitle(str);
    index++;

    // 处于编辑后启用“*”
    // document函数返回一个指向QTextDocument*的指针,该对象的信号含有contentschanged信号
    connect(this->document(),SIGNAL(contentsChanged()),this,SLOT(slot_contentChanged()));
}

void subtext::openFile()
{

    // 获取要打开的文本文件
    QString filename = QFileDialog::getOpenFileName(this,"获取文本文件",".",
                                                    "Text(*.cpp *.h *.txt)");
    // "."表示当前目录
    if(filename.isEmpty()){
        return;
    }

    // 把文件路径保存,文件设置到窗体
    this->filename = filename;

    // 第一种获取文件名方式
//    QStringList list = filename.split("/");
//    QString title = list.at(list.length()-1);

    // 第二种获取文件名方式
    QFileInfo info(filename);
    QString title = QString("%1[*]").arg(info.fileName());

    this->setWindowTitle(title);

    connect(this->document(),SIGNAL(contentsChanged()),this,SLOT(slot_contentChanged()));

    // 对文本进行操作(用流形式打开文件)
    myFile->setFileName(info.fileName());
    bool ret = myFile->open(QIODevice::ReadWrite|QIODevice::Text);

    if(!ret){
        QMessageBox::warning(this,"警告","打开文件失败");
        return;
    }

    QTextStream stream(myFile);
    stream.setCodec(this->codeName.toLocal8Bit().data());

    while(!stream.atEnd()){
        QString str = stream.readLine();
        this->append(str);
    }
    myFile->close();

}

void subtext::setCodeName(const QString codeName)
{
    this->codeName = codeName;
}

void subtext::saveFile()
{
    // 如果没有编辑则不尽行保存
    if(!isEdit){
        qDebug() << "未保存";
        return;
    }

    if(this->filename.isEmpty()){
        QString filename = QFileDialog::getSaveFileName(this,"保存文件",".","Text(*.cpp *.h *.txt)");
        if(filename.isEmpty()){
            return;
        }
        this->filename = filename;
    }

    // 对文件进行操作
    myFile->setFileName(this->filename);
    bool ret = myFile->open(QIODevice::WriteOnly|QIODevice::Text);

    if(!ret){
        QMessageBox::warning(this,"警告","文件打开失败");
        return;
    }

    QTextStream stream(myFile);
    stream.setCodec(this->codeName.toLocal8Bit().data());
    stream << this->toPlainText();
    stream.flush(); // 强制刷新
    this->setWindowModified(false);
    isEdit = false;
    myFile->close();
}

void subtext::saveAsFile()
{
    isEdit = true;
    filename.clear();
    saveFile();

}


void subtext::closeEvent(QCloseEvent *event)
{
    if(!isEdit){
        return;
    }

    QMessageBox::StandardButton ret = QMessageBox::information(this,"保存提示","是否保存",
                             QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,QMessageBox::Yes);

    if(ret == QMessageBox::Yes){
        saveFile();
        event->accept();
    }
    else if(ret == QMessageBox::No){
        event->accept();
    }
    else if(ret == QMessageBox::Cancel){
        event->ignore();
    }
}

void subtext::contextMenuEvent(QContextMenuEvent *e)
{
    QMenu *myMenu = new QMenu(this);
    QAction *redo =  myMenu->addAction(QIcon(":/pic/recall2.jpg"),"撤销",this,SLOT(redo()),QKeySequence::Redo);
    redo->setEnabled(this->document()->isRedoAvailable());

    QAction *undo = myMenu->addAction(QIcon(":/pic/undo.jpg"),"恢复",this,SLOT(undo()),QKeySequence::Undo);
    undo->setEnabled(this->document()->isUndoAvailable());

    myMenu->addSeparator();

    QAction * cut = myMenu->addAction(QIcon(":/pic/cut2.jpg"),"剪贴",this,SLOT(cut()),QKeySequence::Cut);
    cut->setEnabled(this->textCursor().hasSelection());

    QAction *copy = myMenu->addAction(QIcon(":/pic/copy.jpg"),"复制",this,SLOT(copy()),QKeySequence::Copy);
    copy->setEnabled(this->textCursor().hasSelection());

    myMenu->addAction(QIcon(":/pic/v.jpg"),"粘贴",this,SLOT(paste()),QKeySequence::Paste);

    myMenu->addSeparator();

    QAction * clear = myMenu->addAction(QIcon(":/pic/v.jpg"),"清除",this,SLOT(clear()),QKeySequence(tr("Ctrl+D")));
    clear->setEnabled(!this->document()->isEmpty());

    QAction * selectAll = myMenu->addAction(QIcon(":/pic/v.jpg"),"全选",this,SLOT(selectAll()),QKeySequence::SelectAll);
    selectAll->setEnabled(!this->document()->isEmpty());

    myMenu->exec(e->globalPos());
}


void subtext::slot_contentChanged()
{
    isEdit = true;
    this->setWindowModified(true);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值