第五十三課、應用程序的打包與發佈------------------狄泰軟件學院

1、調試與發佈

一、發佈應用程序時的候選者shell

(1)、調試版(debug):開發階段生成可執行程序app

(2)、發佈版(release):最終產品的可執行程序編輯器

二、調試版的可執行程序ide

(1)、包含調試相關的信息,體積巨大函數

(2)、執行速度慢,支持斷點調試工具

三、發佈版的可執行程序佈局

(1)、無任何冗餘信息,體積小巧開發工具

(2)、執行速度快,沒法映射到源碼調試字體

2、程序的庫依賴

一、可執行程序的正常運行須要外部庫的支持ui

所以:發佈程序時必須保證全部依賴庫都存在

二、Windows能夠用Depends工具查看程序的依賴庫

 

三、Linux能夠用ldd命令查看程序的依賴庫

(1)、ldd是Linux系統中的一個腳本程序

3、程序的環境依賴

一、應用程序對於執行程序環境可能還存在依賴關係

 

二、在客戶機上部署程序的執行環境

(1)、方案一

A、用戶根據提供的手冊自行部署環境(不可取)

 (2)、方案二

A、開發一個專用的部署(安裝)程序
B、部署(安裝)程序運行後自動部署執行環境

三、部署(安裝)程序的開發

四、InstallShield的簡介

五、Inno Setup簡介

六、NSIS簡介

七、LinuxQt程序發佈簡介

(1)、方法一:

A、經過ldd命令肯定程序的庫依賴

B、經過shell腳本開發部署程序

(2)、方法二

根據具體發行版開發專用部署程序(dep、rpm)

4、文本編輯器項目完整程序

#ifndef ABOUTDIALOG_H #define ABOUTDIALOG_H #include <QWidget> #include <QLabel> #include <QPlainTextEdit> #include <QPushButton> #include <QDialog>

class AboutDialog : public QDialog { Q_OBJECT protected: QLabel m_label; QPushButton m_closeButton; QPlainTextEdit m_plainTextEdit; public: explicit AboutDialog(QWidget  *parent = 0); }; #endif // ABOUTDIALOG_H
關於對話框AboutDialog .h
#include "AboutDialog.h" #include <QPalette> AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), m_label(this),  m_closeButton(this), m_plainTextEdit(this) { QPixmap pm(":/Res/pic/Logo.PNG"); pm = pm.scaled(120, 120, Qt::KeepAspectRatio); m_label.setPixmap(pm); m_label.move(20, 20); m_label.resize(120, 120); QPalette p = m_plainTextEdit.palette(); p.setColor(QPalette::Active, QPalette::Base, palette().color(QPalette::Active, QPalette::Background)); p.setColor(QPalette::Inactive, QPalette::Base, palette().color(QPalette::Inactive, QPalette::Background)); m_plainTextEdit.move(200, 30); m_plainTextEdit.resize(180, 130); m_plainTextEdit.setPalette(p); m_plainTextEdit.setFrameStyle(QFrame::NoFrame); m_plainTextEdit.setReadOnly(true); m_plainTextEdit.insertPlainText("NotePad Project\n\nPlatform: Qt 4.7.4\n\nVersion: 1.0.0\n\nCopyright: LGC"); m_closeButton.setText("Close"); m_closeButton.move(273, 175); m_closeButton.resize(100, 30); setFixedSize(390, 230); setWindowTitle("About NotePad"); connect(&m_closeButton, SIGNAL(clicked()), this, SLOT(close())); }
關於對話框AboutDialog .cpp
#ifndef APPCONFIG_H #define APPCONFIG_H #include <QObject> #include <QFont> #include <QSize> #include <QPoint>

class AppConfig : public QObject { Q_OBJECT QFont m_editFont; bool m_isToolBarVisible; bool m_isStatusVisible; bool m_isAutoWrap; QSize m_mainWindowSize; QPoint m_mainWindowPosition; bool m_isValid; bool restore(); public: explicit AppConfig(QObject *parent = 0); explicit AppConfig(QFont editFont, bool isToolBarVisible, bool isStatusVisible,bool isAutoWrap, QSize mainWindowSize, QPoint mainWindowPosition, QObject *parent = 0); QFont editFont(); bool isToolBarVisible(); bool isStatusBarVisible(); bool isAutoWrap(); bool isValid(); QSize mainWindowSize(); QPoint mainWindowPosition(); bool store(); }; #endif // APPCONFIG_H
配置文件AppConfig.h
#include "AppConfig.h" #include <QFile> #include <QDataStream> #include <QApplication> #include <QIODevice>

//此構造函數用來讀取
AppConfig::AppConfig(QObject *parent) : QObject(parent) { m_isValid = restore(); } //此構造函數用來寫入
AppConfig::AppConfig(QFont editFont, bool isToolBarVisible, bool isStatusVisible,bool isAutoWrap, QSize mainWindowSize, QPoint mainWindowPosition, QObject *parent) { m_editFont = editFont; m_isToolBarVisible = isToolBarVisible; m_isStatusVisible = isStatusVisible; m_isAutoWrap = isAutoWrap; m_mainWindowSize = mainWindowSize; m_mainWindowPosition = mainWindowPosition; m_isValid = true; } QFont AppConfig::editFont() { return m_editFont; } bool AppConfig::isToolBarVisible() { return m_isToolBarVisible; } bool AppConfig::isStatusBarVisible() { return m_isStatusVisible; } bool AppConfig::isAutoWrap() { return m_isAutoWrap; } bool AppConfig::isValid() { return m_isValid; } bool AppConfig::restore() { bool ret = true; QFile file(QApplication::applicationDirPath() + "/app.config"); if(file.open(QIODevice::ReadOnly)) { QDataStream in(&file); in.setVersion(QDataStream::Qt_4_7); in >> m_editFont; in >> m_isToolBarVisible; in >> m_isStatusVisible; in >> m_isAutoWrap; in >> m_mainWindowSize; in >> m_mainWindowPosition; file.close(); } else { ret = false; } return ret; } bool AppConfig::store() { bool ret = true; QFile file(QApplication::applicationDirPath() + "/app.config"); if(file.open(QIODevice::WriteOnly)) { QDataStream out(&file); out.setVersion(QDataStream::Qt_4_7); out << m_editFont; out << m_isToolBarVisible; out << m_isStatusVisible; out << m_isAutoWrap; out << m_mainWindowSize; out << m_mainWindowPosition; file.close(); } else { ret = false; } return ret; } QSize AppConfig::mainWindowSize() { return m_mainWindowSize; } QPoint AppConfig::mainWindowPosition() { return m_mainWindowPosition; }
配置文件AppConfig.cpp
#ifndef FINDDIALOG_H #define FINDDIALOG_H #include <QDialog> #include <QPushButton> #include <QLabel> #include <QLineEdit> #include <QRadioButton> #include <QCheckBox> #include <QHBoxLayout> #include <QGroupBox> #include <QGridLayout> #include <QPlainTextEdit> #include <QPointer>

class FindDialog : public QDialog { Q_OBJECT protected: QGridLayout m_gLayout;//注意要把聲明放在組件以前,不然程序崩潰
    QGroupBox m_gBox;   //由於同一個佈局管理器裏面的父組件相同,組合的對象根據聲明的順序來構造,全部放在這裏
 QHBoxLayout m_hLayout; QLabel m_findLabel; QLineEdit m_findLineEdit; QPushButton m_findButton; QCheckBox m_checkBox; QRadioButton m_forwardButton; QRadioButton m_backwardButton; QPushButton m_cancleButton; QPointer<QPlainTextEdit> m_plainTextEdit; void initControl(); protected slots: void onFindButtonClicked(); void onCancleButtonClicked(); public: explicit FindDialog(QWidget *parent = 0, QPlainTextEdit* pText = NULL); void setPlainTextEdit(QPlainTextEdit* pText); QPlainTextEdit* getPlainTextEdit(); bool event(QEvent* e); }; #endif // FINDDIALOG_H
查找對話框FindDialog .h
#include "FindDialog.h" #include <QEvent> #include <QString> #include <QTextCursor> #include <QMessageBox> FindDialog::FindDialog(QWidget *parent, QPlainTextEdit* pText) : QDialog(parent, Qt::WindowCloseButtonHint | Qt::Drawer) { initControl(); connect(&m_findButton, SIGNAL(clicked()), this, SLOT(onFindButtonClicked())); connect(&m_cancleButton, SIGNAL(clicked()), this, SLOT(onCancleButtonClicked())); setPlainTextEdit(pText); setWindowTitle("查找"); setLayout(&m_gLayout); } void FindDialog::initControl() { m_findLabel.setText("查找內容: "); // m_findButton.setEnabled(false);
    m_findButton.setText("查找下一個"); m_checkBox.setText("區分大小寫"); m_forwardButton.setText("向上"); m_backwardButton.setChecked(true); m_backwardButton.setText("向下"); m_cancleButton.setText("取消"); m_gBox.setTitle("方向"); m_hLayout.addWidget(&m_forwardButton); m_hLayout.addWidget(&m_backwardButton); m_gBox.setLayout(&m_hLayout); m_gLayout.setSpacing(10); m_gLayout.addWidget(&m_findLabel, 0, 0); m_gLayout.addWidget(&m_findLineEdit, 0, 1); m_gLayout.addWidget(&m_findButton, 0, 2); m_gLayout.addWidget(&m_checkBox, 1, 0); m_gLayout.addWidget(&m_gBox, 1, 1); m_gLayout.addWidget(&m_cancleButton, 1, 2); } void FindDialog::setPlainTextEdit(QPlainTextEdit* pText) { m_plainTextEdit = pText; } QPlainTextEdit* FindDialog::getPlainTextEdit() { return m_plainTextEdit; } void FindDialog::onFindButtonClicked() { QString target = m_findLineEdit.text(); if((m_plainTextEdit != NULL) && (target != "")) { QString text = m_plainTextEdit->toPlainText(); QTextCursor c = m_plainTextEdit->textCursor(); int index = -1; if(m_backwardButton.isChecked()) { index = text.indexOf(target, c.position(), m_checkBox.isChecked()? Qt::CaseSensitive : Qt::CaseInsensitive); if(index >=0 ) { c.setPosition(index); c.setPosition(index + target.length(), QTextCursor::KeepAnchor); m_plainTextEdit->setTextCursor(c);//將光標信息設置到文本框裏面才能看見效果
 } } if(m_forwardButton.isChecked()) { index = text.lastIndexOf(target, c.position() - text.length() - 1, m_checkBox.isChecked()? Qt::CaseSensitive : Qt::CaseInsensitive);//注意下標爲負數
            if(index >=0 ) { c.setPosition(index + target.length()); c.setPosition(index, QTextCursor::KeepAnchor);//注意後往前找到後設置光標的方法
 m_plainTextEdit->setTextCursor(c); } } if(index < 0) { QMessageBox dlg(this); dlg.setText("找不到" + target); dlg.setStandardButtons(QMessageBox::Ok); dlg.setIcon(QMessageBox::Information); dlg.setWindowTitle("查找"); dlg.exec(); } } } void FindDialog::onCancleButtonClicked() { close(); } bool FindDialog::event(QEvent* e) { if(e->type()==QEvent::Close) { hide(); return true; } return QDialog::event(e); }
查找對話框FindDialog.cpp
#ifndef REPLACEDIALOG_H #define REPLACEDIALOG_H #include "FindDialog.h"

class ReplaceDialog : public FindDialog { Q_OBJECT QPushButton m_replaceButton; QPushButton m_replaceAllButton; QLabel m_replaceAsLabel; QLineEdit m_replaceEdit; void initControl(); protected slots: void onReplaceButtonClicked(); void onReplaceAllButtonClicked(); public: explicit ReplaceDialog(QWidget *parent = 0, QPlainTextEdit* pText = NULL); }; #endif // REPLACEDIALOG_H
替換對話框ReplaceDialog .h
#include "ReplaceDialog.h" ReplaceDialog::ReplaceDialog(QWidget *parent, QPlainTextEdit* pText) : FindDialog(parent, pText) { initControl(); connect(&m_replaceButton, SIGNAL(clicked()), this, SLOT(onReplaceButtonClicked())); connect(&m_replaceAllButton, SIGNAL(clicked()), this, SLOT(onReplaceAllButtonClicked())); setWindowTitle("替換"); setLayout(&m_gLayout); } void ReplaceDialog::initControl() { m_replaceButton.setText("替換"); m_replaceAllButton.setText("所有替換"); m_replaceAsLabel.setText("替換爲: "); m_gLayout.removeWidget(&m_checkBox); m_gLayout.removeWidget(&m_gBox); m_gLayout.removeWidget(&m_cancleButton); m_gLayout.addWidget(&m_replaceAsLabel, 1, 0); m_gLayout.addWidget(&m_replaceEdit, 1, 1); m_gLayout.addWidget(&m_replaceButton, 1, 2); m_gLayout.addWidget(&m_replaceAllButton, 2, 2); m_gLayout.addWidget(&m_checkBox, 3, 0); m_gLayout.addWidget(&m_gBox, 3, 1); m_gLayout.addWidget(&m_cancleButton, 3, 2); } void ReplaceDialog::onReplaceButtonClicked() { QString target = m_findLineEdit.text(); QString to = m_replaceEdit.text(); if(m_plainTextEdit != NULL && target !="" && to != "") { QString text = m_plainTextEdit->toPlainText(); QString selText = m_plainTextEdit->textCursor().selectedText(); if(selText == target) { m_plainTextEdit->insertPlainText(to); } onFindButtonClicked(); } } void ReplaceDialog::onReplaceAllButtonClicked() { QString target = m_findLineEdit.text(); QString to = m_replaceEdit.text(); if(m_plainTextEdit != NULL && target !="" && to != "") { QString text = m_plainTextEdit->toPlainText(); text.replace(target, to, m_checkBox.isChecked()? Qt::CaseSensitive : Qt::CaseInsensitive); m_plainTextEdit->clear(); m_plainTextEdit->setPlainText(text); } }
替換對話框ReplaceDialog.cpp
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMenuBar> #include <QMenu> #include <QAction> #include <QString> #include <QtGui/QMainWindow> #include <QToolBar> #include <QIcon> #include <QSize> #include <QStatusBar> #include <QLabel> #include <QPlainTextEdit> #include <QFileDialog> #include <QAction> #include <QSharedPointer> #include "FindDialog.h" #include "ReplaceDialog.h" #include "AboutDialog.h" #include "AppConfig.h"



class MainWindow : public QMainWindow { Q_OBJECT private: QPlainTextEdit mainEdit; QLabel statusLabel; QString m_filePath;//記得在構造函數裏初始化
        bool m_isTextChanged;//構造函數裏初始化爲false
 QSharedPointer<FindDialog> m_findDialogPoiter; QSharedPointer<ReplaceDialog> m_ReplaceDialogPoiter; MainWindow(QWidget *parent = 0); MainWindow(const MainWindow& obj); MainWindow* operator = (const MainWindow& obj); bool construct(); bool initMenuBar();//菜單欄
        bool initToolBar();//工具欄
        bool initStatusBar();//狀態欄
        bool initinitMainEditor();//編輯窗口

        bool initFileMenu(QMenuBar* mb);//文件菜單
        bool initEditMenu(QMenuBar* mb);//編輯菜單
        bool initFormatMenu(QMenuBar* mb);//格式菜單
        bool initViewMenu(QMenuBar* mb);//視圖菜單
        bool initHelpMenu(QMenuBar* mb);//幫助菜單

        bool initFileToolItem(QToolBar* tb);//工具選項
        bool initEditToolItem(QToolBar* tb); bool initFormatToolItem(QToolBar* tb); bool initViewToolItem(QToolBar* tb); bool makeAction(QAction*& action,QMenu* menu, QString text, int key);//菜單項
        bool makeAction(QAction*& action,QToolBar* tb, QString tip, QString icon); QString showFileDialog(QFileDialog::AcceptMode mode, QString title);//文件對話框
        void showErrorMessage(QString message);//錯誤消息對話框
        int showQuesstionMessage(QString message);//問題消息對話框
        QString saveCurrentData(QString path = ""); void preEditorChanged(); void openFileToEdit(QString path); QAction* findToolBarAction(QString text); QAction* findMenuBarAction(QString text); private slots: void onFileNew(); void onFileOpen(); void onFlieSave(); void onFileSaveAs(); void onFilePrint(); void onTextChanged(); void onCursorPositionChanged(); void onFileDelete(); void onFileExit(); void onEditFind(); void onEditReplce(); void onEditGoto(); void onViewStatusBar(); void onViewToolBar(); void onHelpAbout(); void onFontDialog(); void onHelpFindHelp(); void onFormatWrap(); void onCopyAvailable(bool available); void onUndoAvailable(bool available); void onRedoAvailable(bool available); protected: void closeEvent(QCloseEvent *e);//重寫關閉窗口的事件處理函數
        void dragEnterEvent(QDragEnterEvent* e); void dropEvent(QDropEvent* e); public: static MainWindow* NewInstance(); QToolBar* toolBar(); void openFile(QString path); ~MainWindow(); }; #endif // MAINWINDOW_H
主窗口頭文件MainWindow .h
#include "MainWindow.h" #include <QDebug> #include <QPalette> MainWindow::MainWindow(QWidget *parent) : m_findDialogPoiter(new FindDialog(this, &mainEdit)), m_ReplaceDialogPoiter(new ReplaceDialog(this, &mainEdit)) { m_filePath = ""; m_isTextChanged = false; setWindowTitle("NotePad-[New]"); resize(800, 500); setAcceptDrops(true); } bool MainWindow::construct() { bool ret = true; AppConfig config; ret = ret && initMenuBar(); ret = ret && initToolBar(); ret = ret && initStatusBar(); ret = ret && initinitMainEditor(); if(config.isValid()) { mainEdit.setFont(config.editFont()); //不自動換行
        if(!config.isAutoWrap()) { mainEdit.setLineWrapMode(QPlainTextEdit::NoWrap); findMenuBarAction("換行")->setChecked(false); findToolBarAction("換行")->setChecked(false); } //隱藏工具欄
        if(!config.isToolBarVisible()) { toolBar()->setVisible(false); findMenuBarAction("工具欄")->setChecked(false); findToolBarAction("工具欄")->setChecked(false); } //隱藏狀態欄
        if(!config.isStatusBarVisible()) { statusBar()->setVisible(false); findMenuBarAction("狀態欄")->setChecked(false); findToolBarAction("狀態欄")->setChecked(false); } move(config.mainWindowPosition()); resize(config.mainWindowSize()); } return ret; } MainWindow* MainWindow::NewInstance() { MainWindow* ret = new MainWindow(); if((ret==NULL) || (!ret->construct())) { delete ret; ret = NULL; } return ret; } bool MainWindow::initMenuBar()//菜單欄
{ bool ret = true; QMenuBar* mb = menuBar ();//必定要注意是menuBar(),這是普通成員函數,不是構造函數
 ret = ret && initFileMenu(mb);//傳一個參數是爲了在initFileMenu()函數將menu加入菜單欄
    ret = ret && initEditMenu(mb); ret = ret && initFormatMenu(mb); ret = ret && initViewMenu(mb); ret = ret && initHelpMenu(mb); return ret; } bool MainWindow::initToolBar()//工具欄
{ bool ret = true; QToolBar* tb = addToolBar("工具欄"); //tb->setMovable(false); //tb->setFloatable(false);
    tb->setIconSize(QSize(16,16)); ret = ret && initFileToolItem(tb); tb->addSeparator(); ret = ret && initEditToolItem(tb); tb->addSeparator(); ret = ret && initFormatToolItem(tb); tb->addSeparator(); ret = ret && initViewToolItem(tb); return ret; } bool MainWindow::initStatusBar()//狀態欄
{ bool ret = true; QStatusBar* sb = statusBar(); QLabel* label = new QLabel("Made By LGC"); if(label != NULL) { statusLabel.setMinimumWidth(200); statusLabel.setAlignment(Qt::AlignHCenter); statusLabel.setText("行:1 列:1"); label->setMinimumWidth(200); label->setAlignment(Qt::AlignHCenter); sb->addPermanentWidget(new QLabel());//單純加入分隔符
        sb->addPermanentWidget(&statusLabel); sb->addPermanentWidget(label); } else { ret = false; } return ret; } bool MainWindow::initinitMainEditor()//編輯窗口
{ bool ret = true; mainEdit.setParent(this); setCentralWidget(&mainEdit); connect(&mainEdit, SIGNAL(textChanged()), this, SLOT(onTextChanged())); connect(&mainEdit, SIGNAL(copyAvailable(bool)), this, SLOT(onCopyAvailable(bool))); connect(&mainEdit, SIGNAL(undoAvailable(bool)), this, SLOT(onUndoAvailable(bool))); connect(&mainEdit, SIGNAL(redoAvailable(bool)), this, SLOT(onRedoAvailable(bool))); connect(&mainEdit, SIGNAL(cursorPositionChanged()), this, SLOT(onCursorPositionChanged())); QPalette pmainEdit = mainEdit.palette(); pmainEdit.setColor(QPalette::Inactive, QPalette::Highlight, pmainEdit.color(QPalette::Active, QPalette::Highlight)); pmainEdit.setColor(QPalette::Inactive, QPalette::HighlightedText, pmainEdit.color(QPalette::Active, QPalette::HighlightedText)); mainEdit.setPalette(pmainEdit); return ret; } /************************************************文件菜單********************************************************/
bool MainWindow::initFileMenu(QMenuBar* mb) { bool ret = true; QMenu* menu = new QMenu("文件(&F)", mb);//建立文件菜單,(&F)是爲了能夠Alt+F打開
    ret = (menu != NULL); if(ret) { QAction* action = NULL; //New
        ret = ret &&  makeAction(action, menu, "新建(&N)",Qt::CTRL + Qt::Key_N); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onFileNew())); menu->addAction(action); } menu->addSeparator(); //Open
        ret = ret &&  makeAction(action,  menu,"打開(&O)...",Qt::CTRL + Qt::Key_O); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onFileOpen())); menu->addAction(action); } menu->addSeparator(); //Save
        ret = ret &&  makeAction(action,  menu,"保存(&S)",Qt::CTRL + Qt::Key_S); if(ret) { connect(action, SIGNAL(triggered()), this ,SLOT(onFlieSave())); menu->addAction(action); } menu->addSeparator(); //Save As
        ret = ret &&  makeAction(action, menu, "另存爲(&A)...",0); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onFileSaveAs())); menu->addAction(action); } menu->addSeparator(); //print
        ret = ret &&  makeAction(action, menu, "打印(&P)...",Qt::CTRL + Qt::Key_P); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onFilePrint())); menu->addAction(action); } menu->addSeparator(); //Exit
        ret = ret &&  makeAction(action,  menu,"退出(&X)",0); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onFileExit())); menu->addAction(action);//將菜單項加入到菜單
 } } if(ret) { mb->addMenu(menu);//將菜單加入到菜單欄
 } else { delete mb; } return ret; } /************************************************編輯菜單********************************************************/
bool MainWindow::initEditMenu(QMenuBar* mb) { bool ret = true; QMenu* menu = new QMenu("編輯(&E)", mb); ret = (menu != NULL); if(ret) { QAction* action = NULL; //Undo
        ret = ret &&  makeAction(action,  menu,"撤銷(&U)",Qt::CTRL + Qt::Key_Z); if(ret) { connect(action, SIGNAL(triggered()), &mainEdit, SLOT(undo())); action->setEnabled(false); menu->addAction(action); } menu->addSeparator(); //Redo
        ret = ret &&  makeAction(action,  menu,"重作(&R)...",Qt::CTRL + Qt::Key_Y); if(ret) { connect(action, SIGNAL(triggered()), &mainEdit, SLOT(redo())); action->setEnabled(false); menu->addAction(action); } menu->addSeparator(); //Cut
        ret = ret &&  makeAction(action,  menu,"剪切(&X)",Qt::CTRL + Qt::Key_X); if(ret) { connect(action, SIGNAL(triggered()), &mainEdit, SLOT(cut())); action->setEnabled(false); menu->addAction(action); } menu->addSeparator(); //Copy
        ret = ret &&  makeAction(action,  menu,"複製(&C)...",Qt::CTRL + Qt::Key_C); if(ret) { connect(action, SIGNAL(triggered()), &mainEdit, SLOT(copy())); action->setEnabled(false); menu->addAction(action); } menu->addSeparator(); //Paste
        ret = ret &&  makeAction(action,  menu,"粘貼(&P)...",Qt::CTRL + Qt::Key_V); if(ret) { connect(action, SIGNAL(triggered()), &mainEdit, SLOT(paste())); menu->addAction(action); } menu->addSeparator(); //Delete
        ret = ret &&  makeAction(action, menu, "刪除(&L)",Qt::Key_Delete); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onFileDelete())); menu->addAction(action); } menu->addSeparator(); //Find
        ret = ret &&  makeAction(action,  menu,"查找(&F)...",Qt::CTRL + Qt::Key_F); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onEditFind())); menu->addAction(action); } menu->addSeparator(); //Replace
        ret = ret &&  makeAction(action,  menu,"替換(&R)...",Qt::CTRL + Qt::Key_H); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onEditReplce())); menu->addAction(action); } menu->addSeparator(); //Goto
        ret = ret &&  makeAction(action,  menu,"轉到(&G)",Qt::CTRL + Qt::Key_G); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onEditGoto())); menu->addAction(action); } menu->addSeparator(); //Select All
        ret = ret &&  makeAction(action, menu, "全選(&A)",Qt::CTRL + Qt::Key_A); if(ret) { connect(action, SIGNAL(triggered()), &mainEdit, SLOT(selectAll())); menu->addAction(action); } } if(ret) { mb->addMenu(menu); } else { delete mb; } return ret; } /************************************************格式菜單********************************************************/
bool MainWindow::initFormatMenu(QMenuBar* mb) { bool ret = true; QMenu* menu = new QMenu("格式(&O)", mb); ret = (menu != NULL); if(ret) { QAction* action = NULL; //Auto Wrap
        ret = ret &&  makeAction(action,  menu,"換行(&W)",0); if(ret) { action->setCheckable(true); action->setChecked(true); connect(action, SIGNAL(triggered()), this, SLOT(onFormatWrap())); menu->addAction(action); } menu->addSeparator(); //Font
        ret = ret &&  makeAction(action,  menu,"字體(&F)...",0); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onFontDialog())); menu->addAction(action); } } if(ret) { mb->addMenu(menu); } else { delete mb; } return ret; } /************************************************視圖菜單********************************************************/
bool MainWindow::initViewMenu(QMenuBar* mb) { bool ret = true; QMenu* menu = new QMenu("視圖(&V)", mb); ret = (menu != NULL); if(ret) { QAction* action = NULL; //Tool Bar
        ret = ret &&  makeAction(action, menu,"工具欄(&T)",0); if(ret) { action->setCheckable(true); action->setChecked(true); connect(action, SIGNAL(triggered()), this, SLOT(onViewToolBar())); menu->addAction(action); } menu->addSeparator(); //Status Bar
        ret = ret &&  makeAction(action, menu,"狀態欄(&S)",0); if(ret) { action->setCheckable(true); action->setChecked(true); connect(action, SIGNAL(triggered()), this, SLOT(onViewStatusBar())); menu->addAction(action); } } if(ret) { mb->addMenu(menu); } else { delete mb; } return ret; } /************************************************幫助菜單********************************************************/
bool MainWindow::initHelpMenu(QMenuBar* mb) { bool ret = true; QMenu* menu = new QMenu("幫助(&H)", mb); ret = (menu != NULL); if(ret) { QAction* action = NULL; //User Manual
        ret = ret &&  makeAction(action,  menu,"查看幫助",0); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onHelpFindHelp())); menu->addAction(action); } menu->addSeparator(); //About NotePad
        ret = ret &&  makeAction(action,  menu,"關於記事本...",0); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onHelpAbout())); menu->addAction(action); } } if(ret) { mb->addMenu(menu); } else { delete mb; } return ret; } /*****************************************工具************************************************************/
bool MainWindow::initFileToolItem(QToolBar* tb) { bool ret = true; QAction* action = NULL; ret = ret && makeAction(action, tb, "新建", ":/Res/pic/new.png"); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onFileNew())); tb->addAction(action); } ret = ret && makeAction(action,  tb,"打開", ":/Res/pic/open.png"); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onFileOpen())); tb->addAction(action); } ret = ret && makeAction(action,  tb,"保存", ":/Res/pic/save.png"); if(ret) { connect(action, SIGNAL(triggered()), this ,SLOT(onFlieSave())); tb->addAction(action); } ret = ret && makeAction(action,  tb,"另存爲", ":/Res/pic/saveas.png"); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onFileSaveAs())); tb->addAction(action); } ret = ret && makeAction(action, tb,"打印",  ":/Res/pic/print.png"); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onFilePrint())); tb->addAction(action); } return ret; } bool MainWindow::initEditToolItem(QToolBar* tb) { bool ret = true; QAction* action = NULL; ret = ret && makeAction(action, tb,"撤銷",  ":/Res/pic/undo.png"); if(ret) { action->setEnabled(false); connect(action, SIGNAL(triggered()), &mainEdit, SLOT(undo())); tb->addAction(action); } ret = ret && makeAction(action,  tb,"重作", ":/Res/pic/redo.png"); if(ret) { action->setEnabled(false); connect(action, SIGNAL(triggered()), &mainEdit, SLOT(redo())); tb->addAction(action); } ret = ret && makeAction(action, tb, "剪切",  ":/Res/pic/cut.png"); if(ret) { action->setEnabled(false); connect(action, SIGNAL(triggered()), &mainEdit, SLOT(cut())); tb->addAction(action); } ret = ret && makeAction(action,  tb,"複製", ":/Res/pic/copy.png"); if(ret) { action->setEnabled(false); connect(action, SIGNAL(triggered()), &mainEdit, SLOT(copy())); tb->addAction(action); } ret = ret && makeAction(action, tb,"粘貼",  ":/Res/pic/paste.png"); if(ret) { connect(action, SIGNAL(triggered()), &mainEdit, SLOT(paste())); tb->addAction(action); } ret = ret && makeAction(action, tb,"查找",  ":/Res/pic/find.png"); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onEditFind())); tb->addAction(action); } ret = ret && makeAction(action, tb,"替換",  ":/Res/pic/replace.png"); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onEditReplce())); tb->addAction(action); } ret = ret && makeAction(action, tb,"轉到",  ":/Res/pic/goto.png"); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onEditGoto())); tb->addAction(action); } return ret; } bool MainWindow::initFormatToolItem(QToolBar* tb) { bool ret = true; QAction* action = NULL; ret = ret && makeAction(action, tb, "換行", ":/Res/pic/wrap.png"); if(ret) { action->setCheckable(true); action->setChecked(true); connect(action, SIGNAL(triggered()), this, SLOT(onFormatWrap())); tb->addAction(action); } ret = ret && makeAction(action, tb,"字體",  ":/Res/pic/font.png"); if(ret) { connect(action, SIGNAL(triggered()), this, SLOT(onFontDialog())); tb->addAction(action); } return ret; } bool MainWindow::initViewToolItem(QToolBar* tb) { bool ret = true; QAction* action = NULL; ret = ret && makeAction(action,  tb,"工具欄", ":/Res/pic/tool.png"); if(ret) { action->setCheckable(true); action->setChecked(true); connect(action, SIGNAL(triggered()), this, SLOT(onViewToolBar())); tb->addAction(action); } ret = ret && makeAction(action,  tb,"狀態欄", ":/Res/pic/status.png"); if(ret) { action->setCheckable(true); action->setChecked(true); connect(action, SIGNAL(triggered()), this, SLOT(onViewStatusBar())); tb->addAction(action); } return ret; } bool MainWindow::makeAction(QAction*& action,QMenu* menu, QString text, int key)//菜單項
{ bool ret = true; action = new QAction(text, menu); if(action != NULL) { action->setShortcut(QKeySequence(key));//建立快捷鍵
 } else { ret = false; } return ret; } bool MainWindow::makeAction(QAction*& action,QToolBar* tb, QString tip, QString icon) { bool ret = true; action = new QAction("", tb); if(action != NULL) { action->setToolTip(tip); action->setIcon(QIcon(icon)); } else { ret = false; } return ret; } MainWindow::~MainWindow() { }
主窗口界面實現文件MainWindowUI.cpp
#include <QFileDialog> #include <QStringList> #include <QFile> #include <QDebug> #include <QMessageBox> #include "MainWindow.h" #include <QMap> #include <QDragEnterEvent> #include <QDropEvent> #include <QMimeData> #include <QList> #include <QUrl> #include <QFileInfo> #include <QObjectList> #include <QToolBar> #include <QPrintDialog> #include <QPrinter> #include <QKeyEvent> #include <QApplication> #include <QInputDialog> #include <QStatusBar> #include <QList> #include "AboutDialog.h" #include <QFontDialog> #include <QDesktopServices> QString MainWindow::showFileDialog(QFileDialog::AcceptMode mode, QString title) { QString ret = ""; QFileDialog fd; QStringList filters; QMap<QString, QString> map; const char* fileArray[][2]= { {"Text(*.txt)",    ".txt"}, {"All Files(*.*)",   "*" }, {NULL, NULL} }; for(int i=0; fileArray[i][0] != NULL; i++) { filters.append(fileArray[i][0]); map.insert(fileArray[i][0], fileArray[i][1]); } fd.setWindowTitle(title); fd.setAcceptMode(mode); fd.setNameFilters(filters); if(mode==QFileDialog::AcceptOpen) { fd.setFileMode(QFileDialog::ExistingFile); } if(fd.exec()==QFileDialog::Accepted) { ret = fd.selectedFiles()[0]; QString posix = map[fd.selectedNameFilter()];//把下拉中選中的後綴對應鍵值取出

        if(posix != "*" && !ret.endsWith(posix)) { ret += posix; } } return ret; } void MainWindow::showErrorMessage(QString message) { QMessageBox mb(this); mb.setWindowTitle("Quession"); mb.setText(message); mb.setIcon(QMessageBox::Critical); mb.setStandardButtons(QMessageBox::Ok); mb.exec(); } int MainWindow::showQuesstionMessage(QString message) { QMessageBox mb(this); mb.setWindowTitle("Error"); mb.setText(message); mb.setIcon(QMessageBox::Question); mb.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); return mb.exec(); } 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 << QString(mainEdit.toPlainText()); file.close(); setWindowTitle("NotePad - [" + ret + "]"); m_isTextChanged = false;//保存後修改狀態值
 } else { showErrorMessage(QString("Open file Error!\n\n") + "\"" + m_filePath + "\""); ret = ""; } } return ret; } void MainWindow::preEditorChanged() { if(m_isTextChanged) { int r = showQuesstionMessage("Do you want to Save?"); switch (r) { case QMessageBox::Yes: saveCurrentData(m_filePath); break; case QMessageBox::No: m_isTextChanged = false; break; case QMessageBox::Cancel: break; } } } void MainWindow::openFileToEdit(QString path) { if(path != "") { QFile file(path); if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { mainEdit.setPlainText(QString(file.readAll())); file.close(); m_filePath = path;//報存當前文件路徑
 m_isTextChanged = false;//必定記得修改這個
 setWindowTitle("NotePad - [" + m_filePath + "]"); } else { showErrorMessage(QString("Open file Error!\n\n") + "\"" + m_filePath + "\""); } } } QToolBar* MainWindow::toolBar() { QToolBar*  ret = NULL; const QObjectList& list = children();//得到主窗口的組件

    for(int i=0; i<list.count(); i++) { QToolBar* tb = dynamic_cast<QToolBar*>(list[i]);//只有工具欄可以轉換成功

        if(tb != NULL) { ret = tb; } } return ret; } QAction* MainWindow::findMenuBarAction(QString text) { QAction* ret = NULL; const QObjectList& list = menuBar()->children();//得到菜單欄

    for(int i=0; i<list.count(); i++) { QMenu* menu = dynamic_cast<QMenu*>(list[i]);//得到每一個子菜單

        if(menu != NULL) { for(int j=0; j<menu->actions().count(); j++) { if(menu->actions()[j]->text().startsWith(text)) { ret = menu->actions()[j]; break; } } } } return ret; } QAction* MainWindow::findToolBarAction(QString text) { QAction* ret = NULL; QToolBar* tb = toolBar(); if(tb != NULL) { for(int j=0; j<tb->actions().count(); j++) { if(tb->actions()[j]->toolTip().startsWith(text))//注意工具欄裏面的是toolTip()
 { ret = tb->actions()[j]; break; } } } return ret; } void MainWindow::onFileNew() { preEditorChanged(); if(!m_isTextChanged) { mainEdit.clear(); m_filePath = ""; m_isTextChanged = false; setWindowTitle("NotePad-[New]"); } } void MainWindow::onFileOpen() { preEditorChanged(); if(!m_isTextChanged) { QString path = showFileDialog(QFileDialog::AcceptOpen, "open"); openFileToEdit(path); } } void MainWindow::onFlieSave() { QString path = saveCurrentData(m_filePath); if(path != "") { m_filePath = path; } } void MainWindow::onFileSaveAs() { QString path = saveCurrentData();//使用默認參數

    if(path != "") { m_filePath = path; } } void MainWindow::onFilePrint() { QPrintDialog dlg(this); dlg.setWindowTitle("Print"); if(dlg.exec()==QPrintDialog::Accepted) { QPrinter* p = dlg.printer();//將參數設置進打印機
 mainEdit.document()->print(p); } } void MainWindow::onTextChanged() { if(!m_isTextChanged) { setWindowTitle("*" + windowTitle()); } m_isTextChanged = true; } void MainWindow::onCopyAvailable(bool available) { QAction* action = findToolBarAction("複製"); if(action != NULL) { action->setEnabled(available); } action = findMenuBarAction("複製"); if(action != NULL) { action->setEnabled(available); } action = findMenuBarAction("剪切"); if(action != NULL) { action->setEnabled(available); } action = findToolBarAction("剪切"); if(action != NULL) { action->setEnabled(available); } } void MainWindow::onUndoAvailable(bool available) { QAction* action = findMenuBarAction("撤銷"); if(action != NULL) { action->setEnabled(available); } action = findToolBarAction("撤銷"); if(action != NULL) { action->setEnabled(available); } } void MainWindow::onRedoAvailable(bool available) { QAction* action = findMenuBarAction("重作"); if(action != NULL) { action->setEnabled(available); } action = findToolBarAction("重作"); if(action != NULL) { action->setEnabled(available); } } void MainWindow::closeEvent(QCloseEvent *e)//沒有對應的信號來處理,只能重寫事件處理函數
{ preEditorChanged(); QFont font = mainEdit.font(); bool isWrap = (mainEdit.lineWrapMode() == QPlainTextEdit::WidgetWidth); bool tbVisible = (findMenuBarAction("工具欄")->isChecked() && (findToolBarAction("工具欄")->isChecked())); bool sbVisible = (findMenuBarAction("狀態欄")->isChecked() && (findToolBarAction("狀態欄")->isChecked())); AppConfig config(font, tbVisible, sbVisible, isWrap, size(), pos()); config.store(); if(!m_isTextChanged) { QMainWindow::closeEvent(e);//調用父類的關閉事件處理函數
 } else { e->ignore();//點取消的話就忽略這個對話框
 } } void MainWindow::dragEnterEvent(QDragEnterEvent* e) { if(e->mimeData()->hasUrls()) { e->acceptProposedAction(); } else { e->ignore(); } } void MainWindow::dropEvent(QDropEvent* e) { if(e->mimeData()->hasUrls()) { QList<QUrl> list = e->mimeData()->urls(); QString path = list[0].toLocalFile(); QFileInfo fi(path); if(fi.isFile()) { preEditorChanged(); if(!m_isTextChanged) { openFileToEdit(path); } } else { showErrorMessage("Canot open a folder"); } } else { e->ignore(); } } void MainWindow::onCursorPositionChanged() { int pos = mainEdit.textCursor().position(); QString text = mainEdit.toPlainText();//獲取編輯器中的內容
    int ln = 0; int col = 0; int flag = -1; for(int i=0; i<pos; i++) { if(text[i] == '\n') { ln++; flag = i; } } flag++;//如光標在第十一行的某個位置,那麼一共有十個換行符,flag++就是在第十行最後一個位置(即最後一個光標所在位置)
 col = pos - flag;//用第十一行光標所在位置減去前十行的總數就得第十一行的字符個數,即縱座標
 statusLabel.setText("行: " + QString::number(ln+1)+ " 列: " + QString::number(col+1)); } void MainWindow::onFileDelete() { QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Delete,Qt::NoModifier); QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Delete,Qt::NoModifier); QApplication::sendEvent(&mainEdit, &keyPress);//發送事件模擬鍵盤的delete鍵
    QApplication::sendEvent(&mainEdit, &keyRelease); } void MainWindow::onFileExit() { close(); } void MainWindow::onEditFind() { m_findDialogPoiter->show(); } void MainWindow::onEditReplce() { m_ReplaceDialogPoiter->show(); } void MainWindow::onEditGoto() { bool ok = false; int ln = QInputDialog::getInt(this, "轉到", "行號: ", 1, 1, mainEdit.document()->lineCount(), 1, &ok);//第一步

    if(ok) { QString text = mainEdit.toPlainText(); QTextCursor c = mainEdit.textCursor(); int pos = 0; int next = -1; for(int i=0; i<ln; i++)//第二步
 { pos = next + 1;//最後一個換行符的下一個字符就是目標行的第一個字符
 next = text.indexOf('\n', pos); } c.setPosition(pos);//第三步
 mainEdit.setTextCursor(c); } } void MainWindow::onViewStatusBar() { QStatusBar* sb = statusBar(); bool visible = sb->isVisible(); sb->setVisible(!visible); QAction* action = findMenuBarAction("狀態欄"); if(action != NULL) { action->setChecked(!visible); } action = findToolBarAction("狀態欄"); if(action != NULL) { action->setChecked(!visible); } } void MainWindow::onViewToolBar() { QToolBar* tb = toolBar(); if(tb != NULL) { bool visible = tb->isVisible(); tb->setVisible(!visible); QAction* action = findMenuBarAction("工具欄"); if(action != NULL) { action->setChecked(!visible); } action = findToolBarAction("工具欄"); if(action != NULL) { action->setChecked(!visible); } } } void MainWindow::onHelpAbout() { AboutDialog(this).exec(); } void MainWindow::onFontDialog() { bool ok = false; QFont font = QFontDialog::getFont(&ok, mainEdit.font(), this); if( ok ) { mainEdit.setFont(font); } } void MainWindow::onHelpFindHelp() { QDesktopServices::openUrl(QUrl("http://www.baidu.com")); } void MainWindow::onFormatWrap() { QPlainTextEdit::LineWrapMode mode = mainEdit.lineWrapMode(); if( mode == QPlainTextEdit::NoWrap )//若是不是自動換行
 { mainEdit.setLineWrapMode(QPlainTextEdit::WidgetWidth);//就反轉爲自動換行
 findMenuBarAction("換行")->setChecked(true); findToolBarAction("換行")->setChecked(true); } else { mainEdit.setLineWrapMode(QPlainTextEdit::NoWrap); findMenuBarAction("換行")->setChecked(false); findToolBarAction("換行")->setChecked(false); } } void MainWindow::openFile(QString path) { preEditorChanged(); if(!m_isTextChanged) { openFileToEdit(path); } }
主窗口功能實現文件MainWindowSlots.cpp
#include <QtGui/QApplication> #include "MainWindow.h" #include <QTextCodec> #include <QFileInfo>

int main(int argc, char *argv[]) { QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); //路徑名支持中文
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); //QString支持中文
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); //string支持中文
 QApplication a(argc, argv); MainWindow* w = MainWindow::NewInstance(); int ret = -1; if(w != NULL) { if(argc > 1) { QFileInfo fi(argv[1]); if(fi.exists()) { w->openFile(fi.absoluteFilePath()); } } w->show(); ret = a.exec(); } delete w; return ret; }
主函數main.cpp

資源文件:

5、小結

(1)、程序開發時可以生成debug和release版

(2)、打包時首先要解決程序的庫依賴

(3)、程序執行須要特殊環境依賴時必須開發部署程序

(4)、Windows中有豐富的部署程序開發工具可供選擇

(5)、Linux中能夠採用Shell腳本開發部署程序  

相關文章
相關標籤/搜索