原文地址:http://www.dazzle.plus.com/linux/QtCreator/part10.htm
第10部份:文件导入
导入XML文件
这里我们可以让用户导入之前保存的XML文件格式的模拟数据。我们新添加一个“打开...”文件菜单,使用QFileDialog功能让用户可以选择要导入的文件,并且使用QXmlStreamWriter读取XML文件内容。
增强MainWindow
我们需要添加一个公共槽接收用户选择这个新的菜单动作的信号。
bool fileOpen(); // 如果成功加载模拟数据返回真
引入QXmlStreamWriter头文件。
#include <QXmlStreamReader>
在构造函数里,在我们先前创建保存动作的下面,创建和添加一个新的打开文件菜单动作。
QAction* openAction = fileMenu->addAction( "&Open ...", this, SLOT(fileOpen()) );
设置键盘快捷键。
openAction->setShortcut( QKeySequence::Open );
现在添加公共槽代码。在这个槽中我们询问用户文件名和文件目录,判断文件是否可读,并且使用QXmlStreamReader来处理文件。如果没有错误,新建一个场景替代旧的场景用来加载模拟数据。首先找到“qsimulate”这个元素。调用新场景的方法来读取其它信息。如果能成功读取XML文件,槽返回真,否则返回假。
/************************************* fileOpen **************************************/ bool MainWindow::fileOpen() { // 用户选择的文件 QString filename = QFileDialog::getOpenFileName(); if ( filename.isEmpty() ) return false; // 打开文件并判断是否可读 QFile file( filename ); if ( !file.open( QIODevice::ReadOnly ) ) { showMessage( QString("Failed to open '%1'").arg(filename) ); return false; } // 打开一个xml读取流加载模拟数据 QXmlStreamReader stream( &file ); Scene* newScene = new Scene( m_undoStack ); while ( !stream.atEnd() ) { stream.readNext(); if ( stream.isStartElement() ) { if ( stream.name() == "qsimulate" ) newScene->readStream( &stream ); else stream.raiseError( QString("Unrecognised element '%1'").arg(stream.name().toString()) ); } } // 判断是否发生错误 if ( stream.hasError() ) { file.close(); showMessage( QString("Failed to load '%1' (%2)").arg(filename).arg(stream.errorString()) ); delete newScene; return false; } // 关闭文件,显示新场景,删除旧场景并显示有用的消息 file.close(); m_undoStack->clear(); QGraphicsView* view = dynamic_cast<QGraphicsView*>( centralWidget() ); view->setScene( newScene ); delete m_scene; m_scene = newScene; showMessage( QString("Loaded '%1'").arg(filename) ); //作者忘记加上这行代码 connect( m_scene, SIGNAL(message(QString)), this, SLOT(showMessageQString)) ); return true; }
增强scene
添加类QXmlStreamReader的前置定义。
class QXmlStreamReader;
添加一个新的公共的场景方法从QXmlStreamReader读取模拟数据。
void readStream( QXmlStreamReader* ); // 从xml流读取数据
引入类QXmlStreamReader头文件。
#include <QXmlStreamReader>
添加我们新场景的方法代码。这个方法根据从XML流中读取到“station”元素创建一个新的场景电台,并且从每个节点元素属性读取到的属性值设置它的x,y坐标。
/************************************ readStream *************************************/ void Scene::readStream( QXmlStreamReader* stream ) { // 从xml流读取数据 while ( !stream->atEnd() ) { stream->readNext(); if ( stream->isStartElement() && stream->name() == "station" ) { qreal x = 0.0, y = 0.0; foreach( QXmlStreamAttribute attribute, stream->attributes() ) { if ( attribute.name() == "x" ) x = attribute.value().toString().toDouble(); if ( attribute.name() == "y" ) y = attribute.value().toString().toDouble(); } addItem( new Station( x, y ) ); } } }
编译与运行
当你尝试运行程序新的代码将自动被编译。测试程序,导入你之前保存的文件。