Qt 第36课、文本编辑器中的功能交互
创始人
2025-05-28 23:15:28
0

思考:如何判断是否存在未保存的数据?

1、QPlainTextEdit 中的信号

  • QPlainTextEdit 能够触发与编辑操作相关的信号
    在这里插入图片描述
  • 解决方案
    1、定义槽函数 void onTextChanged()
    2、映射 textChanged() 到槽函数
    3、定义成员变量 bool m_isTextChanged = false;
    4、文本框中的字符发生变化时, m_isTextChanged = true;
    5、当 m_isTextChanged 为真,则存在未保存的数据

在这里插入图片描述
MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include 
#include 
#include 
#include 
#include class MainWindow : public QMainWindow
{Q_OBJECT
private:bool m_isTextChanged;QPlainTextEdit plainEdit;QLabel statusLbl;QString m_filePath;MainWindow();MainWindow(const MainWindow& obj);MainWindow& operator= (const MainWindow& obj);bool construct();bool initMenuBar();bool initToolBar();bool initStatusBar();bool initMainEditor();bool initFileMenu(QMenuBar* mb);bool initEditMenu(QMenuBar* mb);bool initFormatMenu(QMenuBar* mb);bool initViewMenu(QMenuBar* mb);bool initHelpMenu(QMenuBar* mb);bool initFileToolItem(QToolBar* tb);bool initEditToolItem(QToolBar* tb);bool initFormatToolItem(QToolBar* tb);bool initViewToolItem(QToolBar* tb);bool makeAction(QAction*& action, QWidget* Parent, QString str, int key);bool makeAction(QAction*& action, QWidget* Parent, QString tip, QString res);QString showFileDialog(QFileDialog::AcceptMode mode, QString title);void showErrorMessage(QString message);int showQueryMessage(QString message);void saveCurrentData(QString path = "");void preEditChange();
private slots:void onFileNew();void onFileOpen();void onFileSave();void onFileSaveAs();void onTextChange();
public:static MainWindow* NewInstance();~MainWindow();
};
#endif // MAINWINDOW_H

MainWindowUI.cpp

#include "MainWindow.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include #include MainWindow::MainWindow(): QMainWindow()
{m_filePath = "";resize(1000, 800);setWindowTitle("NotePad");
}bool MainWindow::construct()
{bool ret = true;ret = ret && initMenuBar();ret = ret && initToolBar();ret = ret && initStatusBar();ret = ret && initMainEditor();return ret;
}MainWindow* MainWindow::NewInstance()
{MainWindow* ret = new MainWindow();if(!(ret && ret->construct())){delete ret;ret = nullptr;}return ret;
}bool MainWindow::initMenuBar()
{bool ret = true;QMenuBar* mb = menuBar();if(mb != nullptr){ret = ret && initFileMenu(mb);ret = ret && initEditMenu(mb);ret = ret && initFormatMenu(mb);ret = ret && initViewMenu(mb);ret = ret && initHelpMenu(mb);}else{ret = false;}return ret;
}bool MainWindow::initToolBar()
{bool ret = true;QToolBar* tb = addToolBar("ToolBar");tb->setFloatable(false);tb->setMovable(false);tb->setIconSize(QSize(16, 16));ret = ret && initFileToolItem(tb);tb->addSeparator();ret = ret && initEditToolItem(tb);tb->addSeparator();ret = ret && initFormatToolItem(tb);tb->addSeparator();ret = ret && initViewToolItem(tb);return ret;
}bool MainWindow::initStatusBar()
{bool ret = true;QStatusBar* sb = statusBar();QLabel* label = new QLabel("D.T.Software");if(label != nullptr){statusLbl.setMinimumWidth(200);statusLbl.setAlignment(Qt::AlignCenter);statusLbl.setText("Ln: 1   Col: 1");label->setMinimumWidth(200);label->setAlignment(Qt::AlignCenter);sb->addPermanentWidget(new QLabel());sb->addPermanentWidget(&statusLbl);sb->addPermanentWidget(label);}else{ret = false;}return ret;
}bool MainWindow::initMainEditor()
{bool ret = true;plainEdit.setParent(this);connect(&plainEdit, SIGNAL(textChanged()), this, SLOT(onTextChange()));setCentralWidget(&plainEdit);return ret;
}bool MainWindow::initFileMenu(QMenuBar* mb)
{QMenu* menu = new QMenu("File(&F)", mb);bool ret = (menu != nullptr);if(ret){QAction* action = nullptr;ret = ret && makeAction(action, menu, "New(&N)", Qt::CTRL + Qt::Key_N);if(ret){connect(action, SIGNAL(triggered()), this, SLOT(onFileNew()));menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Open(&O)", Qt::CTRL + Qt::Key_O);if(ret){connect(action, SIGNAL(triggered()), this, SLOT(onFileOpen()));menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Save(&N)", Qt::CTRL + Qt::Key_S);if(ret){connect(action, SIGNAL(triggered()), this, SLOT(onFileSave()));menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Save As(&A)", Qt::CTRL + Qt::SHIFT + Qt::Key_S);if(ret){connect(action, SIGNAL(triggered()), this, SLOT(onFileSaveAs()));menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Print(&P)", Qt::CTRL + Qt::Key_P);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Exit(&X)", 0);if(ret){menu->addAction(action);}menu->addSeparator();}if(ret){mb->addMenu(menu);}else{delete menu;}return ret;
}bool MainWindow::initEditMenu(QMenuBar* mb)
{QMenu* menu = new QMenu("Edit(&E)", mb);bool ret = (menu != nullptr);if(ret){QAction* action = nullptr;ret = ret && makeAction(action, menu, "Undo(&U)", Qt::CTRL + Qt::Key_Z);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Redo(&R)", Qt::CTRL + Qt::Key_Y);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Cut(&T)", Qt::CTRL + Qt::Key_X);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Copy(&C)", Qt::CTRL + Qt::Key_C);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Paste(&P)", Qt::CTRL + Qt::Key_V);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Delete(&L)", Qt::Key_Delete);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Find(&F)", Qt::CTRL + Qt::Key_F);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Replace(&R)", Qt::CTRL + Qt::Key_H);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Goto(&G)", Qt::CTRL + Qt::Key_G);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Select All(&A)", Qt::CTRL + Qt::Key_A);if(ret){menu->addAction(action);}menu->addSeparator();}if(ret){mb->addMenu(menu);}else{delete menu;}return ret;
}bool MainWindow::initFormatMenu(QMenuBar* mb)
{QMenu* menu = new QMenu("Format(&O)", mb);bool ret = (menu != nullptr);if(ret){QAction* action = nullptr;ret = ret && makeAction(action, menu, "AutoWrap(&W)", 0);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "Font(&F)", 0);if(ret){menu->addAction(action);}menu->addSeparator();}if(ret){mb->addMenu(menu);}else{delete menu;}return ret;
}bool MainWindow::initViewMenu(QMenuBar* mb)
{QMenu* menu = new QMenu("View(&V)", mb);bool ret = (menu != nullptr);if(ret){QAction* action = nullptr;ret = ret && makeAction(action, menu, "ToolBar(&T)", 0);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "StatusBar(&S)", 0);if(ret){menu->addAction(action);}menu->addSeparator();}if(ret){mb->addMenu(menu);}else{delete menu;}return ret;
}bool MainWindow::initHelpMenu(QMenuBar* mb)
{QMenu* menu = new QMenu("Help(&H)", mb);bool ret = (menu != nullptr);if(ret){QAction* action = nullptr;ret = ret && makeAction(action, menu, "User Manual", 0);if(ret){menu->addAction(action);}menu->addSeparator();ret = ret && makeAction(action, menu, "About NotePad...", 0);if(ret){menu->addAction(action);}menu->addSeparator();}if(ret){mb->addMenu(menu);}else{delete menu;}return ret;
}bool MainWindow::initFileToolItem(QToolBar* tb)
{bool ret = true;QAction* action = nullptr;ret = ret && makeAction(action, tb, "New", ":/res/pic/new.png");if(ret){connect(action, SIGNAL(triggered()), this, SLOT(onFileNew()));tb->addAction(action);}ret = ret && makeAction(action, tb, "Open", ":/res/pic/open.png");if(ret){connect(action, SIGNAL(triggered()), this, SLOT(onFileOpen()));tb->addAction(action);}ret = ret && makeAction(action, tb, "Save", ":/res/pic/save.png");if(ret){connect(action, SIGNAL(triggered()), this, SLOT(onFileSave()));tb->addAction(action);}ret = ret && makeAction(action, tb, "Save as", ":/res/pic/saveas.png");if(ret){connect(action, SIGNAL(triggered()), this, SLOT(onFileSaveAs()));tb->addAction(action);}ret = ret && makeAction(action, tb, "Print", ":/res/pic/print.png");if(ret){tb->addAction(action);}return ret;
}bool MainWindow::initEditToolItem(QToolBar* tb)
{bool ret = true;QAction* action = nullptr;ret = ret && makeAction(action, tb, "Undo", ":/res/pic/undo.png");if(ret){tb->addAction(action);}ret = ret && makeAction(action, tb, "Redo", ":/res/pic/redo.png");if(ret){tb->addAction(action);}ret = ret && makeAction(action, tb, "Cut", ":/res/pic/cut.png");if(ret){tb->addAction(action);}ret = ret && makeAction(action, tb, "Copy", ":/res/pic/copy.png");if(ret){tb->addAction(action);}ret = ret && makeAction(action, tb, "Paste", ":/res/pic/paste.png");if(ret){tb->addAction(action);}ret = ret && makeAction(action, tb, "Find", ":/res/pic/find.png");if(ret){tb->addAction(action);}ret = ret && makeAction(action, tb, "Replace", ":/res/pic/replace.png");if(ret){tb->addAction(action);}ret = ret && makeAction(action, tb, "Goto", ":/res/pic/goto.png");if(ret){tb->addAction(action);}return ret;
}bool MainWindow::initFormatToolItem(QToolBar* tb)
{bool ret = true;QAction* action = nullptr;ret = ret && makeAction(action, tb, "Wrap", ":/res/pic/wrap.png");if(ret){tb->addAction(action);}ret = ret && makeAction(action, tb, "Font", ":/res/pic/font.png");if(ret){tb->addAction(action);}return ret;
}bool MainWindow::initViewToolItem(QToolBar* tb)
{bool ret = true;QAction* action = nullptr;ret = ret && makeAction(action, tb, "Tool", ":/res/pic/tool.png");if(ret){tb->addAction(action);}ret = ret && makeAction(action, tb, "Status", ":/res/pic/status.png");if(ret){tb->addAction(action);}return ret;
}bool MainWindow::makeAction(QAction*& action, QWidget* Parent, QString str, int key)
{bool ret = true;action = new QAction(str, Parent);if(action != nullptr){action->setShortcut(QKeySequence(key));}else{ret = false;}return ret;
}bool MainWindow::makeAction(QAction*& action, QWidget* Parent, QString tip, QString res)
{bool ret = true;action = new QAction("", Parent);if(action != nullptr){action->setToolTip(tip);action->setIcon(QIcon(res));}else{ret = false;}return ret;
}MainWindow::~MainWindow()
{}

MainWindowSlots.cpp

#include "MainWindow.h"
#include 
#include 
#include 
#include 
#include //void MainWindow::onFileOpen()
//{
//    QFileDialog flg(this);
//    flg.setWindowTitle("Open");
//    flg.setAcceptMode(QFileDialog::AcceptOpen);
//    flg.setFileMode(QFileDialog::ExistingFile);//    QStringList filters;
//    filters << "Text files (*.txt)"
//            << "Any files (*)";//    flg.setNameFilters(filters);//    if(flg.exec() == QFileDialog::Accept)
//    {
//        QStringList fs = flg.selectedFiles();
//        QFile file(fs[0]);
//        if(file.open(QIODevice::ReadOnly | QIODevice::Text))
//        {
//            plainEdit.setPlainText(QString(file.readAll()));
//            file.close();
//        }
//        else
//        {
//            QMessageBox msg(this);
//            msg.setWindowTitle("Error");
//            msg.setText(QString("Open File Error!\n\n") + "\"" + fs[0] + "\"");
//            msg.setStandardButtons(QMessageBox::Ok);
//            msg.setIcon(QMessageBox::Critical);
//            msg.exec();
//        }
//    }
//}QString MainWindow::showFileDialog(QFileDialog::AcceptMode mode, QString title)
{QString ret = "";QFileDialog flg(this);flg.setWindowTitle(title);flg.setAcceptMode(mode);if(mode == QFileDialog::AcceptOpen){flg.setFileMode(QFileDialog::ExistingFile);}QStringList filters;filters << "Text files (*.txt)"<< "Any files (*)";flg.setNameFilters(filters);if(flg.exec() == QFileDialog::Accepted){ret = flg.selectedFiles()[0];}return ret;
}void MainWindow::showErrorMessage(QString message)
{QMessageBox msg(this);msg.setWindowTitle("Error");msg.setText(message);msg.setStandardButtons(QMessageBox::Ok);msg.setIcon(QMessageBox::Critical);msg.exec();
}int MainWindow::showQueryMessage(QString message)
{QMessageBox msg(this);msg.setWindowTitle("Query");msg.setText(message);msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);msg.setIcon(QMessageBox::Question);return msg.exec();
}void MainWindow::saveCurrentData(QString path)
{if(path == ""){path = showFileDialog(QFileDialog::AcceptSave, "Save");}if(path != ""){QFile file(path);if(file.open(QIODevice::WriteOnly | QIODevice::Text)){QTextStream out(&file);out << plainEdit.toPlainText();file.close();setWindowTitle("NotePad - [ " + path + " ]");m_isTextChanged = false;}else{showErrorMessage(QString("save file Error\n\n") + "\"" + path +"\"");}}
}void MainWindow::preEditChange()
{if(m_isTextChanged){int r = showQueryMessage("Do you want to save the change of the text");switch (r){case QMessageBox::Yes:saveCurrentData(m_filePath);break;case QMessageBox::No:m_isTextChanged = false;break;case QMessageBox::Cancel:break;}}
}void MainWindow::onFileNew()
{preEditChange();if(!m_isTextChanged){plainEdit.clear();setWindowTitle("NotePad - [ New]");m_filePath = "";m_isTextChanged = false;}
}void MainWindow::onFileOpen()
{preEditChange();if(!m_isTextChanged){QString path = showFileDialog(QFileDialog::AcceptOpen, "Open");if(path != ""){QFile file(path);if(file.open(QIODevice::ReadOnly | QIODevice::Text)){plainEdit.setPlainText(QString(file.readAll()));file.close();m_filePath = path;setWindowTitle("NotePad - [ " + m_filePath + " ]");}else{showErrorMessage(QString("open file Error\n\n") + "\"" + path +"\"");}}}
}void MainWindow::onFileSave()
{saveCurrentData(m_filePath);
}void MainWindow::onFileSaveAs()
{saveCurrentData();
}void MainWindow::onTextChange()
{if(!m_isTextChanged){setWindowTitle("*" + windowTitle());}m_isTextChanged = true;}

main.cpp

#include "MainWindow.h"#include int main(int argc, char *argv[])
{QApplication a(argc, argv);int ret = 0;MainWindow* w = MainWindow::NewInstance();if(w != nullptr){w->show();ret = a.exec();}delete w;return ret;
}

小结:

  • 文本编辑组件能够触发与编辑操作相关的信号
  • textChanged() 信号能够用于检测数据变化
  • 文本编辑器项目中需要设置状态变量
  • 功能间的交互通过状态变量完成

相关内容

热门资讯

市人大常委会举行宪法宣誓仪式   本报讯(记者杨盛)6月27日下午,市人大常委会举行宪法宣誓仪式。市人大常委会主任黄中贤主持并监誓...
“苏造”电动车海外成新宠 本报讯 (记者 宋晓华) 从东南亚的繁忙街巷到非洲的广袤大地,从南美洲的崎岖山路到中东的商贸集市……...
黄海之滨,16只东方白鹳幼鸟放... □ 本报记者 程晓琳 华钰 6月26日清晨,盐城市建湖县九龙口国家湿地公园,16只羽翼初丰的东...
最新或2023(历届)小学写景...   开篇简明扼要,精炼有序;重点描述…给人留下深刻印象。   以景喻情,开头颇有新意;倒叙开头,渲染...
南宁市人民代表大会常务委员会任...   (一)  决定任命:  王合新为南宁市机关事务管理局局长  决定免去:  肖宁的南宁市机关事务管...