QT文本编辑器(QMainwindow版)超详细

背景:

昨天一天都在编写QT文本编辑器程序,编写的过程中发现了很多问题,但是在编写的时候都比较难以实现,在网上搜索的消息也比较零散。这里总结一下QT文本编辑器的思路以及一些编写过程。

思路:

文本编辑器编写思路:

文本编辑器首先是基于一个QMainWindow的框架,个框架的主题结构是

菜单栏(Menu Bar)、工具栏(Toolbars)、停靠窗口(Dock Widgets)、状态栏(Status Bar)和中央窗口(Central Widget)

这五个窗口共同组成窗口,其中停靠窗口不能算是QMianWindow里面的窗口,但是剩下的四个窗口都是一些主窗口的组成部分,在主窗口中直接加入就可以了。

对于一个QT程序的思路:

首先要找到他们的构成部件,这里就是这些窗口的部件以及组成他们的一些控件。可以把这些组成部分写进private成员函数里面。对于一些不常用的空间就可以直接在写cpp文件的时候new出来就可以了,不用在private成员里面写指针。

另外一个就是要写好他们的槽函数,对于一个按钮,又或者是动作的实现(跟按钮差不多),都应该要写一个对应的槽函数。或者事件机制,就可以直接有一个对应的事件类来激发他。这里槽函数可以先列出来,然后再到我们的cpp文件里面去实现他。

最后就是对应的别的界面的实现,在除了主要界面的实现,还要写一些对应链接的实现或者是其他窗口的实现。

界面实现效果:

 

 

 

 

废话不多说!(注意:图片的路径记得改一下哦~

上代码:

aboutwidget.h(插入界面):

#ifndef ABOUTWIDGET_H
#define ABOUTWIDGET_H

#include <QWidget>
#include <QLabel>
namespace Ui {
class AboutWidget;
}

class AboutWidget : public QWidget
{
    Q_OBJECT

public:
    explicit AboutWidget(QWidget *parent = nullptr);
     void resizeEvent(QResizeEvent *event);
    ~AboutWidget();

private:
    QLabel *a;
    QPixmap *Pixmap;
    Ui::AboutWidget *ui;


};

#endif // ABOUTWIDGET_H

aboutwidget.cpp(插入界面):

#include "aboutwidget.h"
#include "ui_aboutwidget.h"
#include <QPixmap>
#include <QLabel>
#include <QResizeEvent>
AboutWidget::AboutWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::AboutWidget)
{
    ui->setupUi(this);
    setWindowTitle("about you!");
    a=new QLabel(this);
    a->setPixmap(QPixmap("./release/imageformats/12.jpg"));
    a->setScaledContents(true);
}
void AboutWidget::resizeEvent(QResizeEvent *event)
{
    this->resize(500,850);
    a->resize(this->size());
}
AboutWidget::~AboutWidget()
{
    delete ui;
}

mainwindow.h(主界面):

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QLabel>
#include <QDockWidget>
#include <QListWidget>
#include <QTextEdit>
#include <QFileDialog>
#include <QFontDialog>
#include <QColorDialog>//这些对话框可以实现较为基础的选择选项
#include <QFile>
#include <QTextCodec>
#include <QMessageBox>
#include <QTextStream>
#include <QDesktopServices>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    QString saveCurrentData(QString path);
    void setCurrentFileName(const QString &fileName);
   QString showFileDialog(QFileDialog::AcceptMode mode);
    MainWindow(QWidget *parent = nullptr);
    //  设置光标的选区,使格式作用于选区内的字符
    void mergeFormat(QTextCharFormat fmt);

    ~MainWindow();

private:
    QString m_fileName;
    QTextEdit *textEdit;
    QListWidget *textList;//铆接部分文本区域
    QMenuBar *menuBar;//菜单栏
    QToolBar *toolBar;//工具栏
    Ui::MainWindow *ui;
    QFont font;
    QColor color;
public slots:
    void on_actionexit_triggered();//退出操作

    void on_actionopenfile_triggered();//打开文件操作

    void on_ServeFile_triggered();//保存文件操作

    void on_actionne_triggered();//创建新文件操作

    void on_actionundo_triggered();//撤回操作

    void on_actionredo_triggered();//恢复文件

    void on_actioncut_triggered();//剪切文件

    void on_actioncopy_triggered();//复制文件

    void on_actionpatse_triggered();//粘贴文件

    void on_actionTextUnderLine_triggered();

    void on_actionTextItalic_triggered();

    void on_actionTextBold_triggered();

    //对齐
    void on_actionLift_triggered();

    void on_actionCenter_triggered();

    void on_actionRight_triggered();

    void on_actioncolor_triggered();//颜色操作

    void on_actionfont_triggered();

    void on_kidding();

    void on_about();

};
#endif // MAINWINDOW_H

mainwindow.cpp(主界面):

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "aboutwidget.h"
#include <QToolBar>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
/**************************************************菜单栏**********************************/
    this->setWindowTitle("myWindow");//设置窗口标题

    this->resize(1100,700);//重设窗口大小

    //创建菜单栏
    menuBar = new QMenuBar(this);

    //添加菜单栏到主窗口中
    this->setMenuBar(menuBar);

    QMenu *menu1 = new QMenu("文件",this);
    QMenu *menu2 = new QMenu("编辑",this);
    QMenu *menu3 = new QMenu("样式",this);
    QMenu *menu7 = new QMenu("这个键你点不了",this);
    QMenu *menu8 = new QMenu("帮助",this);
    //添加多个菜单到菜单栏

    menuBar->addMenu(menu1);
    menuBar->addMenu(menu2);
    menuBar->addMenu(menu3);
    menuBar->addMenu(menu7);
    menuBar->addMenu(menu8);

    QAction *action1 = new QAction(QIcon("./release/imageformats/1.png"),"新建文件或项目",this);//有图标
    QAction *action2 = new QAction(QIcon("./release/imageformats/2.png"),"打开文件或项目",this);//有图标
    QAction *action3 = new QAction("退出",this);
    QAction *action15 = new QAction("复制",this);//复制动作
    QAction *action16 = new QAction("粘贴",this);//粘贴动作
     QAction *action17 = new QAction("撤销",this);//撤销动作
      QAction *action18 = new QAction("恢复",this);//恢复动作
      QAction *action19 =new QAction("字体",this);//字体
     QAction *action20 =new QAction("颜色",this);//颜色
     QAction *action21 =new QAction("about",this);//帮助
     QAction *action22 =new QAction("about you!",this);//搞怪

    menu1->addAction(action1);
    menu1->addAction(action2);//菜单添加标签

    menu1->addSeparator();//插入分割线

    QMenu *menu9 = new QMenu("最近访问的文件",this);
    menu1->addMenu(menu9);//添加二级菜单

    menu2->addAction(action15);
    menu2->addAction(action16);
    menu2->addAction(action17);
    menu2->addAction(action18);

    menu3->addAction(action19);
    menu3->addAction(action20);

    menu9->addAction(new QAction("暂无最近打开项目",this));//二级菜单添加菜单项
    menu1->addAction(action3);

    menu7->addAction(action22);

     menu8->addAction(action21);

    action1->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N));//快捷键ctrl+N
    action2->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_O));//快捷键ctrl+O

    connect(action1, SIGNAL(triggered(bool)), this, SLOT(on_actionne_triggered()));//创建文件连接信号槽
    connect(action2, SIGNAL(triggered(bool)), this, SLOT(on_actionopenfile_triggered()));//打开文件连接信号槽
    connect(action3, SIGNAL(triggered(bool)), this, SLOT(on_actionexit_triggered()));
    connect(action19, SIGNAL(triggered(bool)), this, SLOT(on_actionfont_triggered()));
    connect(action20, SIGNAL(triggered(bool)), this, SLOT(on_actioncolor_triggered()));
    connect(action21, SIGNAL(triggered(bool)), this, SLOT(on_about()));
    connect(action22, SIGNAL(triggered(bool)), this, SLOT(on_kidding()));
/************************************工具栏********************************************/
    //创建工具栏
    toolBar = new QToolBar(this);
    //主窗口添加工具栏
    this->addToolBar(Qt::TopToolBarArea,toolBar);//设置工具栏默认停靠在左边

    toolBar->setFloatable(false);//设置不允许浮动
    toolBar->setMovable(false);//设置不允许移动
    toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);//设置工具项为图片在文字上方

    QString str[20]={tr("./release/imageformats/1.png"),tr("./release/imageformats/2.png"),tr("./release/imageformats/3.png"),
                     tr("./release/imageformats/11.png"),tr("./release/imageformats/4.png"),tr("./release/imageformats/5.png"),
                  tr("./release/imageformats/6.png"),tr("./release/imageformats/7.png"),tr("./release/imageformats/8.png"),
                     tr("./release/imageformats/9.png"),tr("./release/imageformats/10.png")};

    //创建工具项
    QAction *action4 = new QAction(QIcon(str[0]),"文件",this);
    QAction *action5 = new QAction(QIcon(str[1]),"保存",this);
    QAction *action6 = new QAction(QIcon(str[2]),"撤回",this);
    QAction *action7 = new QAction(QIcon(str[3]),"恢复",this);
    QAction *action8 = new QAction(QIcon(str[4]),"剪切",this);
    QAction *action9 = new QAction(QIcon(str[5]),"粗体",this);
    QAction *action10 = new QAction(QIcon(str[6]),"斜体",this);
    QAction *action11 = new QAction(QIcon(str[7]),"下划线",this);
    QAction *action12 = new QAction(QIcon(str[8]),"左对齐",this);
    QAction *action13 = new QAction(QIcon(str[9]),"中对齐",this);
    QAction *action14 = new QAction(QIcon(str[10]),"右对齐",this);

    action15->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_C));//快捷键ctrl+C
    action16->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_V));//快捷键ctrl+V




//    action6->setEnabled(false);//设置不能使用

    //工具栏添加工具项
    toolBar->addAction(action4);
    toolBar->addSeparator();//添加分割线

    toolBar->addAction(action5);
    toolBar->addSeparator();//添加分割线

    toolBar->addAction(action6);
    toolBar->addSeparator();//添加分割线

    toolBar->addAction(action7);
    toolBar->addSeparator();//添加分割线

    toolBar->addAction(action8);
    action8->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_X));//快捷键ctrl+X
    toolBar->addSeparator();//添加分割线

    toolBar->addAction(action9);
    toolBar->addSeparator();//添加分割线

    toolBar->addAction(action10);
    toolBar->addSeparator();//添加分割线

    toolBar->addAction(action11);
    toolBar->addSeparator();//添加分割线

    toolBar->addAction(action12);
    toolBar->addSeparator();//添加分割线

    toolBar->addAction(action13);
    toolBar->addSeparator();//添加分割线

    toolBar->addAction(action14);
    toolBar->addSeparator();//添加分割线

/*********************************************************状态栏*****************************/

    //创建状态栏
    QStatusBar *status = new QStatusBar(this);
    status->setObjectName("状态栏");
    status->setStyleSheet("QStatusBar::item{border: 0px}"); //设置不显示label的边框

    //主窗口添加状态栏
    this->setStatusBar(status);

    //创建标签
    QLabel *statusLabel = new QLabel("我是状态栏", this);

    //状态栏添加信息
    status->showMessage("欢迎使用文本编辑器", 3000);//显示在左侧,并且3秒后自动消失

    status->addPermanentWidget(statusLabel);//添加右侧标签(永久性)

    /****************************创建铆接部分**********************************/

    //创建铆接部件
    QDockWidget *dockWidget = new QDockWidget(this);
    dockWidget->setFeatures(QDockWidget::NoDockWidgetFeatures);//设置铆接部件不可移动、不可关闭、不可浮动
    dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);//设置允许左右停靠

    QLabel *titleLabel = new QLabel("行数");
    titleLabel->setAlignment(Qt::AlignCenter);//设置中心对齐
    dockWidget->setTitleBarWidget(titleLabel);//设置标题栏

    //主窗口添加铆接部件
    this->addDockWidget(Qt::LeftDockWidgetArea,dockWidget);//设置铆接部件停靠在左侧(浮动窗口)

    //创建ListWidget

    QListWidget *textList = new QListWidget(this);
    for(int i=1; i<=50; i++)
    {
        QListWidgetItem *item = new QListWidgetItem(QString("%1").arg(i));
        textList->addItem(item);
        item->setTextAlignment(Qt::AlignRight);
    }
    textList->setFixedWidth(30);
    textList->setObjectName("文本列表");
    //设置没有水平以及垂直滑动条
    textList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    textList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    //铆接部件添加内容主体
    dockWidget->setWidget(textList);
//从这里可以看出来铆接部分不是主窗口的一个必要部分
    /**************************************主要部分***************************************/
    //设置中心部件
    //创建文本编辑框 显示文本
    textEdit = new QTextEdit(this);
    textEdit->setText("我是文本编辑框");
    textEdit->setObjectName("文本编辑框");
    connect(textEdit, SIGNAL(textChanged()), this, SLOT(createFile()));//连接信号槽
    QFont font = QFont("宋体",18,QFont::Normal,true);
    //主窗口设置文本编辑框为中心部件
    this->setCentralWidget(textEdit);

    //都大学生了为什么还有作业要做!
/*********************************槽函数与信号的链接*******************************/
    connect(action4, SIGNAL(triggered(bool)), this, SLOT(on_actionopenfile_triggered()));
    connect(action5, SIGNAL(triggered(bool)), this, SLOT(on_ServeFile_triggered()));
    connect(action6, SIGNAL(triggered(bool)), this, SLOT(on_actionundo_triggered()));
    connect(action7, SIGNAL(triggered(bool)), this, SLOT(on_actionredo_triggered()));
    connect(action17, SIGNAL(triggered(bool)), this, SLOT(on_actionundo_triggered()));
    connect(action18, SIGNAL(triggered(bool)), this, SLOT(on_actionredo_triggered()));
    connect(action8, SIGNAL(triggered(bool)), this, SLOT(on_actioncut_triggered()));
    connect(action15, SIGNAL(triggered(bool)), this, SLOT(on_actioncopy_triggered()));
    connect(action16, SIGNAL(triggered(bool)), this, SLOT(on_actionpatse_triggered()));
    connect(action9, SIGNAL(triggered(bool)), this, SLOT(on_actionTextBold_triggered()));
    connect(action10, SIGNAL(triggered(bool)), this, SLOT(on_actionTextItalic_triggered()));
    connect(action11, SIGNAL(triggered(bool)), this, SLOT(on_actionTextUnderLine_triggered()));
    connect(action12, SIGNAL(triggered(bool)), this, SLOT(on_actionLift_triggered()));
    connect(action13, SIGNAL(triggered(bool)), this, SLOT(on_actionCenter_triggered()));
    connect(action14, SIGNAL(triggered(bool)), this, SLOT(on_actionRight_triggered()));
}

MainWindow::~MainWindow()
{
    delete ui;
}
/****************************************槽函数的实现*******************************/
   //关闭主窗口
    void MainWindow::on_actionexit_triggered()
    {
        close();
    }
    //字体改变
    QString MainWindow::showFileDialog(QFileDialog::AcceptMode mode)
    {
        //这个函数可以实现对于文件的打开以及保存
        QString ret = "";
        QFileDialog fd(this);
        QStringList filters;

        filters.append("Text Files (*.txt)");
        filters.append("All Files (*)");

        fd.setWindowTitle("文件");//对话框标题
        fd.setAcceptMode(mode);
//        fd.setFilter();

        if( mode == QFileDialog::AcceptOpen )//是打开文件还是保存文件
        {
            fd.setFileMode(QFileDialog::ExistingFile);//设置可选单个已存在的文件
        }

        if( fd.exec() == QFileDialog::Accepted )
        {
            ret = fd.selectedFiles()[0];//函数返回装有选中的文件的绝对路径的链表
        }

        return ret;
    }
    /*******************对文件进行操作*********************/
    //打开文件!!
    void MainWindow::setCurrentFileName(const QString &fileName)
    {
        m_fileName = fileName;
        textEdit->document()->setModified(false);

        QString shownName;
        if (fileName.isEmpty())
            shownName = "untitled.txt";
        else
            shownName = QFileInfo(fileName).fileName();

        setWindowModified(false);
    }


     void MainWindow ::on_actionopenfile_triggered()
     {

        QString path = showFileDialog(QFileDialog::AcceptOpen);
        setCurrentFileName(path);
             if( path != "" )
             {
                 QFile file(path);

                 if( file.open(QIODevice::ReadOnly | QIODevice::Text) )
                 {
                     textEdit->setPlainText(QString(file.readAll()));//读取文件的所有数据并导入到编辑组件
                     file.close();
                     setWindowTitle("NotePad - [ " + path + " ]");
                 }
                 else
                 {
                     //showErrorMessage(QString("Open file error! \n\n") + "\"" + path + "\"");//自定义的一个错误提示对话框
                 }
             }

     }
     //创建文件
     void MainWindow::on_actionne_triggered()
     {
         QMessageBox::StandardButton ok=QMessageBox::warning(this,tr("Warning"),
         tr("创建新文件?"),
         QMessageBox::Yes | QMessageBox::Default,
         QMessageBox::No);//通过QMessagebox里面的东西来

         m_fileName.clear();
         textEdit->setText(QString());
         if( m_fileName == ""&& ok==QMessageBox::StandardButton::Yes)
             m_fileName = showFileDialog(QFileDialog::AcceptSave);



     }

     //保存文件
     QString MainWindow::saveCurrentData(QString path)
     {
         QString ret = path;

         if( ret == "" )
             ret = showFileDialog(QFileDialog::AcceptSave);
         if( ret != "" )
         {
             QFile file(ret);
             if( file.open(QIODevice::WriteOnly | QIODevice::Text) )
             {
                 QTextStream out(&file);
                 out << textEdit->toPlainText();
                 file.close();
                 setWindowTitle("NotePad - [ " + ret + " ]");
             }
             else
             {
                // showErrorMessage(QString("Save file error! \n\n") + "\"" + ret + "\"");
                 ret = "";
             }
         }
         return ret;
     }

     void MainWindow::on_ServeFile_triggered()
     {
         QString path = saveCurrentData(m_fileName);

             if( path != "" )
             {
                 m_fileName = path;
             }
     }
/*******************对文件进行操作*********************/
     /********************************撤销与恢复****************************/
     void MainWindow::on_actionundo_triggered()
     {
         textEdit->undo();
     }

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

     /********************************撤销与恢复****************************/
     /************剪切******************/
     void MainWindow::on_actioncut_triggered()
     {
         textEdit->cut();
     }

     void MainWindow::on_actioncopy_triggered()
     {
         textEdit->copy();
     }
     void MainWindow::on_actionpatse_triggered()
     {
         textEdit->paste();
     }
     /************剪切******************/
     /************粗体,斜体,下划线*************************/

     //  设置光标的选区,使格式作用于选区内的字符
     void MainWindow::mergeFormat(QTextCharFormat fmt)
     {
         QTextCursor cursor = textEdit->textCursor();
         if (!cursor.hasSelection()) {
            cursor.select(QTextCursor::WordUnderCursor);
         }
         cursor.mergeCharFormat(fmt);
     }

     //加粗
     void MainWindow::on_actionTextBold_triggered()
     {
         bool boldcheck=true;
         QTextCharFormat fmt;
         fmt.setFontWeight(boldcheck ? QFont::Bold : QFont::Normal);
         mergeFormat(fmt);
         boldcheck = !boldcheck;
     }
     //倾斜
     void MainWindow::on_actionTextItalic_triggered()
     {
         bool Italiccheck=true;
         QTextCharFormat fmt;
         fmt.setFontItalic(Italiccheck ? true : false);
         mergeFormat(fmt);
         Italiccheck = !Italiccheck;
     }
     //下划线
     void MainWindow::on_actionTextUnderLine_triggered()
     {
         bool UnderLinecheck=true;
         QTextCharFormat fmt;
         fmt.setFontUnderline(UnderLinecheck ? true : false);
         mergeFormat(fmt);
         UnderLinecheck = !UnderLinecheck;
     }

     /************粗体,斜体,下划线*************************/
     /*******************对齐********************/
     //左对齐
     void MainWindow::on_actionLift_triggered()
     {
         textEdit->setAlignment(Qt::AlignLeft);
     }
     //居中对齐
     void MainWindow::on_actionCenter_triggered()
     {
         textEdit->setAlignment(Qt::AlignCenter);
     }
     //右对齐
     void MainWindow::on_actionRight_triggered()
     {
         textEdit->setAlignment(Qt::AlignRight);
     }

      /*******************对齐********************/
/********************颜色,字体******************************/
     void MainWindow::on_actioncolor_triggered()
     {
         QColor c = QColorDialog::getColor(color,this,"颜色选择框");
         if(c.isValid()){
             color = c;

             // 设置文本框的文本颜色
             // 1. 从光标开始新输入的文本颜色被设置
             // 2. 鼠标选中的文本颜色设置
             textEdit->setTextColor(c);
         }
     }
     void MainWindow::on_actionfont_triggered()
     {
         bool ok; // 用户字体对话框保存是否选择了字体的结构

         // 第一个参数是判断用户是否选择了字体,第二个是字体对话框的初始值
         QFont f = QFontDialog::getFont(&ok,font,this,"选择文本框要设置的字体");//基础的用户字体对话框

         if(ok){
             font = f;

             // 1. 从当前光标开始
             // 2. 鼠标选中的文本的字体
             textEdit->setCurrentFont(f);
         }

     }
     /********************颜色,字体******************************/
     /*************kidding,about*******************************/

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

     void MainWindow::on_about()
     {
         QDesktopServices::openUrl(QUrl(QLatin1String("https://www.qt.io/zh-cn/")));
     }
/*************kidding,about*******************************/

main.cpp(主函数):

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

最后:

帅哥美女们,你们嫌麻烦吗,不嫌的话。

就麻烦给UU个赞吧!

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值