对于很多专业软件来说,每次计算都要在界面上需要输入很多参数。类似下图这样的: 每次运行,这些参数大部分是相同的,需要保存下来以免每次都重新输入。
主要的输入控件是 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_HQtWidgetsSaveLoad.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(); }