第五十一课、程序中的配置文件------------------狄泰软件学院
一、程序中的配置文件
1、应用程序在刚开始启动时都要一个初始化状态
(1)、一般而言:程序的初始状态是最近一次运行退出前的状态
2、保存和恢复程序状态的解决思路
(1)、程序退出前保存状态参数到文件(数据库)
(2)、程序再次启动时读出状态参数并恢复
3、状态参数的存储方式
(1)、文本文件格式(XML、JSon等)
(2)、轻量级数据库(Access、SQlite等)
(3)、私有二进制文件格式
4、Qt中的解决方案
(1)、通过二进制数据流将状态参数直接存储于文件中
(2)、优势
A、参数的存储和读取简单高效,易于编码实现
B、最终文件为二进制格式,不易被恶意修改
5、设计与实现
编程思路:一个构造函数用来写入,一个构造函数用来读取
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef APPCONFIG_H #define APPCONFIG_H #include <QObject> #include <QFont> class AppConfig : public QObject { Q_OBJECT QFont m_editFont; bool m_isToolBarVisible; bool m_isStatusVisible; bool m_isAutoWrap; bool m_isValid; bool restore(); public: explicit AppConfig(QObject *parent = 0); explicit AppConfig(QFont editFont, bool isToolBarVisible, bool isStatusVisible,bool isAutoWrap, QObject *parent = 0); QFont editFont(); bool isToolBarVisible(); bool isStatusBarVisible(); bool isAutoWrap(); bool isValid(); bool store(); }; #endif // APPCONFIG_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include "AppConfig.h" #include <QFile> #include <QDataStream> #include <QApplication> #include <QIODevice> //此构造函数用来读取 AppConfig::AppConfig(QObject *parent) : QObject(parent) { m_isValid = restore(); } //此构造函数用来写入 AppConfig::AppConfig(QFont editFont, bool isToolBarVisible, bool isStatusVisible,bool isAutoWrap, QObject *parent) { m_editFont = editFont; m_isToolBarVisible = isToolBarVisible; m_isStatusVisible = isStatusVisible; m_isAutoWrap = isAutoWrap; m_isValid = true; } QFont AppConfig::editFont() { return m_editFont; } bool AppConfig::isToolBarVisible() { return m_isToolBarVisible; } bool AppConfig::isStatusBarVisible() { return m_isStatusVisible; } bool AppConfig::isAutoWrap() { return m_isAutoWrap; } bool AppConfig::isValid() { return m_isValid; } bool AppConfig::restore() { bool ret = true; QFile file(QApplication::applicationDirPath() + "/app.config"); if(file.open(QIODevice::ReadOnly)) { QDataStream in(&file); in.setVersion(QDataStream::Qt_4_7); in >> m_editFont; in >> m_isToolBarVisible; in >> m_isStatusVisible; in >> m_isAutoWrap; file.close(); } else { ret = false; } return ret; } bool AppConfig::store() { bool ret = true; QFile file(QApplication::applicationDirPath() + "/app.config"); if(file.open(QIODevice::WriteOnly)) { QDataStream out(&file); out.setVersion(QDataStream::Qt_4_7); out << m_editFont; out << m_isToolBarVisible; out << m_isStatusVisible; out << m_isAutoWrap; file.close(); } else { ret = false; } return ret; }
使用这个类的方法:在二阶构造那里调用读出的构造函数,在析构函数那里调用写入的构造函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
bool MainWindow::construct() { bool ret = true; AppConfig config; ret = ret && initMenuBar(); ret = ret && initToolBar(); ret = ret && initStatusBar(); ret = ret && initinitMainEditor(); if(config.isValid()) { mainEdit.setFont(config.editFont()); //不自动换行 if(!config.isAutoWrap()) { mainEdit.setLineWrapMode(QPlainTextEdit::NoWrap); findMenuBarAction("换行")->setChecked(false); findToolBarAction("换行")->setChecked(false); } //隐藏工具栏 if(!config.isToolBarVisible()) { toolBar()->setVisible(false); findMenuBarAction("工具栏")->setChecked(false); findToolBarAction("工具栏")->setChecked(false); } //隐藏状态栏 if(!config.isStatusBarVisible()) { statusBar()->setVisible(false); findMenuBarAction("状态栏")->setChecked(false); findToolBarAction("状态栏")->setChecked(false); } } return ret; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
MainWindow::~MainWindow() { QFont font = mainEdit.font(); bool isWrap = (mainEdit.lineWrapMode() == QPlainTextEdit::WidgetWidth); bool tbVisible = (findMenuBarAction("工具栏")->isChecked() && (findToolBarAction("工具栏")->isChecked())); bool sbVisible = (findMenuBarAction("状态栏")->isChecked() && (findToolBarAction("状态栏")->isChecked())); AppConfig config(font, tbVisible, sbVisible, isWrap); config.store(); }
其它修改的地方:将查找工具栏的函数抽取出来做一个函数
之前使用到的函数也做了相应修改:
前几节课的bug已找到,创建菜单时忘了指定父组件
而后面又通过children()函数来寻找,自然出错:
二、小结
(1)、应用程序在退出时保存应用状态(用户配置)
(2)、应用程序启动时恢复最近异常程序状态
(3)、可以通过二进制数据流将状态参数直接存储于文件中
(4)、二进制数据流的方式非常的安全,简单,高效