Qt 第35课、文本编辑器中的数据存取
创始人
2025-05-29 06:14:18
0

1、QAction 的信号

  • QAction 被点击之后会产生一个 triggered 信号
    — 通过信号与槽的机制能够捕捉对 QAction 对象的操作
    — 项目中可以将多个信号映射到同一个槽函数
connect(action, SIGNAL(triggered()), this, SLOT(slot_function()));

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

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include 
#include 
#include 
#include class MainWindow : public QMainWindow
{Q_OBJECT
private:QPlainTextEdit plainEdit;QLabel statusLbl;QString m_filePath;MainWindow();MainWindow(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 text, int key);bool makeAction(QAction*& action, QWidget* parent, QString text, QString path);QString showFileDialog(QFileDialog::AcceptMode mode, QString title);void showErrorMessage(QString message);private slots:void onFileOpen();void onFileSave();void onFileSaveAs();
public:static MainWindow* NewInstance();~MainWindow();
};
#endif // MAINWINDOW_H

MainWindowUI.cpp

#include "MainWindow.h"
#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();ret = ret && initFileMenu(mb);ret = ret && initEditMenu(mb);ret = ret && initFormatMenu(mb);ret = ret && initViewMenu(mb);ret = ret && initHelpMenu(mb);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);setCentralWidget(&plainEdit);return ret;
}bool MainWindow::initFileMenu(QMenuBar* mb)
{QMenu* menu = new QMenu("File(&F)", nullptr);bool ret = (menu != nullptr);if(ret){QAction* action = nullptr;ret = ret && makeAction(action, menu, "New(&N)", Qt::CTRL + Qt::Key_N);if(ret){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{ret = false;delete menu;}return ret;
}
bool MainWindow::initEditMenu(QMenuBar* mb)
{QMenu* menu = new QMenu("Edit(&E)", nullptr);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{ret = false;delete menu;}return ret;
}
bool MainWindow::initFormatMenu(QMenuBar* mb)
{QMenu* menu = new QMenu("Format(&O)", nullptr);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{ret = false;delete menu;}return ret;
}
bool MainWindow::initViewMenu(QMenuBar* mb)
{QMenu* menu = new QMenu("View(&V)", nullptr);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{ret = false;delete menu;}return ret;
}
bool MainWindow::initHelpMenu(QMenuBar* mb)
{QMenu* menu = new QMenu("Help(&H)", nullptr);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{ret = false;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){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 text, int key)
{bool ret = true;action = new QAction(text, parent);if(action != nullptr){action->setShortcut(QKeySequence(key));}else{ret = false;}return ret;
}bool MainWindow::makeAction(QAction*& action,  QWidget* parent, QString text, QString path)
{bool ret = true;action = new QAction("", parent);if(action != nullptr){action->setToolTip(text);action->setIcon(QIcon(path));}else{ret = false;}return ret;
}MainWindow::~MainWindow()
{}

MainWindowSlots.cpp

#include "MainWindow.h"
#include 
#include 
#include 
#include 
#include QString MainWindow::showFileDialog(QFileDialog::AcceptMode mode, QString title)
{QString ret = "";QFileDialog flg(this);flg.setAcceptMode(mode);flg.setWindowTitle(title);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.setIcon(QMessageBox::Critical);msg.setText(message);msg.setStandardButtons(QMessageBox::Ok);msg.exec();
}void MainWindow::onFileOpen()
{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") + "\"" + path + "\"");}}}void MainWindow::onFileSave()
{if(m_filePath == ""){m_filePath = showFileDialog(QFileDialog::AcceptSave, "Save");}if(m_filePath != ""){QFile file(m_filePath);if(file.open(QIODevice::WriteOnly | QIODevice::Text)){QTextStream out(&file);out << plainEdit.toPlainText();file.close();setWindowTitle("NotePad - [ " + m_filePath + " ]");}else{showErrorMessage(QString("Save file error \n\n") + "\"" + m_filePath + "\"");m_filePath = "";}}
}void MainWindow::onFileSaveAs()
{QString path = showFileDialog(QFileDialog::AcceptSave, "Save as");if(path != ""){QFile file(path);if(file.open(QIODevice::WriteOnly | QIODevice::Text)){QTextStream out(&file);out << plainEdit.toPlainText();file.close();m_filePath = path;setWindowTitle("NotePad - [ " + m_filePath + " ]");}else{showErrorMessage(QString("Save as file error \n\n") + "\"" + m_filePath + "\"");}}
}

main.cpp

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

思考:如何判断是否存在为保存的数据?
在文件打开的步骤那里,我们只实现了内部不存在保存的数据,所以我们的程序只有直接打开文件的功能。但是实际上如果内部存在数据,我们要先保存数据,然后再去打开文本。

小结

  • Qt 项目中尽量将界面代码和功能代码分离开
  • Qt 项目开发时尽量复用平台提供的相关组件
  • Qt 项目中的多数情况都是编写相应的槽函数
    — 槽函数用于相应用户操作
    — 槽函数是具体功能的触发点

相关内容

热门资讯

基础入门 HTTP数据包Pos... 文章目录数据-方法&头部&状态码请求requestResponse状态码案例-文件探针&登录爆破工具...
【每日一题Day151】LC1... 执行操作后字典序最小的字符串【LC1625】 给你一个字符串 s 以及两个整数 a 和 b 。其中...
最新或2023(历届)小学生学... 【学习雷锋好榜样】  学习雷锋好榜样  忠于革命忠于党  爱憎分明不忘本  立场坚定斗志强  立场坚...
最新或2023(历届)3月学雷... 【素材一:团结友爱】  雷锋把自己的藏书拿出来供大家学习,被人们称为“小小的雷锋图书馆”。他帮助同志...
小学一年级学雷锋手抄报内容最新... 【学雷锋心得体会】  三月是一个春光明媚、生机勃勃的季节,三月更是一个讲文明、树新风、发扬雷锋精神的...
最新或2023(历届)最新小学... 【关于雷锋的名言】  1、我觉得一个革命者就应该把革命利益放在第一位,为党的事业贡献出自己的一切,这...
小学生最新或2023(历届)3...  【学雷锋心得体会】  “滴水只有放进大海才永远不会干涸,一个人只有当他把自己和事业融合在一起才能最...
cdn原理与应用 免费的ChatGPT镜像网站网页搜索技巧 | 西园公子的科研百宝箱 (zwjjiaozhu.top)...
最新或2023(历届)小学二年... 【雷锋的名言】  1) 我愿永远做一个螺丝钉。  2) 谁要是游戏人生,他就一事无成;谁不能主宰自己...
最新或2023(历届)3月5日... 【雷锋日记摘抄】  6月5日  单丝不成线,独木不成林。一个人是办不了大事的,群众的事一定要发动群众...
最新或2023(历届)学习雷锋...  1940年12月18日:雷锋(原名:雷正兴)出生在湖南长沙望城区雷锋镇简家塘一户贫苦农民家里,这一...
Spring注解驱动开发--声... Spring注解驱动开发—声明式事务 六、声明式事务 环境搭建: 1、导入相关依赖 数...
论文解读HN-PPISP:一种... Title:HN-PPISP: a hybrid network based on MLP-Mixe...
最新或2023(历届)小学生学...  1960年11月雷锋被树为沈阳军区学毛著的标兵后。1961年2月,解放军各部队掀起了学习雷锋的高潮...
最新或2023(历届)学雷锋手...  共青团中央确定3月5日为中国青年志愿者服务日,团中央、中国青年志愿者协会近日下发通知,从2000年...
最新或2023(历届)小学生学...  雷锋的名言  (1) 人的生命是有限的,可是,为人民服务是无限的,我要把有限的生命,投入到无限为人...
学习雷锋手抄报图片最新或202...  雷锋,原名雷正兴。1940年1月至1962年8月 在中国人民解放军某部运输连任战士、班长。1962...
最新或2023(历届)学习雷锋...  雷锋精神  雷锋精神,是以雷锋的名字命名的、以雷锋的精神为基本内涵的、在实践中不断丰富和发展着的革...
B2097 最长平台 【入门】 白细胞计数 题目描述 医院采样了某临床病例治疗期间的白细胞数量样本 nnn 份,用于分...
最新或2023(历届)学习雷锋...   向雷锋同志学习  雷锋同志因公殉职后,1963年1月7日,国防部命名他生前所在班为“雷锋班”;1...