QT文本编辑器———第二弹
一、实现文件菜单
文件
新建(&N)
打开(&O)
保存(&S)
另存为(&A)…
退出
二、效果演示
file_open...
三、代码
1.mainwindow.cpp
#include <QFile>//对文件操作
#include <QFont>
#include <QMessageBox>
#include <QTextEdit>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
/**************^_^丛林溪流^_^***************/
this->setMaximumSize(1000,800);
this->setMinimumSize(700,600);
this->setWindowTitle("文本编辑器");
this->setWindowIcon(QIcon(":/images/bear"));
//this->setIconSize(QSize(50,50));//可以改变工具栏图标大小
//1.设置中央布局组件
textEdit = new QTextEdit(this);
this->setCentralWidget(textEdit);
//2.mainwindow添加状态栏
statusBar = new QStatusBar(this);
this->setStatusBar(statusBar);
//label添加到状态栏的左侧
label = new QLabel(this);
statusBar->addWidget(label);
//文本框内容改动后在文件名前显示*号
connect(textEdit,&QTextEdit::textChanged,[&](){
if(!label->text().contains('*'))
label->setText(label->text()+'*');
});
//lineColumnLabel添加到状态栏的右侧
lineColumnLabel = new QLabel(this);
lineColumnLabel->setText("Ln:0 Col:0\t");
statusBar->addPermanentWidget(lineColumnLabel);
//3.添加滚动条
textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);//设置垂直滚动条,属性设置为当在需要的时候显示
// textEdit->setHorizontalScrollBarPolicy(Qt::ScrollB会arAsNeeded);
//注意要点:在设置水平滚动条的时候碰到一个bug,因为setCentralWidget(textEdit)会内容自适应,和状态栏之间没有空隙给水平滚动条。
//因此若用ui设计的中央布局组件,要留出一点位置给水平滚动条,不然无法显示。若用代码实现的,可以用以下另一种方式。
textEdit->setLineWrapMode(QTextEdit::NoWrap);
}
注意要点1:这里在设置水平滚动条时,出现了bug。
垂直滚动条可以这样设置,但水平滚动条不能。
textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);//设置垂直滚动条,属性设置为当在需要的时候显示
//textEdit->setHorizontalScrollBarPolicy(Qt::ScrollB会arAsNeeded);
原因我分析的是,因为设置中央布局组件时setCentralWidget(textEdit)会内容自适应,导致textEdit和状态栏之间没有空隙给水平滚动条。所以水平滚动条用了另一种方式。
注意要点2:文本框内容改动后在文件名前显示*号,这里是模仿了记事本对改动过的文本的操作。
1.新建
注意要点:新建前如果有未保存的文本,应该有保存提示。若文本已经被保存,新建时会直接清空textEdit。最后一步清空textEdit,清空label。
void MainWindow::on_actionnew_triggered()//新建 新建前有文本,保存提示。若文本已经被保存,新建时会直接清空
{
qDebug() << "newfile";
//1、有‘*’,提醒用户是否保存文件
int ret;
if(label->text().contains('*')){
ret = QMessageBox::warning(this, "注意", "是否保存文件", "是", "否");//获取返回值 0保存 1不保存
qDebug() << ret;
}
if(ret == 0)//保存
{
MainWindow::on_actionsave_File_S_triggered();
}
else
//2、清空textEdit,清空label
textEdit->clear();
label->clear();
}
2.打开
注意要点:打开文本前如果有未保存的文本,应该有保存提示,若文本已经被保存,打开时会直接清空textEidt。无论点击保存or不保存,之后一步都应该清空textEdit,清空label,为打开新文件做准备。
void MainWindow::on_actionopen_triggered()//打开 打开前有未保存的文本,保存提示。打开前若文本已经被保存,打开时会直接清空
{
qDebug() << "openfile";
//1、打开前有未保存的文本,有‘*’,提醒用户是否保存文件
int ret;
if(label->text().contains('*')){
ret = QMessageBox::warning(this, "注意", "是否保存文件", "是", "否");//获取返回值 0保存 1不保存
qDebug() << ret;
}
if(ret == 0)//保存
{
MainWindow::on_actionsave_File_S_triggered();
}
else
//2、清空textEdit,清空label
textEdit->clear();
label->clear();
//1. 弹出文件选择对话框
QString filename = QFileDialog::getOpenFileName(this, "打开文本文件", "C:\\Users\\admin\\Desktop\\conglinxiliu", "txt (*.txt)");
if(filename.isEmpty())//没有打开文件的操作
return;
//2. 读出文件内容到buf
QFile f(filename);
f.open(QIODevice::ReadOnly);
QByteArray buf = f.readAll();
f.close();
//3. 显示在te
textEdit->setText(buf);
//4. 显示文件名到状态来
label->setText(filename);
}
3.保存
注意要点:保存和另存为的区别;首先判断文本有没有被编辑。1.有被编辑(即标签含星号)且打开的文本有路径,点击保存默认保存在原路径 2.有被编辑但文本没有路径,点击保存弹出文件保存对话框,可以选择保存路径 3.文本未被修改时(即标签不含*),点击保存没有作用 4.最后一步都要清空标签的星号。
void MainWindow::on_actionsave_File_S_triggered()//保存 保存和另存为功能
{
qDebug() << "savefile";
//1.文本没有被编辑
if(!label->text().contains('*'))//标签没有含‘*’
return;
//2.文本被编辑
if(label->text().contains('*')){//标签含‘*’
QString fileName = label->text();
fileName.chop(1);//去掉标签的最后一个字符‘*’,以便保存时,文件名不显示‘*’
if(fileName.isEmpty())
fileName = QFileDialog::getSaveFileName(this,"保存文件","C:\\Users\\admin\\Desktop\\conglinxiliu","文本文档(*.txt);;word文档(*.doc)");//直接点保存为默认路径
QFile f(fileName);//内容保存到路径文件
f.open(QIODevice::WriteOnly);
f.write(textEdit->toPlainText().toStdString().c_str());
f.close();
//3.消除标签的‘*’
label->setText(fileName);
}
}
4.另存为
注意要点:保存和另存为的区别;另存为百度解释,可以将打开的文件(不论有没修改过)保存到硬盘的任意一处,可存为任意名称,而不影响你目前打开的原文件。所以,另存为的判断条件和保存不同,不应该根据文本是否被编辑来判断,而是文件名不为空。最后一步依然要清除标签的星号。
void MainWindow::on_action_SaveAs_triggered()//另存为
//可以将打开的文件(不论有没修改过)保存到硬盘的任意一处,可存为任意名称,而不影响你目前打开的原文件
{
qDebug() << "saveas_file";
QString fileName = label->text();
if(!fileName.isEmpty())
fileName = QFileDialog::getSaveFileName(this,"保存文件","C:\\Users\\admin\\Desktop\\conglinxiliu","文本文档(*.txt);;word文档(*.doc)");//直接点保存为默认路径
QFile f(fileName);//内容保存到路径文件
f.open(QIODevice::WriteOnly);
f.write(textEdit->toPlainText().toStdString().c_str());
f.close();
//消除标签的‘*’
label->setText(fileName);
}
5.退出
注意要点:退出时,判断文本是否被保存(即标签是否有星号)。1.文本保存过,点击退出直接退出整个文本编辑器;2.文本未被保存,提醒用户保存文件,点击保存调保存函数即可,不保存时退出整个文本编辑器。
void MainWindow::on_action_exit_triggered()//退出
{
qDebug() << "closefile";
//1.检测状态栏有‘*’号,弹出消息提示对话框,提醒用户保存文件
int ret;
if(label->text().contains('*'))
ret = QMessageBox::information(this,"提示","是否保存文件","是","否");//用ret去接收返回值,0保存,1不保存
if(ret == 0)
{
MainWindow::on_actionsave_File_S_triggered();//调保存函数
}
else
this->close();//关闭窗体,不保存时退出整个文本编辑器
}
2.mainwindow.h
private slots://槽函数
void on_actionopen_triggered();
void on_actionnew_triggered();
void on_actionsave_File_S_triggered();
void on_action_exit_triggered();
void on_action_SaveAs_triggered();
private:
Ui::MainWindow *ui;
QTextEdit *textEdit;
QLabel *label,*lineColumnLabel;//状态栏的左标签、右标签,分别显示文件路径和光标定位第几行第几列
QStatusBar *statusBar;
四、反思总结
五个子菜单的功能没有想象中的复杂,主要是逻辑以及分析每个子菜单的判断条件,其中”打开“这个子菜单功能分析要稍微复杂一些,但仔细发现其实就是步骤多了一点,判断星号这段代码,几个子菜单都可以共用。
注意要点做了详细阐述,代码中也写了注释,这也是博主在写代码时遇到的一些问题。
后续内容还会陆续更新哟~