zoukankan      html  css  js  c++  java
  • 第五十一课、程序中的配置文件------------------狄泰软件学院

    一、程序中的配置文件

    1、应用程序在刚开始启动时都要一个初始化状态

    (1)、一般而言:程序的初始状态是最近一次运行退出前的状态

    2、保存和恢复程序状态的解决思路

    (1)、程序退出前保存状态参数到文件(数据库)

    (2)、程序再次启动时读出状态参数并恢复

    3、状态参数的存储方式

    (1)、文本文件格式(XML、JSon等)

    (2)、轻量级数据库(Access、SQlite等)

    (3)、私有二进制文件格式

    4、Qt中的解决方案

    (1)、通过二进制数据流将状态参数直接存储于文件中

    (2)、优势

    A、参数的存储和读取简单高效,易于编码实现

    B、最终文件为二进制格式,不易被恶意修改

    5、设计与实现

    编程思路:一个构造函数用来写入,一个构造函数用来读取

    #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
    Application.h
    #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;
    }
    Application.cpp

     使用这个类的方法:在二阶构造那里调用读出的构造函数,在析构函数那里调用写入的构造函数

    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;
    }
    读出
    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)、二进制数据流的方式非常的安全,简单,高效

  • 相关阅读:
    java爬取Excel表格
    drf-view
    django--View
    tornado的Application的一些事儿
    tornado的路由分发
    线程和asyncio的比较
    GIL
    else的使用
    协程
    生成器代替迭代器
  • 原文地址:https://www.cnblogs.com/gui-lin/p/6428435.html
Copyright © 2011-2022 走看看