原文地址: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 ) );
}
}
}
编译与运行
当你尝试运行程序新的代码将自动被编译。测试程序,导入你之前保存的文件。