第五十三课、应用程序的打包与发布------------------狄泰软件学院
一、调试与发布
1、发布应用程序时的候选者
(1)、调试版(debug):开发阶段生成可执行程序
(2)、发布版(release):最终产品的可执行程序
2、调试版的可执行程序
(1)、包含调试相关的信息,体积巨大
(2)、执行速度慢,支持断点调试
3、发布版的可执行程序
(1)、无任何冗余信息,体积小巧
(2)、执行速度快,无法映射到源码调试
二、程序的库依赖
1、可执行程序的正常运行需要外部库的支持
因此:发布程序时必须保证所有依赖库都存在
2、Windows可以用Depends工具查看程序的依赖库
3、Linux可以用ldd命令查看程序的依赖库
(1)、ldd是Linux系统中的一个脚本程序
三、程序的环境依赖
1、应用程序对于执行程序环境可能还存在依赖关系
2、在客户机上部署程序的执行环境
(1)、方案一
A、用户根据提供的手册自行部署环境(不可取)
(2)、方案二
A、开发一个专用的部署(安装)程序
B、部署(安装)程序运行后自动部署执行环境
3、部署(安装)程序的开发
4、InstallShield的简介
5、Inno Setup简介
6、NSIS简介
7、LinuxQt程序发布简介
(1)、方法一:
A、通过ldd命令确定程序的库依赖
B、通过shell脚本开发部署程序
(2)、方法二
根据具体发行版开发专用部署程序(dep、rpm)
四、文本编辑器项目完整程序
#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
#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())); }
#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
#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; }
#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
#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); }
#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
#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); } }
#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
#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() { }
#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); } }
#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; }
资源文件:
五、小结
(1)、程序开发时能够生成debug和release版
(2)、打包时首先要解决程序的库依赖
(3)、程序执行需要特殊环境依赖时必须开发部署程序
(4)、Windows中有丰富的部署程序开发工具可供选择
(5)、Linux中可以采用Shell脚本开发部署程序