QMainWindow学习-5
菜单栏有了,工具栏也有了,连用户可以输入的编辑框也有了,接下来当然是给我们这些按钮添加动作,以完成一个记事本的功能。
1.打开文件
首先我们在类中定义一个槽,还记得槽是怎么声明的吗,就是在private slots:下声明一个函数。
private slots:
void loadFile();
然后我们在mainwindow.cpp中实现这个函数,其中我们要用到一个变量,mFileName表示当前文本文件的名字,这里定义成QString类型,还是要在类中定义这个变量。
QString mFileName;
void MainWindow::loadFile()
{
QString fileName = QFileDialog::getOpenFileName(this);
QFile file(fileName);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
textEdit->setPlainText(QString::fromUtf8(file.readAll()));
mFileName = fileName;
statusBar()->showMessage(tr("file load successfully"), 3000);
}
}
Qt中提供了文件打开的对话框类QFileDialog,在这里我们使用了该类的一个静态方法,getOpenFileName,该方法返回打开文件的名字,它是QString类型。
我们看QT文档提供的一个例子
fileName = QFileDialog::getOpenFileName(this,
tr("Open Image"), "/home/jana", tr("Image Files (*.png *.jpg *.bmp)"));
第一个参数为parent指针,第二个参数为对话框窗口标题,第三个参数为打开的目录,第四个参数为用于过滤后缀名,如果要使用多个过滤器,使用;;分割,如
"Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
QFileDialog类扩展
QFileDialog类继承QDialog,它还提供了几种静态方法,getSaveFileName和getExistingDirectory,其中一个我们后面会遇到。
对于打开文件,QT中使用的是QFile类,该类的方法有点类似于C中的文件指针
QFile中的open方法用于打开一个文件,我们这里是只读方式打开一个文本文件
然后调用readAll方法将这个文本文件类容读到编辑框中。
保存文本文件的名字,同时在状态栏显示一条消息 file load successfully,注意后面还有一个时间,表示只显示3秒,3秒过后自动消失
还有一点,我们定义的QAction,如果我们用鼠标点击一下这个action,将会发出triggered()信号,那我们加这个信号和上面写的槽连接起来,在构造函数做就可以了。
connect(openAct, SIGNAL(triggered()), this, SLOT(loadFile()));
这样我们就完成了打开操作了。
2.保存文件
同样的道理我们写保存文件操作,在类中定义槽,写上连接,然后写具体的函数
bool MainWindow::saveFile()
{
if (mFileName.isEmpty()) {
return saveFileAs();
} else {
return saveFile(mFileName);
}
}
这里我们先做了处理,判断这个mFileName是否为空,如果为空说明是我们刚刚新建的文件,那么调用saveFileAs去另存为一个文本文件,如果不为空,说明已经有了这个名字的文本文件,那么直接做保存操作就好了。
bool MainWindow::saveFile(const QString &name)
{
QFile file(name);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
file.write(textEdit->toPlainText().toUtf8());
textEdit->document()->setModified(false);
statusBar()->showMessage(tr("save file successfully"), 3000);
return true;
}
}
我们还是调用QFile这个类的open函数以只写的方式打开这个文件,然后调用它的write将编辑框所有类容写入这个文本文件中,在状态栏显示save file successfully,同样还是3秒。这里还做了一个处理,那就是既然已经保存了,那么我们将这个编辑框的修改状态标志设置成false,表示编辑框没有被修改。
说到这里,还要额外的说一点,我们点击了保存按钮,文本文件已经做了保存,那么这个按钮就应该变成灰色的,即处于不能点击状态,所以我们还要添加一些信号的连接
saveAct->setEnabled(textEdit->document()->isModified());
connect(textEdit->document(), SIGNAL(modificationChanged(bool)), saveAct, SLOT(setEnabled(bool)));
这里我们首先是将保存这个按钮的可见状态设置成文本是否被修改的状态,刚开始肯定是false,后一句表示如果文本被修改了,那么立马设置这个按钮的可见状态,也就是可以保存了。
然后是saveFileAs
bool MainWindow::saveFileAs()
{
mFileName = QFileDialog::getSaveFileName(this);
if (mFileName.isEmpty()) {
return false;
} else {
if (QFileInfo(mFileName).suffix().isEmpty()) {
mFilePath.append(".txt");
}
}
return saveFile(mFileName);
}
这个就是另存为,同打开一样,调用 QfileDialog去获取一个名字,用户可能没有输入后缀名,那么我们为它添上,然后再保存。
3新建文件。
定义槽,写上连接
然后是函数
void MainWindow::newFile()
{
if (mayDiscardDocument()) {
textEdit->setPlainText("");
mFileName = "";
}
}
先调用mayDiscardDocument()这个函数去判断是否丢掉当前的文本,如果可以丢掉,那么我们就这个编辑框置成空,名字也为空,表示一个新的编辑框出来了。
bool MainWindow::mayDiscardDocument()
{
if (textEdit->document()->isModified()) {
QString fileName = mFileName;
if (fileName.isEmpty()) {
fileName = tr("unnamed");
}
QMessageBox::StandardButton ret;
ret = QMessageBox::warning(this, tr("save document?"),
tr("The document has been modified.\n"
"Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard |
QMessageBox::Cancel);
if (ret == QMessageBox::Save) {
return saveFile();
} else if (ret == QMessageBox::Cancel) {
return false;
}
}
return true;
}
先判断这个文本是否被修改了,如果没有被修改,那么可以丢掉,直接返回true,如果修改了,那么再调用QMessageBox弹出一个对话框,提示用户是保存,还是丢掉,还是取消这次操作。如果是保存,那么调用saveFile去保存文本好了。如果是丢掉,那既然你多选择了丢掉,那我也只有丢掉了,返回true。如果用户取消了,也许是用户点错了,那么原路返回,什么也不做。
QmessageBox扩展
warning函数原形
StandardButton warning(QWidget *parent, const Qstring &title, const Qstring &text, StandardButton buttons = Ok, StandardButton defaultButton = NoButton)
其中defaultButton代表默认时选择按钮,这个方法有个返回值,代表我们点击的是哪个按钮,我们可以根据这个按钮做相应的处理
它是QMessageBox类的一个静态方法,
QMessageBox类继承QDialog类,它是一种modal dialog,QMessageBox类提供了好几种类似于warning方法,其他的还有about, question, information, critical等
关闭事件
当用户点击退出按钮时,将会调用QWidget::close槽,该槽会给这个窗口发送一个close事件,我们可以重载closeEvent函数,给用户以提示,是否要保存当前已被修改的文本。
virtual void closeEvent(QCloseEvent *e);
void MainWindow::closeEvent(QCloseEvent *e)
{
if (mayDiscardDocument()) {
e->accept();
} else {
e->ignore();
}
}
还是调用mayDiscardDocument()函数去判断是否丢掉当前的文本,然后再做处理。
关于对话框
最后一个关于对话框,定义槽,加上连接,当用户点击Help菜单中的about按钮时弹出一个消息框,显示软件版本等等信息。
void MainWindow::about()
{
QMessageBox::about(this, tr("about"),
tr("text edit 1.0\n"
"2011 ChengDu"));
}
好,现在我们的软件基本功能都有了。
1.打开文件
首先我们在类中定义一个槽,还记得槽是怎么声明的吗,就是在private slots:下声明一个函数。
private slots:
void loadFile();
然后我们在mainwindow.cpp中实现这个函数,其中我们要用到一个变量,mFileName表示当前文本文件的名字,这里定义成QString类型,还是要在类中定义这个变量。
QString mFileName;
void MainWindow::loadFile()
{
QString fileName = QFileDialog::getOpenFileName(this);
QFile file(fileName);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
textEdit->setPlainText(QString::fromUtf8(file.readAll()));
mFileName = fileName;
statusBar()->showMessage(tr("file load successfully"), 3000);
}
}
Qt中提供了文件打开的对话框类QFileDialog,在这里我们使用了该类的一个静态方法,getOpenFileName,该方法返回打开文件的名字,它是QString类型。
我们看QT文档提供的一个例子
fileName = QFileDialog::getOpenFileName(this,
tr("Open Image"), "/home/jana", tr("Image Files (*.png *.jpg *.bmp)"));
第一个参数为parent指针,第二个参数为对话框窗口标题,第三个参数为打开的目录,第四个参数为用于过滤后缀名,如果要使用多个过滤器,使用;;分割,如
"Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
QFileDialog类扩展
QFileDialog类继承QDialog,它还提供了几种静态方法,getSaveFileName和getExistingDirectory,其中一个我们后面会遇到。
对于打开文件,QT中使用的是QFile类,该类的方法有点类似于C中的文件指针
QFile中的open方法用于打开一个文件,我们这里是只读方式打开一个文本文件
然后调用readAll方法将这个文本文件类容读到编辑框中。
保存文本文件的名字,同时在状态栏显示一条消息 file load successfully,注意后面还有一个时间,表示只显示3秒,3秒过后自动消失
还有一点,我们定义的QAction,如果我们用鼠标点击一下这个action,将会发出triggered()信号,那我们加这个信号和上面写的槽连接起来,在构造函数做就可以了。
connect(openAct, SIGNAL(triggered()), this, SLOT(loadFile()));
这样我们就完成了打开操作了。
2.保存文件
同样的道理我们写保存文件操作,在类中定义槽,写上连接,然后写具体的函数
bool MainWindow::saveFile()
{
if (mFileName.isEmpty()) {
return saveFileAs();
} else {
return saveFile(mFileName);
}
}
这里我们先做了处理,判断这个mFileName是否为空,如果为空说明是我们刚刚新建的文件,那么调用saveFileAs去另存为一个文本文件,如果不为空,说明已经有了这个名字的文本文件,那么直接做保存操作就好了。
bool MainWindow::saveFile(const QString &name)
{
QFile file(name);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
file.write(textEdit->toPlainText().toUtf8());
textEdit->document()->setModified(false);
statusBar()->showMessage(tr("save file successfully"), 3000);
return true;
}
}
我们还是调用QFile这个类的open函数以只写的方式打开这个文件,然后调用它的write将编辑框所有类容写入这个文本文件中,在状态栏显示save file successfully,同样还是3秒。这里还做了一个处理,那就是既然已经保存了,那么我们将这个编辑框的修改状态标志设置成false,表示编辑框没有被修改。
说到这里,还要额外的说一点,我们点击了保存按钮,文本文件已经做了保存,那么这个按钮就应该变成灰色的,即处于不能点击状态,所以我们还要添加一些信号的连接
saveAct->setEnabled(textEdit->document()->isModified());
connect(textEdit->document(), SIGNAL(modificationChanged(bool)), saveAct, SLOT(setEnabled(bool)));
这里我们首先是将保存这个按钮的可见状态设置成文本是否被修改的状态,刚开始肯定是false,后一句表示如果文本被修改了,那么立马设置这个按钮的可见状态,也就是可以保存了。
然后是saveFileAs
bool MainWindow::saveFileAs()
{
mFileName = QFileDialog::getSaveFileName(this);
if (mFileName.isEmpty()) {
return false;
} else {
if (QFileInfo(mFileName).suffix().isEmpty()) {
mFilePath.append(".txt");
}
}
return saveFile(mFileName);
}
这个就是另存为,同打开一样,调用 QfileDialog去获取一个名字,用户可能没有输入后缀名,那么我们为它添上,然后再保存。
3新建文件。
定义槽,写上连接
然后是函数
void MainWindow::newFile()
{
if (mayDiscardDocument()) {
textEdit->setPlainText("");
mFileName = "";
}
}
先调用mayDiscardDocument()这个函数去判断是否丢掉当前的文本,如果可以丢掉,那么我们就这个编辑框置成空,名字也为空,表示一个新的编辑框出来了。
bool MainWindow::mayDiscardDocument()
{
if (textEdit->document()->isModified()) {
QString fileName = mFileName;
if (fileName.isEmpty()) {
fileName = tr("unnamed");
}
QMessageBox::StandardButton ret;
ret = QMessageBox::warning(this, tr("save document?"),
tr("The document has been modified.\n"
"Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard |
QMessageBox::Cancel);
if (ret == QMessageBox::Save) {
return saveFile();
} else if (ret == QMessageBox::Cancel) {
return false;
}
}
return true;
}
先判断这个文本是否被修改了,如果没有被修改,那么可以丢掉,直接返回true,如果修改了,那么再调用QMessageBox弹出一个对话框,提示用户是保存,还是丢掉,还是取消这次操作。如果是保存,那么调用saveFile去保存文本好了。如果是丢掉,那既然你多选择了丢掉,那我也只有丢掉了,返回true。如果用户取消了,也许是用户点错了,那么原路返回,什么也不做。
QmessageBox扩展
warning函数原形
StandardButton warning(QWidget *parent, const Qstring &title, const Qstring &text, StandardButton buttons = Ok, StandardButton defaultButton = NoButton)
其中defaultButton代表默认时选择按钮,这个方法有个返回值,代表我们点击的是哪个按钮,我们可以根据这个按钮做相应的处理
它是QMessageBox类的一个静态方法,
QMessageBox类继承QDialog类,它是一种modal dialog,QMessageBox类提供了好几种类似于warning方法,其他的还有about, question, information, critical等
关闭事件
当用户点击退出按钮时,将会调用QWidget::close槽,该槽会给这个窗口发送一个close事件,我们可以重载closeEvent函数,给用户以提示,是否要保存当前已被修改的文本。
virtual void closeEvent(QCloseEvent *e);
void MainWindow::closeEvent(QCloseEvent *e)
{
if (mayDiscardDocument()) {
e->accept();
} else {
e->ignore();
}
}
还是调用mayDiscardDocument()函数去判断是否丢掉当前的文本,然后再做处理。
关于对话框
最后一个关于对话框,定义槽,加上连接,当用户点击Help菜单中的about按钮时弹出一个消息框,显示软件版本等等信息。
void MainWindow::about()
{
QMessageBox::about(this, tr("about"),
tr("text edit 1.0\n"
"2011 ChengDu"));
}
好,现在我们的软件基本功能都有了。