Qt: 多文档应用程序源码解析及下载

时间:2021-07-17 17:18:58

如果有代码看不懂,可以留言,我会回复大家的留言(Qt、C++纯技术交流群:302558294)

效果图如下:

Qt: 多文档应用程序源码解析及下载


项目结构:

Qt: 多文档应用程序源码解析及下载


程序主要功能:

1、新建文本文件。

2、多文档编辑文本文件。

3、打开已有文件。

4、文件另存为。


解析:

1、 Editor 类继承自 QTextEdit,主要用于文本编辑和处理功能。

2、MainWindow继承自QMainWindow,主要用于创建主界面,界面布局等功能。


源码:

//main.cpp

#include <QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

MainWindow mainWin; //创建一个程序实例
mainWin.show();

return app.exec();
}

//Editor.h

#ifndef EDITOR_H
#define EDITOR_H

#include <QTextEdit>

class Editor : public QTextEdit
{
Q_OBJECT

public:
Editor(QWidget *parent = 0);

void newFile(); //新建文件
bool save(); //文件保存
bool saveAs(); //文件另存为
QSize sizeHint() const; //获取窗口的推荐大小
QAction *windowMenuAction() const { return action; }

static Editor *open(QWidget *parent = 0); //打开窗口
static Editor *openFile(const QString &fileName, QWidget *parent = 0); //打开文件

protected:
void closeEvent(QCloseEvent *event); //关闭事件,在程序关闭之前执行此函数

private slots:
void documentWasModified(); //设置窗口显示状态,修改和未修改两种

private:
bool okToContinue();
bool saveFile(const QString &fileName); //保存文件
void setCurrentFile(const QString &fileName); //设置当前文件
bool readFile(const QString &fileName); //读文件
bool writeFile(const QString &fileName); //写文件
QString strippedName(const QString &fullFileName); //从文件路径中剥取文件名

QString curFile;
bool isUntitled;
QAction *action;
};

#endif

//Editor.cpp

#include <QApplication>
#include <QtGui>
#include <QAction>
#include <QMessageBox>
#include <QFileDialog>
#include "editor.h"

Editor::Editor(QWidget *parent)
: QTextEdit(parent)
{
action = new QAction(this);
action->setCheckable(true);
connect(action, SIGNAL(triggered()), this, SLOT(show()));
connect(action, SIGNAL(triggered()), this, SLOT(setFocus()));

isUntitled = true; //记录文件是否已经存在

connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); //文档内容发生改变时,触发槽

setWindowIcon(QPixmap(":/images/document.png")); //设置子窗口图标
setWindowTitle("[*]");
setAttribute(Qt::WA_DeleteOnClose); //窗口关闭的时候删除
}

void Editor::newFile()
{
static int documentNumber = 1; //记录打开子窗口的个数

curFile = tr("document%1.txt").arg(documentNumber);
setWindowTitle(curFile + "[*]");
action->setText(curFile);
isUntitled = true;
++documentNumber;
}

bool Editor::save()
{
if (isUntitled)
return saveAs();
else
return saveFile(curFile);
}

bool Editor::saveAs()
{
QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile);
if (fileName.isEmpty())
return false;

return saveFile(fileName);
}

QSize Editor::sizeHint() const
{
return QSize(72 * fontMetrics().width('x'), 25 * fontMetrics().lineSpacing());
}

Editor *Editor::open(QWidget *parent) //弹出“打开”打开窗口,获取路径和文件名
{
QString fileName = QFileDialog::getOpenFileName(parent, tr("Open"), ".");
if (fileName.isEmpty())
return 0;

return openFile(fileName, parent);
}

Editor *Editor::openFile(const QString &fileName, QWidget *parent)
{
Editor *editor = new Editor(parent);
if (editor->readFile(fileName))
{
editor->setCurrentFile(fileName);
return editor;
}
else
{
delete editor;
return 0;
}
}

void Editor::closeEvent(QCloseEvent *event) //关闭事件发生时
{
if (okToContinue())
event->accept(); //接受关闭事件
else
event->ignore(); //忽视关闭事件
}

void Editor::documentWasModified() //设置窗口为被修改状态
{
setWindowModified(true);
}

bool Editor::okToContinue() //是否继续
{
if (document()->isModified()) //判断文件是否被修改
{
int r = QMessageBox::warning(this, tr("MDI Editor"),
tr("File %1 has been modified.\n" "Do you want to save your changes?")
.arg(strippedName(curFile)),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
if (r == QMessageBox::Yes)
{
return save();
}
else if (r == QMessageBox::Cancel)
{
return false;
}
}
return true;
}

bool Editor::saveFile(const QString &fileName) //保存文件
{
if (writeFile(fileName))
{
setCurrentFile(fileName);
return true;
}
else
{
return false;
}
}

void Editor::setCurrentFile(const QString &fileName) //设置当前文件
{
curFile = fileName;
isUntitled = false;
action->setText(strippedName(curFile));
document()->setModified(false);
setWindowTitle(strippedName(curFile) + "[*]");
setWindowModified(false);
}

bool Editor::readFile(const QString &fileName) //读文件
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
QMessageBox::warning(this, tr("MDI Editor"),
tr("Cannot read file %1:\n%2.")
.arg(file.fileName())
.arg(file.errorString()));
return false;
}

QTextStream in(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
setPlainText(in.readAll());
QApplication::restoreOverrideCursor();
return true;
}

bool Editor::writeFile(const QString &fileName) //写文件
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
QMessageBox::warning(this, tr("MDI Editor"),
tr("Cannot write file %1:\n%2.")
.arg(file.fileName())
.arg(file.errorString()));
return false;
}

QTextStream out(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
out << toPlainText();
QApplication::restoreOverrideCursor();
return true;
}

QString Editor::strippedName(const QString &fullFileName) //从路径中剥离文件名
{
return QFileInfo(fullFileName).fileName();
}

//mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class QAction;
class QActionGroup;
class QLabel;
class QMdiArea;
class QMenu;
class QToolBar;
class Editor;

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow();

public slots:
void newFile();
void openFile(const QString &fileName);

protected:
void closeEvent(QCloseEvent *event);

private slots:
void open();
void save();
void saveAs();
void cut();
void copy();
void paste();
void about();
void updateActions();
void loadFiles();

private:
void createActions();
void createMenus();
void createToolBars();
void createStatusBar();
void addEditor(Editor *editor);
Editor *activeEditor();

QMdiArea *mdiArea;
QLabel *readyLabel;
QWidgetList windows;

QMenu *fileMenu;
QMenu *editMenu;
QMenu *windowMenu;
QMenu *helpMenu;
QToolBar *fileToolBar;
QToolBar *editToolBar;
QActionGroup *windowActionGroup;
QAction *newAction;
QAction *openAction;
QAction *saveAction;
QAction *saveAsAction;
QAction *exitAction;
QAction *cutAction;
QAction *copyAction;
QAction *pasteAction;
QAction *closeAction;
QAction *closeAllAction;
QAction *tileAction;
QAction *cascadeAction;
QAction *nextAction;
QAction *previousAction;
QAction *separatorAction;
QAction *aboutAction;
QAction *aboutQtAction;
};

#endif

//mainwindow.cpp

#include <QToolBar>
#include <QLabel>
#include <QtGui>
#include <QMdiArea>
#include <QApplication>
#include <QMessageBox>
#include <QAction>
#include <QMenuBar>
#include <QStatusBar>
#include <QMdiSubWindow>
#include "editor.h"
#include "mainwindow.h"

MainWindow::MainWindow()
{
mdiArea = new QMdiArea;
setCentralWidget(mdiArea);
connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)),this, SLOT(updateActions()));

createActions();
createMenus();
createToolBars();
createStatusBar();

setWindowIcon(QPixmap(":/images/icon.png"));
setWindowTitle(tr("MDI Editor"));
QTimer::singleShot(0, this, SLOT(loadFiles()));
}

void MainWindow::loadFiles()
{
QStringList args = QApplication::arguments();
args.removeFirst();
if (!args.isEmpty())
{
foreach (QString arg, args)
openFile(arg);
mdiArea->cascadeSubWindows();
}
else
{
newFile();
}
mdiArea->activateNextSubWindow();
}

void MainWindow::newFile()
{
Editor *editor = new Editor;
editor->newFile();
addEditor(editor);
}

void MainWindow::openFile(const QString &fileName)
{
Editor *editor = Editor::openFile(fileName, this);
if (editor)
addEditor(editor);
}

void MainWindow::closeEvent(QCloseEvent *event)
{
mdiArea->closeAllSubWindows();
if (!mdiArea->subWindowList().isEmpty())
{
event->ignore();
}
else
{
event->accept();
}
}

void MainWindow::open()
{
Editor *editor = Editor::open(this);
if (editor)
addEditor(editor);
}

void MainWindow::save()
{
if (activeEditor())
activeEditor()->save();
}

void MainWindow::saveAs()
{
if (activeEditor())
activeEditor()->saveAs();
}

void MainWindow::cut()
{
if (activeEditor())
activeEditor()->cut();
}

void MainWindow::copy()
{
if (activeEditor())
activeEditor()->copy();
}

void MainWindow::paste()
{
if (activeEditor())
activeEditor()->paste();
}

void MainWindow::about()
{
QMessageBox::about(this, tr("About MDI Editor"),
tr("<h2>Editor 1.1</h2>"
"<p>Copyright &copy; 2007 Software Inc."
"<p>MDI Editor is a small application that demonstrates "
"QMdiArea."));
}

void MainWindow::updateActions()
{
bool hasEditor = (activeEditor() != 0);
bool hasSelection = activeEditor() && activeEditor()->textCursor().hasSelection();

saveAction->setEnabled(hasEditor);
saveAsAction->setEnabled(hasEditor);
cutAction->setEnabled(hasSelection);
copyAction->setEnabled(hasSelection);
pasteAction->setEnabled(hasEditor);
closeAction->setEnabled(hasEditor);
closeAllAction->setEnabled(hasEditor);
tileAction->setEnabled(hasEditor);
cascadeAction->setEnabled(hasEditor);
nextAction->setEnabled(hasEditor);
previousAction->setEnabled(hasEditor);
separatorAction->setVisible(hasEditor);

if (activeEditor())
activeEditor()->windowMenuAction()->setChecked(true);
}

void MainWindow::createActions()
{
newAction = new QAction(tr("&New"), this);
newAction->setIcon(QIcon(":/images/new.png"));
newAction->setShortcut(QKeySequence::New);
newAction->setStatusTip(tr("Create a new file"));
connect(newAction, SIGNAL(triggered()), this, SLOT(newFile()));

openAction = new QAction(tr("&Open..."), this);
openAction->setIcon(QIcon(":/images/open.png"));
openAction->setShortcut(QKeySequence::Open);
openAction->setStatusTip(tr("Open an existing file"));
connect(openAction, SIGNAL(triggered()), this, SLOT(open()));

saveAction = new QAction(tr("&Save"), this);
saveAction->setIcon(QIcon(":/images/save.png"));
saveAction->setShortcut(QKeySequence::Save);
saveAction->setStatusTip(tr("Save the file to disk"));
connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));

saveAsAction = new QAction(tr("Save &As..."), this);
saveAsAction->setStatusTip(tr("Save the file under a new name"));
connect(saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs()));

exitAction = new QAction(tr("E&xit"), this);
exitAction->setShortcut(tr("Ctrl+Q"));
exitAction->setStatusTip(tr("Exit the application"));
connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));

cutAction = new QAction(tr("Cu&t"), this);
cutAction->setIcon(QIcon(":/images/cut.png"));
cutAction->setShortcut(QKeySequence::Cut);
cutAction->setStatusTip(tr("Cut the current selection to the "
"clipboard"));
connect(cutAction, SIGNAL(triggered()), this, SLOT(cut()));

copyAction = new QAction(tr("&Copy"), this);
copyAction->setIcon(QIcon(":/images/copy.png"));
copyAction->setShortcut(QKeySequence::Copy);
copyAction->setStatusTip(tr("Copy the current selection to the "
"clipboard"));
connect(copyAction, SIGNAL(triggered()), this, SLOT(copy()));

pasteAction = new QAction(tr("&Paste"), this);
pasteAction->setIcon(QIcon(":/images/paste.png"));
pasteAction->setShortcut(QKeySequence::Paste);
pasteAction->setStatusTip(tr("Paste the clipboard's contents at "
"the cursor position"));
connect(pasteAction, SIGNAL(triggered()), this, SLOT(paste()));

closeAction = new QAction(tr("Cl&ose"), this);
closeAction->setShortcut(QKeySequence::Close);
closeAction->setStatusTip(tr("Close the active window"));
connect(closeAction, SIGNAL(triggered()), mdiArea, SLOT(closeActiveSubWindow()));

closeAllAction = new QAction(tr("Close &All"), this);
closeAllAction->setStatusTip(tr("Close all the windows"));
connect(closeAllAction, SIGNAL(triggered()), this, SLOT(close()));

tileAction = new QAction(tr("&Tile"), this);
tileAction->setStatusTip(tr("Tile the windows"));
connect(tileAction, SIGNAL(triggered()), mdiArea, SLOT(tileSubWindows()));

cascadeAction = new QAction(tr("&Cascade"), this);
cascadeAction->setStatusTip(tr("Cascade the windows"));
connect(cascadeAction, SIGNAL(triggered()), mdiArea, SLOT(cascadeSubWindows()));

nextAction = new QAction(tr("Ne&xt"), this);
nextAction->setShortcut(QKeySequence::NextChild);
nextAction->setStatusTip(tr("Move the focus to the next window"));
connect(nextAction, SIGNAL(triggered()), mdiArea, SLOT(activateNextSubWindow()));

previousAction = new QAction(tr("Pre&vious"), this);
previousAction->setShortcut(QKeySequence::PreviousChild);
previousAction->setStatusTip(tr("Move the focus to the previous " "window"));
connect(previousAction, SIGNAL(triggered()),mdiArea, SLOT(activatePreviousSubWindow()));

separatorAction = new QAction(this);
separatorAction->setSeparator(true);

aboutAction = new QAction(tr("&About"), this);
aboutAction->setStatusTip(tr("Show the application's About box"));
connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));

aboutQtAction = new QAction(tr("About &Qt"), this);
aboutQtAction->setStatusTip(tr("Show the Qt library's About box"));
connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));

windowActionGroup = new QActionGroup(this);
}

void MainWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(newAction);
fileMenu->addAction(openAction);
fileMenu->addAction(saveAction);
fileMenu->addAction(saveAsAction);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);

editMenu = menuBar()->addMenu(tr("&Edit"));
editMenu->addAction(cutAction);
editMenu->addAction(copyAction);
editMenu->addAction(pasteAction);

windowMenu = menuBar()->addMenu(tr("&Window"));
windowMenu->addAction(closeAction);
windowMenu->addAction(closeAllAction);
windowMenu->addSeparator();
windowMenu->addAction(tileAction);
windowMenu->addAction(cascadeAction);
windowMenu->addSeparator();
windowMenu->addAction(nextAction);
windowMenu->addAction(previousAction);
windowMenu->addAction(separatorAction);

menuBar()->addSeparator();

helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(aboutAction);
helpMenu->addAction(aboutQtAction);
}

void MainWindow::createToolBars()
{
fileToolBar = addToolBar(tr("File"));
fileToolBar->addAction(newAction);
fileToolBar->addAction(openAction);
fileToolBar->addAction(saveAction);

editToolBar = addToolBar(tr("Edit"));
editToolBar->addAction(cutAction);
editToolBar->addAction(copyAction);
editToolBar->addAction(pasteAction);
}

void MainWindow::createStatusBar()
{
readyLabel = new QLabel(tr(" Ready"));
statusBar()->addWidget(readyLabel, 1);
}

void MainWindow::addEditor(Editor *editor)
{
connect(editor, SIGNAL(copyAvailable(bool)),
cutAction, SLOT(setEnabled(bool)));
connect(editor, SIGNAL(copyAvailable(bool)),
copyAction, SLOT(setEnabled(bool)));

QMdiSubWindow *subWindow = mdiArea->addSubWindow(editor);
windowMenu->addAction(editor->windowMenuAction());
windowActionGroup->addAction(editor->windowMenuAction());
subWindow->show();
}

Editor *MainWindow::activeEditor()
{
QMdiSubWindow *subWindow = mdiArea->activeSubWindow();
if (subWindow)
return qobject_cast<Editor *>(subWindow->widget());
return 0;
}


源码下载地址: