1 文本编辑器实现打开文件、保存文件、文件另存为、新建文件、软件关闭的功能
在Qt项目我们应该尽量将界面代码与功能代码分离开,所以槽函数单独放在一个文件里,文件名命名为MainWindowSlots。文件目录结构如下:
我们需要解决一个关键问题:如何判断是否存在未保存的数据?
- 我们需要利用QPlainTextEdit中能够触发与编辑操作相关信号的功能。
解决方案如下:
槽函数实现如下:
void MainWindow::onTextChanged()
{
if( !m_isTextChanged )
{
setWindowTitle("*" + windowTitle());
}
m_isTextChanged = true;
}
槽函数声明:
信号与槽的绑定省略,下面只给出关键操作代码。
1.1 打开文件
打开文件操作流程图:
关键代码如下:
#include "MainWindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QDebug>
void MainWindow::showErrorMessage(QString message)
{
QMessageBox msg(this);
msg.setWindowTitle("Error");
msg.setText(message);
msg.setIcon(QMessageBox::Critical);
msg.setStandardButtons(QMessageBox::Ok);
msg.exec();
}
int MainWindow::showQueryMessage(QString message)
{
QMessageBox msg(this);
msg.setWindowTitle("Query");
msg.setText(message);
msg.setIcon(QMessageBox::Question);
msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
return msg.exec();
}
QString MainWindow::showFileDialog(QFileDialog::AcceptMode mode, QString title)
{
QString ret = "";
QFileDialog fd(this);
QStringList filters;
QMap<QString, QString> map;
const char* filterArray[][2] =
{
{"Text Files (*.txt)", ".txt"},
{"All Files (*)", "*" },
{NULL, NULL }
};
for(int i=0; filterArray[i][0]!=NULL; i++)
{
filters.append(filterArray[i][0]);
map.insert(filterArray[i][0], filterArray[i][1]);
}
fd.setWindowTitle(title);
fd.setAcceptMode(mode);
fd.setFilters(filters);
if( mode == QFileDialog::AcceptOpen )
{
fd.setFileMode(QFileDialog::ExistingFile);
}
if( fd.exec() == QFileDialog::Accepted )
{
ret = fd.selectedFiles()[0];
if( mode == QFileDialog::AcceptSave )
{
QString postfix = map[fd.selectedFilter()];
if( (postfix != "*") && !ret.endsWith(postfix) )
{
ret = ret + postfix;
}
}
}
return ret;
}
QString MainWindow::saveCurrentData(QString path)
{
QString ret = path;
if( ret == "" )
{
ret = showFileDialog(QFileDialog::AcceptSave, "Save");
}
if( ret != "" )
{
QFile file(ret);
if( file.open(QIODevice::WriteOnly | QIODevice::Text) )
{
QTextStream out(&file);
out << mainEditor.toPlainText();
file.close();
setWindowTitle("NotePad - [ " + ret + " ]");
m_isTextChanged = false;
}
else
{
showErrorMessage(QString("Save file error! \n\n") + "\"" + ret + "\"");
ret = "";
}
}
return ret;
}
void MainWindow::preEditorChange()
{
if( m_isTextChanged )
{
int r = showQueryMessage("Do you want to save the changes to file?");
switch(r)
{
case QMessageBox::Yes:
saveCurrentData(m_filePath);
break;
case QMessageBox::No:
m_isTextChanged = false;
break;
case QMessageBox::Cancel:
break;
}
}
}
void MainWindow::openFileToEditor(QString path)
{
if( path != "" )
{
QFile file(path);
if( file.open(QIODevice::ReadOnly | QIODevice::Text) )
{
mainEditor.setPlainText(QString(file.readAll()));
file.close();
m_filePath = path;
m_isTextChanged = false;
setWindowTitle("NotePad - [ " + m_filePath + " ]");
}
else
{
showErrorMessage(QString("Open file error! \n\n") + "\"" + path + "\"");
}
}
}
void MainWindow::onFileOpen()
{
preEditorChange();
if( !m_isTextChanged )
{
QString path = showFileDialog(QFileDialog::AcceptOpen, "Open");
openFileToEditor(path);
}
}
1.2 保存文件
保存文件操作流程图:
关键代码如下:
void MainWindow::onFileSave()
{
QString path = saveCurrentData(m_filePath);
if( path != "" )
{
m_filePath = path;
}
}
1.3 文件另存为
文件另存为操作流程图:
关键代码如下:
void MainWindow::onFileSaveAs()
{
QString path = saveCurrentData();
if( path != "" )
{
m_filePath = path;
}
}
1.4 新建文件
新建文件流程图如下:
关键代码如下:
void MainWindow::onFileNew()
{
preEditorChange();
if( !m_isTextChanged )
{
mainEditor.clear();
setWindowTitle("NotePad - [ New ]");
m_filePath = "";
m_isTextChanged = false;
}
}
1.5 软件关闭
流程图如下:
关键代码如下:
void MainWindow::closeEvent(QCloseEvent* e)
{
preEditorChange();
if( !m_isTextChanged )
{
QMainWindow::closeEvent(e);
}
else
{
e->ignore();
}
}
同时我们也把菜单栏的exit选项实现下,具体的槽函数如下:
void MainWindow::onFileExit()
{
close();
}
参考资料: