1、程序中的配置文件
应用程序在运行后都有一个初始化的状态
一般而言:
-程序的初始状态是最近一次运行退出前的状态
问题
如何保存和恢复程序状态?
解决思路
-程序退出前保存状态参数到文件(数据库)
-程序再次启动时读出状态参数并恢复
状态参数的存储方式
-文本文件格式(XML, Json, 等)
-轻量级数据库(Access, SQLite, 等)
-私有二进制文件格式
Qt中的解决方案
-通过二进制数据流将状态参数直接存储于文件中
-优势:
参数的存储和读取简单高效,易于编码实现
最终文件为二进制格式,不易被恶意修改
设计与实现
2、主窗口的状态参数
主窗口的状态参数
-应用程序必须保存和恢复主窗口的状态参数
★ 位 置 ,大小
问题
-什么时候保存主窗口的状态数据?
应用程序退出的过程
1. 收到关闭事件
2. 执行关闭事件处理函数
3. 主窗口从屏幕上消失
4. 主窗口的析构函数执行
5 . 。。。
一般而言
-应用程序收到关闭事件时进行状态参数的保存
Qt中的解决方案
1. 重写关闭事件处理函数
2. 在关闭事件处理函数中保存状态参数
3、编程实验
文本编辑器的状态配置,主窗口的状态参数 NotePad.pro
AppConfig.h
#ifndef _APPCONFIG_H_
#define _APPCONFIG_H_
#include <QObject>
#include <QFont>
#include <QSize>
#include <QPoint>
class AppConfig : public QObject
{
Q_OBJECT
QFont m_editorFont; //保存字体
QSize m_mainWindowSize; //保存主窗口大小
QPoint m_mainWindowPoint; //保存主窗口位置
bool m_isAutoWrap; //是否自动换行
bool m_isToolBarVisible; //工具栏可见
bool m_isStatusBarVisible; //状态栏可见
bool m_isValid;
bool restore();
public:
explicit AppConfig(QObject* parent = 0);
explicit AppConfig(QFont font, QPoint point, QSize size, bool isWrap, bool tbVisible, bool sbVisible, QObject* parent = 0);
bool store();
QFont editorFont();
QSize mainWindowSize();
QPoint mainWindowPoint();
bool isAutoWrap();
bool isToolBarVisible();
bool isStatusBarVisible();
bool isValid();
};
#endif // _APPCONFIG_H_
AppConfig.cpp
#include "AppConfig.h"
#include <QFile>
#include <QDataStream>
#include <QApplication>
AppConfig::AppConfig(QObject* parent) : QObject(parent)
{
m_isValid = restore();
}
AppConfig::AppConfig(QFont font, QPoint point, QSize size, bool isWrap, bool tbVisible, bool sbVisible, QObject* parent): QObject(parent)
{
m_editorFont = font;
m_mainWindowPoint = point;
m_mainWindowSize = size;
m_isAutoWrap = isWrap;
m_isToolBarVisible = tbVisible;
m_isStatusBarVisible = sbVisible;
m_isValid = true;
}
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_editorFont;
in >> m_mainWindowPoint;
in >> m_mainWindowSize;
in >> m_isAutoWrap;
in >> m_isToolBarVisible;
in >> m_isStatusBarVisible;
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_editorFont;
out << m_mainWindowPoint;
out << m_mainWindowSize;
out << m_isAutoWrap;
out << m_isToolBarVisible;
out << m_isStatusBarVisible;
file.close();
}
else
{
ret = false;
}
return ret;
}
QFont AppConfig::editorFont()
{
return m_editorFont;
}
QSize AppConfig::mainWindowSize()
{
return m_mainWindowSize;
}
QPoint AppConfig::mainWindowPoint()
{
return m_mainWindowPoint;
}
bool AppConfig::isAutoWrap()
{
return m_isAutoWrap;
}
bool AppConfig::isToolBarVisible()
{
return m_isToolBarVisible;
}
bool AppConfig::isStatusBarVisible()
{
return m_isStatusBarVisible;
}
bool AppConfig::isValid()
{
return m_isValid;
}
在构造函数中恢复(第二阶构造)
bool MainWindow::construct()
{
bool ret = true;
AppConfig config; //生成配置文件对象,进行恢复程序状态
ret = ret && initMenuBar();
ret = ret && initToolBar();
ret = ret && initStatusBar();
ret = ret && initMainEditor();
if( config.isValid() ) //根据设置进行恢复
{
mainEditor.setFont(config.editorFont());
if( !config.isAutoWrap() )
{
mainEditor.setLineWrapMode(QPlainTextEdit::NoWrap);
findMenuBarAction("Auto Wrap")->setChecked(false);
findToolBarAction("Auto Wrap")->setChecked(false);
}
if( !config.isToolBarVisible() )
{
toolBar()->setVisible(false);
findMenuBarAction("Tool Bar")->setChecked(false);
findToolBarAction("Tool Bar")->setChecked(false);
}
if( !config.isStatusBarVisible() )
{
statusBar()->setVisible(false);
findMenuBarAction("Status Bar")->setChecked(false);
findToolBarAction("Status Bar")->setChecked(false);
}
move(config.mainWindowPoint());
resize(config.mainWindowSize());
}
return ret;
}
在关闭事件处理函数中保存状态
void MainWindow::closeEvent(QCloseEvent* e)
{
preEditorChange();
if( !m_isTextChanged )
{
QFont font = mainEditor.font();
bool isWrap = (mainEditor.lineWrapMode() == QPlainTextEdit::WidgetWidth);
bool tbVisible = toolBar()->isVisible();
bool sbVisible = statusBar()->isVisible();
AppConfig config(font, pos(), size(), isWrap, tbVisible, sbVisible); //在AppConfig构造函数中初始化成员变量
config.store(); //保存到配置文件
QMainWindow::closeEvent(e);
}
else
{
e->ignore();
}
}
4、命令行参数的应用
每一个应用程序都能够接收命令行参数
问题 :
GUI系统中命令行参数如何传递到应用程序?
命令行参数的应用一
-传统应用方式
在命令行启动GUI程序时传递参数
命令行参数的应用二
-操作系统关联方式
在文件被双击时,操作系统根据文件后缀选择应用程序
将文件路径作为命令行参数启动应用程序
5、编程实验
处理命令行参数 NotePad.pro
main.cpp
#include <QtGui/QApplication>
#include <QFileInfo>
#include "MainWindow.h"
int main(int argc, char *argv[]) //关于main()的参数相关知识,在C语言进阶剖析已介绍
{
QApplication a(argc, argv);
MainWindow* w = MainWindow::NewInstance();
int ret = -1;
if( w != NULL )
{
if( argc > 1 )
{
QFileInfo fi(argv[1]);
if( fi.exists() )
{
w->openFile(fi.absoluteFilePath());
}
}
w->show();
ret = a.exec();
}
delete w;
return ret;
}
6、小结
应用程序中在退出时保存程序状态(用户配置)
应用程序启动时恢复最近一次的程序状态
可以通过二进制数据流将状态参数直接存储于文件中
二进制数据流的方式非常的安全,简单,高效
GUI程序主窗口的相关参数必须保存
GUI程序在收到关闭事件时保存状态参数
GUI程序依然能够接收命令行参数
操作系统将文件的路径作为命令行参数传递