原文网址:http://www.dazzle.plus.com/linux/QtCreator/part12.htm
第12部份:新建和退出
添加两个新的文件菜单项和一个工具栏
在这一部份,我们将添加两个文件菜单项,一个用于启动新的模拟场景,另一个是退出应用程序。为了帮肋用户防止丢失他们的操作数据,这两个菜单项在操作前提供机会让用户去保存他们先前的操作数据。我们还将添加一个工具栏可以直接访问主文件菜单项。
实现这些改变,我们只需要修改类MainWindow的代码。我们将使用QToolBar实现工具条,节省我们自己设计和绘制图标的工作,我们会使用由QStyle提供标准的像素图。
增强类MainWindow
添加一个公共的槽方法接收信号当用户启动一个新的模拟场景。
void fileNew(); // 启动一个新的模拟场景
重写QMainWindow的虚保护方法closeEvent,当程序收到退出请求时,需要程序做的事
protected:
void closeEvent( QCloseEvent* ); // 判断用户是否要退出
引入QCloseEvent,QMessageBox,QToolBar类的头文件。
#include <QCloseEvent>
#include <QMessageBox>
#include <QToolBar>
构造函数里,在打开和保存的文件菜单项上面添加一个用于启动模拟场景的动作。
QAction* newAction = fileMenu->addAction( "&New", this, SLOT(fileNew()) );
在打印和打印预览文件菜单项下面,我们新增一条分隔符和退出应用程序菜单项。这个退出动作会调用QMainWindow的槽方法close。我们也要为启动一新的模拟场景设置键盘快捷键。
fileMenu->addSeparator();
fileMenu->addAction( "&Quit",this, SLOT(close()) );
newAction->setShortcut( QKeySequence::New );
构造函数里,在我们创建的undo堆栈后面创建工具条并且填充它。正如前面提到的,为了节省我们的时间和精力,我们使用一些标准的像素图创建图标。由于QStyle的像素图大小是不同的,我们用一个较小的标准像素图设置工具栏,并在这个尺寸显示所有图标。
// 创建工具条, 设置图标大小,添加动作
QToolBar* toolBar = addToolBar( "Standard" );
QStyle* style = this->style();
QSize size = style->standardIcon(QStyle::SP_DesktopIcon).actualSize( QSize(99,99) );
toolBar->setIconSize( size );
newAction->setIcon( style->standardIcon(QStyle::SP_DesktopIcon) );
openAction->setIcon( style->standardIcon(QStyle::SP_DialogOpenButton) );
saveAction->setIcon( style->standardIcon(QStyle::SP_DialogSaveButton) );
previewAction->setIcon( style->standardIcon(QStyle::SP_FileDialogContentsView) );
printAction->setIcon( style->standardIcon(QStyle::SP_ComputerIcon) );
undoAction->setIcon( style->standardIcon(QStyle::SP_ArrowBack) );
redoAction->setIcon( style->standardIcon(QStyle::SP_ArrowForward) );
toolBar->addAction( newAction );
toolBar->addAction( openAction );
toolBar->addAction( saveAction );
toolBar->addSeparator();
toolBar->addAction( previewAction );
toolBar->addAction( printAction );
toolBar->addSeparator();
toolBar->addAction( undoAction );
toolBar->addAction( redoAction );
现在我们添加启动一个新模拟场景的代码。如果旧的模拟场景没有操作数据,我们直接启动。否则使用QMessageBox,在创建一个新的空白的场景之前给用户有机会保存他们之前的操作数据。
/************************************** fileNew **************************************/
void MainWindow::fileNew()
{
// 如果没有操作数据(只有默认的左上角场景),直接返回
if ( m_scene->items().count() <= 1 ) return;
// 判断在启动新模拟场景前,用户是否想要保存
while (true)
switch ( QMessageBox::warning( this, "QSimulate",
"Do you want to save before starting new?",
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel ) )
{
case QMessageBox::Save:
// 保存失败,再次询问
if ( !fileSaveAs() ) break;
case QMessageBox::Discard:
// 启动新模拟场景
{
m_undoStack->clear();
Scene* newScene = new Scene( m_undoStack );
QGraphicsView* view = dynamic_cast<QGraphicsView*>( centralWidget() );
view->setScene( newScene );
delete m_scene;
m_scene = newScene;
}
return;
default: // "取消"
return;
}
}
我们还将添加重写类QMainWindow的虚拟函数“closeEvent”类似的代码。如果旧的模拟场景没有操作数据,我们直接退出。否则使用QMessageBox,在退出程序之前给用户有机会保存他们之前的操作数据。
/************************************ closeEvent *************************************/
void MainWindow::closeEvent( QCloseEvent* event )
{
// 如果没有操作数据(只有默认的左上角场景),接受退出
if ( m_scene->items().count() <= 1 )
{
event->accept();
return;
}
// 判断在退出前,用户是否想要保存
while (true)
switch ( QMessageBox::warning( this, "QSimulate",
"Do you want to save before you quit?",
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel ) )
{
case QMessageBox::Save:
// 保存失败,再次询问
if ( !fileSaveAs() ) break;
case QMessageBox::Discard:
event->accept();
return;
default: // "取消"
event->ignore();
return;
}
}
编译与运行
当你尝试运行程序新的代码将自动被编译。测试程序,检测新功能。