Qt: 多文件應用程式原始碼解析及下載
阿新 • • 發佈:2019-01-09
如果有程式碼看不懂,可以留言,我會回覆大家的留言(Qt、C++純技術交流群:302558294)
效果圖如下:
專案結構:
程式主要功能:
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 © 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;
}
原始碼下載地址: