Qt5實現文本編輯器(附圖片轉PDF與詳細代碼)

1. 功能介紹

老規矩,我們直接上截圖

這是主界面
在這裡插入圖片描述
文件菜單界面
在這裡插入圖片描述

編輯菜單界面
在這裡插入圖片描述
設置菜單界面
在這裡插入圖片描述
關於菜單界面

在這裡插入圖片描述

2. 功能演示

設置字體顏色
在這裡插入圖片描述
在這裡插入圖片描述
設置字體大小

在這裡插入圖片描述
在這裡插入圖片描述
點擊關於菜單
在這裡插入圖片描述
點擊關於Qt菜單
在這裡插入圖片描述
會自動跳轉到Qt的官網

點擊圖片轉PDF
在這裡插入圖片描述
打開文件等對話框
在這裡插入圖片描述

3. 代碼

我們直接上代碼

aboutwidget.h

#ifndef ABOUTWIDGET_H
#define ABOUTWIDGET_H

#include <QWidget>

namespace Ui {
class AboutWidget;
}

class AboutWidget : public QWidget
{
    Q_OBJECT

public:
    explicit AboutWidget(QWidget *parent = nullptr);
    ~AboutWidget();

private:
    Ui::AboutWidget *ui;
};

#endif // ABOUTWIDGET_H

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFont>
#include <QColor>


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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




private slots:
    void on_actionexit_triggered();

    void on_actioncolor_triggered();

    void on_actionfont_triggered();

    void on_actionne_triggered();

    void on_actionopen_triggered();

    void on_actionsave_triggered();

    void on_actionasfile_triggered();

    void on_actioncut_triggered();

    void on_actioncopy_triggered();

    void on_actionundo_triggered();

    void on_actionredo_triggered();

    void on_actionpatse_triggered();

    void on_actionAbout_triggered();

    void on_actionAboutQT_triggered();

    void on_actionPDF_triggered();

private:
    Ui::MainWindow *ui;
    QFont font;
    QColor color;
    QString currentFile;
};
#endif // MAINWINDOW_H

topdf.h

#ifndef TOPDF_H
#define TOPDF_H

#include <QWidget>

namespace Ui {
class ToPdf;
}

class ToPdf : public QWidget
{
    Q_OBJECT

public:
    explicit ToPdf(QWidget *parent = nullptr);
    ~ToPdf();
    bool pictureToPDF(QString sourth,QString sDir);

private slots:
    void on_pictureBtn_clicked();

    void on_saveBtn_clicked();

    void on_startBtn_clicked();

private:
    Ui::ToPdf *ui;
};

#endif // TOPDF_H

aboutwidget.cpp

#include "aboutwidget.h"
#include "ui_aboutwidget.h"

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

    ui->Pixmap->setPixmap(QPixmap(":/dog.jpg").scaled(141,131,Qt::KeepAspectRatio));
}

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

main.cpp

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;

    w.show();
    return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFontDialog>
#include <QColorDialog>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QTextStream>
#include <QTextCodec>
#include <QDesktopServices>
#include "aboutwidget.h"
#include "topdf.h"
// #pragma execution_character_set("utf-8")
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);


    // 設置文本框為單工作區
    setCentralWidget(ui->textEdit);

    font = QFont("宋體",18,QFont::Normal,true);
    color = QColor(Qt::black);

    // 工具條,項目默認生成一個
    // 工具條上放的是菜單常用的菜單項
    // 所以工具條和菜單共用QAction,得通過代碼添加
    ui->toolBar->addAction(ui->actionne);
    ui->toolBar->addAction(ui->actionopen);
    ui->toolBar->addAction(ui->actionsave);
    ui->toolBar->addAction(ui->actionPDF);
    ui->toolBar->addAction(ui->actionundo);
    ui->toolBar->addAction(ui->actionredo);
    ui->toolBar->addAction(ui->actioncopy);
    ui->toolBar->addAction(ui->actionpatse);
    ui->toolBar->addAction(ui->actioncolor);
    ui->toolBar->addAction(ui->actionfont);
    ui->toolBar->addAction(ui->actioncut);
    ui->toolBar->addSeparator();
    ui->toolBar->addAction(ui->actionexit);




}

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


void MainWindow::on_actionexit_triggered()
{
    close();
}


void MainWindow::on_actioncolor_triggered()
{
    QColor c = QColorDialog::getColor(color,this,"顏色選擇框");
    if(c.isValid()){
        color = c;

        // 設置文本框的文本顏色
        // 1. 從光標開始新輸入的文本顏色被設置
        // 2. 鼠標選中的文本顏色設置
        ui->textEdit->setTextColor(c);
    }
}

void MainWindow::on_actionfont_triggered()
{
    bool ok; // 用戶字體對話框保存是否選擇了字體的結構

    // 第一個參數是判斷用戶是否選擇了字體,第二個是字體對話框的初始值
    QFont f = QFontDialog::getFont(&ok,font,this,"選擇文本框要設置的字體");

    if(ok){
        font = f;

        // 1. 從當前光標開始
        // 2. 鼠標選中的文本的字體
        ui->textEdit->setCurrentFont(f);
    }

}

void MainWindow::on_actionne_triggered()
{
    QMessageBox::warning(this,tr("Warning"),
    tr("創建新文件?"),
    QMessageBox::Yes | QMessageBox::Default,
    QMessageBox::No);

    currentFile.clear();
    ui->textEdit->setText(QString());

}

void MainWindow::on_actionopen_triggered()
{
    QString fileName = QFileDialog::getOpenFileName(this, "打開文件");
    QFile file(fileName);
    currentFile = fileName;
    if (!file.open(QIODevice::ReadOnly | QFile::Text)) {
        QMessageBox::warning(this, "警告", "無法打開文件: " + file.errorString());
        return;
     }
     setWindowTitle(fileName);
     QTextStream *in = new QTextStream(&file);
     in->setCodec("UTF-8");
     QString text = in->readAll();

     ui->textEdit->setText(text);
     delete in;
     file.close();
}

void MainWindow::on_actionsave_triggered()
{
    QString fileName;
    // 若沒有文件,重新創建一個
    if (currentFile.isEmpty()) {
        fileName = QFileDialog::getSaveFileName(this, "Save");
        currentFile = fileName;
    } else {
        fileName = currentFile;
    }

    // 打開文件
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QFile::Text)) {
        QMessageBox::warning(this, "警告", "無法打開文件: " + file.errorString());
        return;
    }
    setWindowTitle(fileName);
    QTextStream out(&file);

    out.setCodec("UTF-8");

    QString text = ui->textEdit->toPlainText();
    out << text;
    file.close();

}

void MainWindow::on_actionasfile_triggered()
{
    QString fileName = QFileDialog::getSaveFileName(this, "另存為");
    QFile file(fileName);

    if (!file.open(QFile::WriteOnly | QFile::Text)) {
        QMessageBox::warning(this, "警告", "無法打開文件: " + file.errorString());
        return;
    }
    currentFile = fileName;
    setWindowTitle(fileName);
    QTextStream out(&file);
    QString text = ui->textEdit->toPlainText();
    out << text;
    file.close();

}

void MainWindow::on_actioncut_triggered()
{
    ui->textEdit->cut();
}

void MainWindow::on_actioncopy_triggered()
{
    ui->textEdit->copy();
}


void MainWindow::on_actionundo_triggered()
{
    ui->textEdit->undo();
}

void MainWindow::on_actionredo_triggered()
{
    ui->textEdit->redo();
}

void MainWindow::on_actionpatse_triggered()
{
    ui->textEdit->paste();
}

void MainWindow::on_actionAbout_triggered()
{
    static AboutWidget about;
    about.show();
}

void MainWindow::on_actionAboutQT_triggered()
{
    QDesktopServices::openUrl(QUrl(QLatin1String("//www.qt.io/zh-cn/")));
}

void MainWindow::on_actionPDF_triggered()
{
    static ToPdf pdf;
    pdf.show();
}

topdf.cpp

#include "topdf.h"
#include "ui_topdf.h"

#include <QFileDialog>
#include <QMessageBox>
#include <QPainter>
#include <QtPrintSupport/QPrinter>
ToPdf::ToPdf(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ToPdf)
{
    ui->setupUi(this);
}

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

bool ToPdf::pictureToPDF(QString sourth, QString sDir)
{

    try
    {
        QPixmap pixmap(sourth);
        //圖片生成pdf
        QPrinter printerPixmap(QPrinter::HighResolution);
        printerPixmap.setPageSize(QPrinter::Custom);  //設置紙張大小為A4
        printerPixmap.setOutputFormat(QPrinter::PdfFormat);  //設置輸出格式為pdf
        printerPixmap.setOutputFileName(sDir);   //設置輸出路徑

        double dHeight = 300;
        double dWidth = (double)pixmap.width() / (double)pixmap.height() * dHeight;
        printerPixmap.setPageSizeMM(QSize(dWidth, dHeight));
        printerPixmap.setPageMargins(0, 0, 0, 0, QPrinter::DevicePixel);

        QPainter painterPixmap;
        painterPixmap.begin(&printerPixmap);
        QRect rect = painterPixmap.viewport();
        float multiple = (double(rect.width()) / pixmap.width());
        float yMultiple = (double(rect.height()) / pixmap.height());
        float fMin = (multiple < yMultiple) ? multiple : yMultiple;
        painterPixmap.scale(fMin, fMin); //將圖像(所有要畫的東西)在pdf上放大multiple-1倍
        painterPixmap.drawPixmap(0, 0, pixmap.width(), pixmap.height(), pixmap);  //畫圖
        painterPixmap.end();

        return true;
    }
    catch (...)
    {
        return false;
    }


}

void ToPdf::on_pictureBtn_clicked()
{
    //定義文件對話框類
    QFileDialog *fileDialog = new QFileDialog(this);
    //定義文件對話框標題
    fileDialog->setWindowTitle(tr("選擇圖片"));

    //設置默認文件路徑
    //fileDialog->setDirectory(".");

    //設置文件過濾器
    fileDialog->setNameFilter(tr("Images(*.png *.jpg *.jpeg *.bmp)"));
    //設置可以選擇多個文件,默認為只能選擇一個文件QFileDialog::ExistingFiles
    //fileDialog->setFileMode(QFileDialog::ExistingFiles);
    //設置視圖模式
    fileDialog->setViewMode(QFileDialog::Detail);
    //打印所有選擇的文件的路徑

    // 獲取選擇的文件名
    QStringList fileNameList;

    // exec()模態對話框
    if(fileDialog->exec()){

        fileNameList = fileDialog->selectedFiles();
    }
    ui->pictureFileName->setText(fileNameList[0]);
    //emit fileName(fileNameList);
}

void ToPdf::on_saveBtn_clicked()
{
    //定義文件對話框類
    QFileDialog *fileDialog = new QFileDialog(this);
    //定義文件對話框標題
    fileDialog->setWindowTitle(tr("選擇PDF"));
    fileDialog->setViewMode(QFileDialog::Detail);
    //打印所有選擇的文件的路徑

    //設置文件過濾器
    fileDialog->setNameFilter(tr("*.pdf"));
    // 獲取選擇的文件名
    QStringList fileNameList;

    // exec()模態對話框
    if(fileDialog->exec()){

        fileNameList = fileDialog->selectedFiles();
    }

    ui->saveFileName->setText(fileNameList[0]);

}

void ToPdf::on_startBtn_clicked()
{
    QString picture = ui->pictureFileName->text();
    QString pdf = ui->pictureFileName->text();

    if(pictureToPDF(picture,pdf)){
        QMessageBox::information(this,"轉換成功","轉換成功!!!");
    }else{
        QMessageBox::information(this,"轉換失敗","轉換失敗!");

    }
}

4. 改進

如果您發現我的代碼有些什麼不足之處,請私信或者評論區告訴我,我會及時改正,轉載請註明出處

有許多改進的地方

  • 首先是圖片轉PDF這塊,需要選中一個pdf文件,而不是選中目錄
  • 然後可以寫一個PDF轉圖片,加一些小功能,水印什麼的
  • 然後可以開始兼容doc,docx文件,實現一個小小的wps
  • 然後程序里沒有用到多線程,有些時候會卡頓,有些地方沒有異常處理,會造成閃退

總之,如果你真想用這個軟件來編輯文本,那還是很難受的,不好用,但是作為練手的項目來說,還不錯
最後,如果我以後有時間的話,會對這個項目進行改進,到時候會分享到博客當中,所以好奇的小夥伴可以點個關注哈哈哈

然後,準備去查漏補缺C++的一些基礎知識了,到時候也會寫成博客分享給大家