对于很多专业软件来说,每次计算都要在界面上需要输入很多参数。类似下图这样的:
每次运行,这些参数大部分是相同的,需要保存下来以免每次都重新输入。
主要的输入控件是 QLineEdit,因为界面上输入区域 QLineEdit太多,不方便用JSON、XML或Setting的方式,按名称/数值 对一个个保存。
因此采用序列化的保存方式,但是qt不能对一般的QWidget序列化,更不用说以QWidget为成员的QList,编译时就会出错。
而且保存全部QWidget信息没有必要,我们关心的只是名称和数值,name and value
因此自定义了一个 WidgetInfo 类,并实现了它的序列化
class WidgetInfo
{
public:
QString name ;
QString value ;
//重载运算符
friend QDataStream & operator << ( QDataStream &dataStream, const WidgetInfo &wi ){
dataStream << wi.name << wi.value ;
return dataStream ;
}
friend QDataStream & operator >> ( QDataStream &dataStream, WidgetInfo &wi ){
dataStream >> wi.name >> wi.value ;
return dataStream ;
}
};
所有要保存的widget,必须用 setObjectName() 设置过名字,在创建widget时设置。
因为 w->objectName() 这个函数不能返回对象名或变量名, 它返回的只是setObjectName() 设置的名字 ,
用QDesigner创建的界面,已经执行了setObjectName,
手工创建的界面,必须用 setObjectName() 设置名字。
目前代码只处理了 QLineEdit的保存,其它控件类似。
上代码:
QtWidgetsSaveLoad.h
#ifndef QTWIDGETSSAVELOAD_H
#define QTWIDGETSSAVELOAD_H
#include <QtWidgets>
#include <QList>
#include <QDataStream>
class WidgetInfo
{
public:
QString name ;
QString value ;
//重载运算符
friend QDataStream & operator << ( QDataStream &dataStream, const WidgetInfo &wi ){
dataStream << wi.name << wi.value ;
return dataStream ;
}
friend QDataStream & operator >> ( QDataStream &dataStream, WidgetInfo &wi ){
dataStream >> wi.name >> wi.value ;
return dataStream ;
}
};
class QtWidgetsSaveLoad
{
public:
QtWidgetsSaveLoad();
void addWidget( QLineEdit *w ) ;
void saveToFile( QWidget *parent ) ;
void loadFromFile( QWidget *parent ) ;
void setFilenameWithPath( const QString &filenameWithPath) ;
QList <WidgetInfo> widgetInfoList ;
protected:
QString filename ;
QString workPath ;
void gatherChildrenWidgetInfo( QWidget *parent ) ;
void setChildrenWidgetValue( QWidget *parent ) ;
};
#endif // QTWIDGETSSAVELOAD_H
QtWidgetsSaveLoad.cpp
#include "QtWidgetsSaveLoad.h"
#include <QDataStream>
QtWidgetsSaveLoad::QtWidgetsSaveLoad()
{
}
void QtWidgetsSaveLoad::addWidget( QLineEdit *w )
{
WidgetInfo wi ;
wi.name = w->objectName() ;
wi.value = w->text() ;
widgetInfoList.append( wi ) ;
}
void QtWidgetsSaveLoad::gatherChildrenWidgetInfo( QWidget *parent )
{
// 收集控件信息,保存到 QList WidgetInfo
QList <QLineEdit*> list = parent->findChildren<QLineEdit *>();
for( int i = 0 ; i < list.size(); i++)
{
QLineEdit *le = list.at(i) ;
if( le->objectName() == "" )
qDebug() << "widget should run setObjectName() to set a name;" ;
else {
WidgetInfo wi ;
wi.name = le->objectName() ;
wi.value = le->text() ;
widgetInfoList.append( wi ) ;
}
}
}
void QtWidgetsSaveLoad::setChildrenWidgetValue( QWidget *parent )
{
QList <QLineEdit*> list = parent->findChildren<QLineEdit *>();
for( int i = 0 ; i < widgetInfoList.size() ;i++ ){
for(int j = 0 ; j < list.size(); j++)
{
QLineEdit *le = list.at(j) ;
if( le->objectName() == widgetInfoList.at(i).name )
le->setText( widgetInfoList.at(i).value ) ;
}
}
}
// 所有要保存的widget,必须用 setObjectName() 设置过名字,在创建widget时设置
// 因为 w->objectName() 这个函数不能返回对象名或变量名,
// 它返回的只是 setObjectName() 设置的名字 , 用QDesigner创建的界面,已经设置了setObjectName
void QtWidgetsSaveLoad::saveToFile( QWidget *parent )
{
// 收集控件信息,保存到 QList WidgetInfo 中
gatherChildrenWidgetInfo( parent ) ;
// 把 QList WidgetInfo 序列化 到文件中
QString allpath = workPath + "\\" + filename ;
QFile file( allpath ) ;
if( file.open( QIODevice::ReadWrite ) ){
QDataStream stream( &file ) ;
stream << widgetInfoList ;
file.close();
}
else {
qDebug() << allpath + " open error!" ;
}
}
void QtWidgetsSaveLoad::loadFromFile( QWidget *parent )
{
// 通过 序列化 读取文件中信息到 QList WidgetInfo
QString allpath = workPath + "\\" + filename ;
QFile file( allpath ) ;
if( file.open( QIODevice::ReadOnly ) ){
QDataStream stream( &file ) ;
stream >> widgetInfoList ;
file.close();
}
else {
qDebug() << allpath + " open error!" ;
}
setChildrenWidgetValue( parent ) ;
}
void QtWidgetsSaveLoad::setFilenameWithPath( const QString &filenameWithPath)
{
QFileInfo fileinfo = QFileInfo( filenameWithPath );
filename = fileinfo.fileName();
workPath = fileinfo.absolutePath();
}