个人网站注册平台要多少钱,软件开发公司简介范文大全,哈尔滨自助建站系统,网站关键词如何选取一、核心功能
本软件为多文档型程序#xff0c;界面是标准的 Windows 主从窗口
拥有#xff1a;主菜单、工具栏、文档显示区 和 状态栏。 所要实现的东西#xff0c;均在下图了。 开发该软件#xff0c;主要分为下面三个阶段
1#xff09;界面设计开发
多窗口 MDI 程序…一、核心功能
本软件为多文档型程序界面是标准的 Windows 主从窗口
拥有主菜单、工具栏、文档显示区 和 状态栏。 所要实现的东西均在下图了。 开发该软件主要分为下面三个阶段
1界面设计开发
多窗口 MDI 程序框架的建立菜单设计工具栏设计工具按钮状态栏的帮助提示文本多个文档子窗口的管理和控制
2文本编辑功能实现
建立、打开和保存剪切、复制和粘贴撤销和恢复
3排版美化功能实现
字体选择字形字号文字颜色文档段落标号和标号的添加段落对齐方式
二、界面设计与开发
新建项目MyselfWord。 1. 建立 MDI 程序框架
1.1 多文档区域的创建
在头文件 “myword.h” 中添加 QMdiArea 类的声明和定义变量
#ifndef MYWORD_H
#define MYWORD_H#include QMainWindow//申明
class QMdiArea;class MyWord : public QMainWindow
{Q_OBJECTpublic:MyWord(QWidget *parent nullptr);~MyWord();private://定义变量QMdiArea *mdiArea;
};
#endif // MYWORD_H在 “myword.cpp” 的构造函数编写如下
#include myword.h
#include QtWidgetsMyWord::MyWord(QWidget *parent): QMainWindow(parent)
{mdiArea new QMdiArea; // 创建一个新的QMdiArea实例mdiArea-setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); // 设置水平滚动条策略为根据需要显示mdiArea-setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); // 设置垂直滚动条策略为根据需要显示setCentralWidget(mdiArea); // 将QMdiArea设置为窗口的中心部件move(200,150);resize(800,500);setWindowTitle(tr(Myself Word));
}MyWord::~MyWord()
{
} 1.2 子窗口类的创建 为了实现多文档操作和管理需要向 QMdiArea 中添加子窗口。为了可以更好地操作子窗口则必须实例化子窗口的中心部件。而子窗口的中心部件使用了 QTextEdit 类所以要实现自己的类它必须继承自 QTextEdit 类。 添加新的类具体如下 在 “mychild.h” 中添加
#ifndef MYCHILD_H
#define MYCHILD_H#include QWidget
#include QTextEditclass MyChild : public QTextEdit
{Q_OBJECT
public:MyChild();void newFile(); //新建操作QString userFriendlyCurrentFile(); //提取文件名QString currentFile() { return curFile; } //返回当前文件路径
protected:void closeEvent(QCloseEvent *event); //关闭事件
private slots:void documentWasModified(); //文档被更改时窗口显示更改状态标识
private:QString strippedName(const QString fullFileName); //获取较短的绝对路径QString curFile; //保存当前文件路径bool isUntitled; //作为当前文件是否被保存到硬盘上的标识
};#endif // MYCHILD_H声明了许多函数和定义了几个变量。其实可以一边实现功能一边添加需要的函数。现在先实现新建功能首先声明函数 newFile()。 1.3 新建文件操作
1newFile() 设计思路
设置窗口编号设置文件未被保存过 “isUntitiled true;”保存文件路径为 curFile 赋初值用 strippedName 函数修改为绝对路径设置子窗口标题关联文档内容改变信号 contentsChanged() 到显示文档更改状态标志槽documentWasModified()。
2newFile() 实现
子窗口的初始化
在“mychild.cpp”文件中添加
#include mychild.h
#include QtWidgetsMyChild::MyChild()
{setAttribute(Qt::WA_DeleteOnClose); //设置在子窗口关闭时销毁这个类的对象isUntitled true; //初始 isUntitled 为 true
}newFile() 的实现 void MyChild::newFile()
{//设置窗口编号因为编号会一直保存所以需要使用静态变量static int sequenceNumber 1;//新建的文档默认为命名isUntitled true;//将当前文件命名为文档编号的形式编号先使用再1curFile tr(文档 %1).arg(sequenceNumber);//设置窗口标题使用[*]可以在文档被更改后在文件名称后显示*号setWindowTitle(curFile [*] tr( - Myself Word));//文档更改时发送 contentsChanged()信号执行 documentWasModified() 曹函数connect(document(),SIGNAL(contentsChanged()),this,SLOT(documentWasModified()));
}
这里在设置窗口标题时添加了“[*]”字符它可以保证编辑器内容被更改后在文档标题中显示“*”号。
3文件更改标记
下面是 documentWasModified() 槽函数的定义
void MyChild::documentWasModified()
{ //根据文档的 isModified() 函数的返回值判断编辑器内容是否被更改setWindowModified(document()-isModified());
}
编辑器内容是否被更改可以使用 QTextDocument 类的 isModified() 函数得知。
设置文档子窗口标题
QString MyChild::userFriendlyCurrentFile()
{return strippedName(curFile);
}
strippedName 函数用于修改文件名为较短的绝对路径。接收一个完整的文件名包括路径作为参数类型为 QString然后返回这个文件名中的基本文件名部分即去除路径后的文件名。
QString MyChild::strippedName(const QString fullFileName)
{return QFileInfo(fullFileName).fileName();
}
先不考虑关闭文档时的保存逻辑在 closeEvent() 中无条件地接收关闭事件。
void MyChild::closeEvent(QCloseEvent *event)
{event-accept();
} 2. 菜单系统设计
MyselfWord 的菜单系统包括主菜单、菜单栏和子菜单三级。
在 “myword.h” 中声明以及系统动作和菜单的实现
#ifndef MYWORD_H
#define MYWORD_H#include QMainWindowclass QMdiArea;
class QAction;//
class QMenu;//class MyWord : public QMainWindow
{Q_OBJECTpublic:MyWord(QWidget *parent nullptr);~MyWord();private:QMdiArea *mdiArea;void createActions();//void createMenus();//
};
#endif // MYWORD_H2.1 文件 主菜单
需要包括新建N打开O保存S另存为A打印P打印预览退出X。
在“myword.h”文件中定义“文件”菜单指针定义“文件”主菜单下各个功能项的 QAction
private:void createActions();void createMenus();QMdiArea *mdiArea;//菜单QMenu *fileMenu;//动作(Action)QAction *newAct; //【文件】主菜单QAction *openAct;QAction *saveAct;QAction *saveAsAct;QAction *printAct;QAction *printPreviewAct;QAction *exitAct;
在“myword.cpp”文件中编写函数 createActions() 的代码
记得在 images目录下搞点菜单图标。
const QString rsrcPath :/images;
void MyWord::createActions()
{/*【文件】菜单动作集*///N 表示这个菜单项可以使用快捷键 AltN 来访问newAct new QAction(QIcon(rsrcPath /filenew.png), tr(新建(N)), this);newAct-setShortcuts(QKeySequence::New); //设置了快捷键newAct-setToolTip(新建); //设置工具栏按钮的提示文本newAct-setStatusTip(tr(创建一个新文档)); //设置状态栏提示文本//connect(newAct, SIGNAL(triggered()), this, SLOT(fileNew()));openAct new QAction(QIcon(rsrcPath /fileopen.png), tr(打开(O)...), this);openAct-setShortcuts(QKeySequence::Open);openAct-setToolTip(打开);openAct-setStatusTip(tr(打开已存在的文档));//connect(openAct, SIGNAL(triggered()), this, SLOT(fileOpen()));saveAct new QAction(QIcon(rsrcPath /filesave.png), tr(保存(S)), this);saveAct-setShortcuts(QKeySequence::Save);saveAct-setToolTip(保存);saveAct-setStatusTip(tr(将当前文档存盘));//connect(saveAct, SIGNAL(triggered()), this, SLOT(fileSave()));saveAsAct new QAction(tr(另存为(A)...), this);saveAsAct-setShortcuts(QKeySequence::SaveAs);saveAsAct-setStatusTip(tr(以一个新名字保存文档));//connect(saveAsAct, SIGNAL(triggered()), this, SLOT(fileSaveAs()));printAct new QAction(QIcon(rsrcPath /fileprint.png), tr(打印(P)...), this);printAct-setShortcuts(QKeySequence::Print);printAct-setToolTip(打印);printAct-setStatusTip(tr(打印文档));//connect(printAct, SIGNAL(triggered()), this, SLOT(filePrint()));printPreviewAct new QAction(tr(打印预览...), this);printPreviewAct-setStatusTip(tr(预览打印效果));//connect(printPreviewAct, SIGNAL(triggered()), this, SLOT(filePrintPreview()));exitAct new QAction(tr(退出(X)), this);exitAct-setShortcuts(QKeySequence::Quit);exitAct-setStatusTip(tr(退出应用程序));//connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
}上面所写的槽函数后面会一一实现。
然后再编写函数 createMenus() 的代码
void MyWord::createMenus()
{//【文件】主菜单fileMenu menuBar()-addMenu(tr(文件(F)));fileMenu-addAction(newAct);fileMenu-addAction(openAct);fileMenu-addSeparator(); //分隔线fileMenu-addAction(saveAct);fileMenu-addAction(saveAsAct);fileMenu-addSeparator(); //分隔线fileMenu-addAction(printAct);fileMenu-addAction(printPreviewAct);fileMenu-addSeparator(); //分隔线fileMenu-addAction(exitAct);
}
记得别忘记在“myword.cpp”的构造函数中添加这里两个函数 createActions();createMenus();
“文件”主菜单的运行显示效果如下 2.2 编辑 主菜单
“编辑” 主菜单功能项应包含撤销U、重做R、剪切T、复制C、粘贴P
在 “myword.h”文件中定义“编辑”主菜单指针 QMenu *editMenu;QAction *undoAct; //【编辑】主菜单QAction *redoAct;QAction *cutAct;QAction *copyAct;QAction *pasteAct;
在“myword.cpp”文件函数 createActions() 的代码中添加
/*【编辑】菜单动作集*/undoAct new QAction(QIcon(rsrcPath /editundo.png),tr(撤销(U)), this);undoAct-setShortcut(QKeySequence::Undo);undoAct-setToolTip(撤销);undoAct-setStatusTip(tr(撤销当前操作));connect(undoAct, SIGNAL(triggered()), this, SLOT(undo())); //不用子窗口类去实现redoAct new QAction(QIcon(rsrcPath /editredo.png),tr(重做(R)), this);redoAct-setShortcut(QKeySequence::Redo);redoAct-setToolTip(重做);redoAct-setStatusTip(tr(恢复之前操作));connect(redoAct, SIGNAL(triggered()), this, SLOT(redo())); //不用子窗口类去实现cutAct new QAction(QIcon(rsrcPath /editcut.png),tr(剪切(T)), this);cutAct-setShortcuts(QKeySequence::Cut);cutAct-setToolTip(剪切);cutAct-setStatusTip(tr(从文档中裁剪所选内容并将其放入剪贴板));connect(cutAct, SIGNAL(triggered()), this, SLOT(cut())); //不用子窗口类去实现copyAct new QAction(QIcon(rsrcPath /editcopy.png),tr(复制(C)), this);copyAct-setShortcuts(QKeySequence::Copy);copyAct-setToolTip(复制);copyAct-setStatusTip(tr(拷贝所选内容并将其放入剪贴板));connect(copyAct, SIGNAL(triggered()), this, SLOT(copy())); //不用子窗口类去实现pasteAct new QAction(QIcon(rsrcPath /editpaste.png),tr(粘贴(P)), this);pasteAct-setShortcuts(QKeySequence::Paste);pasteAct-setToolTip(粘贴);pasteAct-setStatusTip(tr(将剪贴板的内容粘贴到文档));connect(pasteAct, SIGNAL(triggered()), this, SLOT(paste())); //不用子窗口类去实现
在“myword.cpp”文件函数 createMenus() 的代码中添加
//【编辑】主菜单editMenu menuBar()-addMenu(tr(编辑(E)));editMenu-addAction(undoAct);editMenu-addAction(redoAct);editMenu-addSeparator(); //分隔线editMenu-addAction(cutAct);editMenu-addAction(copyAct);editMenu-addAction(pasteAct);
“编辑” 主菜单的运行效果 2.3 格式 主菜单
“格式”主菜单功能项应包含
字体D 加粗B、倾斜I、下画线U 段落 左对齐L、居中E、右对齐R、两端对齐J 颜色C
这是多级菜单了在“myword.h”中定义“格式”主菜单及其自菜单的指针 QMenu *formatMenu;QMenu *fontMenu; //子菜单QMenu *alignMenu; //子菜单QAction *boldAct; //【格式】主菜单QAction *italicAct;QAction *underlineAct;QAction *leftAlignAct;QAction *centerAct;QAction *rightAlignAct;QAction *justifyAct;QAction *colorAct;
在“myword.cpp”文件函数 createActions() 的代码中添加 /*【格式】菜单动作集*/boldAct new QAction(QIcon(rsrcPath /textbold.png),tr(加粗(B)), this);boldAct-setCheckable(true);boldAct-setShortcut(Qt::CTRL Qt::Key_B);boldAct-setToolTip(加粗);boldAct-setStatusTip(tr(将所选文字加粗));QFont bold;bold.setBold(true);boldAct-setFont(bold);connect(boldAct, SIGNAL(triggered()), this, SLOT(textBold()));italicAct new QAction(QIcon(rsrcPath /textitalic.png),tr(倾斜(I)), this);italicAct-setCheckable(true);italicAct-setShortcut(Qt::CTRL Qt::Key_I);italicAct-setToolTip(倾斜);italicAct-setStatusTip(tr(将所选文字用斜体显示));QFont italic;italic.setItalic(true);italicAct-setFont(italic);connect(italicAct, SIGNAL(triggered()), this, SLOT(textItalic()));underlineAct new QAction(QIcon(rsrcPath /textunder.png),tr(下划线(U)), this);underlineAct-setCheckable(true);underlineAct-setShortcut(Qt::CTRL Qt::Key_U);underlineAct-setToolTip(下划线);underlineAct-setStatusTip(tr(给所选文字加下划线));QFont underline;underline.setUnderline(true);underlineAct-setFont(underline);connect(underlineAct, SIGNAL(triggered()), this, SLOT(textUnderline()));//【格式】→【段落】子菜单下的各项为同一个菜单项组只能选中其中一项QActionGroup *grp new QActionGroup(this);connect(grp, SIGNAL(triggered(QAction*)), this, SLOT(textAlign(QAction*)));if (QApplication::isLeftToRight()) {leftAlignAct new QAction(QIcon(rsrcPath /textleft.png),tr(左对齐(L)), grp);centerAct new QAction(QIcon(rsrcPath /textcenter.png),tr(居中(E)), grp);rightAlignAct new QAction(QIcon(rsrcPath /textright.png),tr(右对齐(R)), grp);} else {rightAlignAct new QAction(QIcon(rsrcPath /textright.png),tr(右对齐(R)), grp);centerAct new QAction(QIcon(rsrcPath /textcenter.png),tr(居中(E)), grp);leftAlignAct new QAction(QIcon(rsrcPath /textleft.png),tr(左对齐(L)), grp);}justifyAct new QAction(QIcon(rsrcPath /textjustify.png),tr(两端对齐(J)), grp);leftAlignAct-setShortcut(Qt::CTRL Qt::Key_L);leftAlignAct-setCheckable(true);leftAlignAct-setToolTip(左对齐);leftAlignAct-setStatusTip(tr(将文字左对齐));centerAct-setShortcut(Qt::CTRL Qt::Key_E);centerAct-setCheckable(true);centerAct-setToolTip(居中);centerAct-setStatusTip(tr(将文字居中对齐));rightAlignAct-setShortcut(Qt::CTRL Qt::Key_R);rightAlignAct-setCheckable(true);rightAlignAct-setToolTip(右对齐);rightAlignAct-setStatusTip(tr(将文字右对齐));justifyAct-setShortcut(Qt::CTRL Qt::Key_J);justifyAct-setCheckable(true);justifyAct-setToolTip(两端对齐);justifyAct-setStatusTip(tr(将文字左右两端同时对齐并根据需要增加字间距));QPixmap pix(16, 16);pix.fill(Qt::red);colorAct new QAction(pix, tr(颜色(C)...), this);colorAct-setToolTip(颜色);colorAct-setStatusTip(tr(设置文字颜色));connect(colorAct, SIGNAL(triggered()), this, SLOT(textColor()));
这里用到了 QActionGroup 类它将菜单动作分组。
在上面的代码创建了一个 Action 组 grp。由于 Action 组默认是互斥的所以同一时刻只有一个会被选中。
在“myword.h”文件中添加 textAlign() 声明以及对应cpp文件添加定义
//myword.h
private slots:void textAlign(QAction *a);//myword.cpp
void MyWord::textAlign(QAction *a)
{}
暂时不写其中的代码只是定义函数体。
在“myword.cpp”文件函数 createMenus() 的代码中添加 //【格式】主菜单formatMenu menuBar()-addMenu(tr(格式(O)));fontMenu formatMenu-addMenu(tr(字体(D))); //【字体】子菜单fontMenu-addAction(boldAct);fontMenu-addAction(italicAct);fontMenu-addAction(underlineAct);alignMenu formatMenu-addMenu(tr(段落)); //【段落】子菜单alignMenu-addAction(leftAlignAct);alignMenu-addAction(centerAct);alignMenu-addAction(rightAlignAct);alignMenu-addAction(justifyAct);运行效果如下 2.4 窗口 和 帮助 主菜单
“窗口”主菜单功能项应包含关闭O关闭所有A平铺T层叠C下一个X前一个V。
在“myword.h”头文件中定义“窗口”主菜单指针以及各个功能项的动作 QMenu *windowMenu;QAction *closeAct; //【窗口】主菜单QAction *closeAllAct;QAction *tileAct;QAction *cascadeAct;QAction *nextAct;QAction *previousAct;QAction *separatorAct;QAction *aboutAct; //【帮助】主菜单QAction *aboutQtAct; 在“myword.cpp”文件函数 createActions() 的代码中添加 /*【窗口】菜单动作集*/closeAct new QAction(tr(关闭(O)), this);closeAct-setStatusTip(tr(关闭活动文档子窗口));//connect(closeAct, SIGNAL(triggered()),mdiArea, SLOT(closeActiveSubWindow())); //不用自己实现closeAllAct new QAction(tr(关闭所有(A)), this);closeAllAct-setStatusTip(tr(关闭所有子窗口));//connect(closeAllAct, SIGNAL(triggered()),mdiArea, SLOT(closeAllSubWindows())); //不用自己实现tileAct new QAction(tr(平铺(T)), this);tileAct-setStatusTip(tr(平铺子窗口));//connect(tileAct, SIGNAL(triggered()), mdiArea, SLOT(tileSubWindows())); //不用自己实现cascadeAct new QAction(tr(层叠(C)), this);cascadeAct-setStatusTip(tr(层叠子窗口));//connect(cascadeAct, SIGNAL(triggered()), mdiArea, SLOT(cascadeSubWindows())); //不用自己实现nextAct new QAction(tr(下一个(X)), this);nextAct-setShortcuts(QKeySequence::NextChild);nextAct-setStatusTip(tr(移动焦点到下一个子窗口));//connect(nextAct, SIGNAL(triggered()),mdiArea, SLOT(activateNextSubWindow())); //不用自己实现previousAct new QAction(tr(前一个(V)), this);previousAct-setShortcuts(QKeySequence::PreviousChild);previousAct-setStatusTip(tr(移动焦点到前一个子窗口));//connect(previousAct, SIGNAL(triggered()),mdiArea, SLOT(activatePreviousSubWindow())); //不用自己实现separatorAct new QAction(this);separatorAct-setSeparator(true);/*【帮助】菜单动作集*/aboutAct new QAction(tr(关于(A)), this);aboutAct-setStatusTip(tr(关于 Myself Word));//connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));aboutQtAct new QAction(tr(关于 Qt(Q)), this);aboutQtAct-setStatusTip(tr(关于 Qt 库));//connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); 在“myword.cpp”文件函数 createMenus() 的代码中添加 //【窗口】主菜单windowMenu menuBar()-addMenu(tr(窗口(W)));//updateWindowMenu();//connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowMenu()));menuBar()-addSeparator(); 2.5 图标问题
把图标的问题解决下主要是路径的问题。
这段改成绝对路径即可。当然这里可以先不改后面会创建 qrc 文件来管理资源。
const QString rsrcPath D:/qt_project/MyselfWord/images; 3. 工具栏设计
工具栏共有四个工具条其中三个分别对应 “文件”、“编辑” 和“格式” 菜单的功能。最后一个为组合选择栏它提供一组选择框控件。
3.1 工具条开发
在“myword.h”头文件中声明
class QComboBox;
class QFontComboBox;private:void createToolBars();//工具栏QToolBar *fileToolBar; //文件 工具条QToolBar *editToolBar; //编辑 工具条QToolBar *formatToolBar; //格式 工具条QToolBar *comboToolBar; //组合选择框QComboBox *comboStyle; //子控件 标号与编号类型选择框QFontComboBox *comboFont; //子控件 字体选择框QComboBox *comboSize; //子控件 字号选择框
在“myword.cpp”实现 createToolBars() 函数别忘记构造函数添加成员函数
void MyWord::createToolBars()
{//文件工具栏fileToolBar addToolBar(tr(文件));fileToolBar-addAction(newAct);fileToolBar-addAction(openAct);fileToolBar-addAction(saveAct);fileToolBar-addSeparator(); //分隔条fileToolBar-addAction(printAct);//编辑工具栏editToolBar addToolBar(tr(编辑));editToolBar-addAction(undoAct);editToolBar-addAction(redoAct);editToolBar-addSeparator(); //分隔条editToolBar-addAction(cutAct);editToolBar-addAction(copyAct);editToolBar-addAction(pasteAct);//格式工具栏formatToolBar addToolBar(tr(格式));formatToolBar-addAction(boldAct);formatToolBar-addAction(italicAct);formatToolBar-addAction(underlineAct);formatToolBar-addSeparator(); //分隔条formatToolBar-addAction(leftAlignAct);formatToolBar-addAction(centerAct);formatToolBar-addAction(rightAlignAct);formatToolBar-addAction(justifyAct);formatToolBar-addSeparator(); //分隔条formatToolBar-addAction(colorAct);//组合工具栏addToolBarBreak(Qt::TopToolBarArea); //使这个工具条在界面上另起一行显示comboToolBar addToolBar(tr(组合选择));comboStyle new QComboBox();comboToolBar-addWidget(comboStyle);comboStyle-addItem(标准);comboStyle-addItem(项目符号 (●));comboStyle-addItem(项目符号 (○));comboStyle-addItem(项目符号 (■));comboStyle-addItem(编号 (⒈⒉⒊));comboStyle-addItem(编号 ( a.b.c.));comboStyle-addItem(编号 ( A.B.C.));comboStyle-addItem(编号 (ⅰ.ⅱ.ⅲ.));comboStyle-addItem(编号 (Ⅰ.Ⅱ.Ⅲ.));comboStyle-setStatusTip(段落加标号或编号);connect(comboStyle, SIGNAL(activated(int)), this, SLOT(textStyle(int)));comboFont new QFontComboBox();comboToolBar-addWidget(comboFont);comboFont-setStatusTip(更改字体);connect(comboFont, SIGNAL(activated(QString)), this, SLOT(textFamily(QString)));comboSize new QComboBox();comboToolBar-addWidget(comboSize);comboSize-setEditable(true);comboSize-setStatusTip(更改字号);QFontDatabase db;foreach(int size, db.standardSizes())comboSize-addItem(QString::number(size));connect(comboSize, SIGNAL(activated(QString)), this, SLOT(textSize(QString)));comboSize-setCurrentIndex(comboSize-findText(QString::number(QApplication::font().pointSize())));
} 3.2 导入图标资源
图片资源存放在 D:\qt_project\MyselfWord 下。
给工程项目添加 Qt Resource File也就是 qrc 后缀的文件。 添加以下内容
RCCqresource prefix/fileimages/editcopy.png/filefileimages/editcut.png/filefileimages/editpaste.png/filefileimages/editredo.png/filefileimages/editundo.png/filefileimages/filenew.png/filefileimages/fileopen.png/filefileimages/fileprint.png/filefileimages/filesave.png/filefileimages/textbold.png/filefileimages/textcenter.png/filefileimages/textitalic.png/filefileimages/textjustify.png/filefileimages/textleft.png/filefileimages/textright.png/filefileimages/textunder.png/file/qresource
/RCC
在 “myword.cpp”文件开头添加资源路径
const QString rsrcPath :/images;
然后运行效果如下 4. 子窗口管理
4.1 新建子窗口
前面已经建立了子窗口的中心部件 MyChild 类它继承自 QTextEDit 类。
下面便可以使用这个类来创建文档子窗口。
“myword.h”
class MyChild;private slots:void fileNew();MyChild *createMyChild();
“myword.cpp”
#include mychild.h
MyChild *MyWord::createMyChild()
{MyChild *child new MyChild;mdiArea-addSubWindow(child);connect(child, SIGNAL(copyAvailable(bool)),cutAct, SLOT(setEnabled(bool)));connect(child, SIGNAL(copyAvailable(bool)),copyAct, SLOT(setEnabled(bool)));return child;
} 函数 createActions() 中去掉注释。
connect(newAct, SIGNAL(triggered()), this, SLOT(fileNew()));void MyWord::fileNew()
{MyChild *child createMyChild();child-newFile();child-show();enabledText(); //使得字体设置菜单可用
} “myword.h”
private:void enabledText(); //使得【格式】下的各个子菜单项可用 “myword.cpp”
void MyWord::enabledText()
{boldAct-setEnabled(true);italicAct-setEnabled(true);underlineAct-setEnabled(true);leftAlignAct-setEnabled(true);centerAct-setEnabled(true);rightAlignAct-setEnabled(true);justifyAct-setEnabled(true);colorAct-setEnabled(true);
}
文件 → 新建出现 “文档1” 子窗口。 4.2 更新菜单状态
在“myword.h”
class QMdiSubWindow;private slots:void updateMenus(); //更新菜单private:MyChild *activeMyChild(); //活动窗口
在“myword.cpp”
connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)),this, SLOT(updateMenus()));
updateMenus(); updateMenus() 函数 void MyWord::updateMenus()
{//至少有一个子文档打开着的情况bool hasMyChild (activeMyChild()!0);saveAct-setEnabled(hasMyChild);saveAsAct-setEnabled(hasMyChild);printAct-setEnabled(hasMyChild);printPreviewAct-setEnabled(hasMyChild);pasteAct-setEnabled(hasMyChild);closeAct-setEnabled(hasMyChild);closeAllAct-setEnabled(hasMyChild);tileAct-setEnabled(hasMyChild);cascadeAct-setEnabled(hasMyChild);nextAct-setEnabled(hasMyChild);previousAct-setEnabled(hasMyChild);separatorAct-setVisible(hasMyChild);//文档打开着并且其中有内容被选中的情况bool hasSelection (activeMyChild() activeMyChild()-textCursor().hasSelection());cutAct-setEnabled(hasSelection);copyAct-setEnabled(hasSelection);boldAct-setEnabled(hasSelection);italicAct-setEnabled(hasSelection);underlineAct-setEnabled(hasSelection);leftAlignAct-setEnabled(hasSelection);centerAct-setEnabled(hasSelection);rightAlignAct-setEnabled(hasSelection);justifyAct-setEnabled(hasSelection);colorAct-setEnabled(hasSelection);
}
activeMyChild() 函数
MyChild *MyWord::activeMyChild()
{if (QMdiSubWindow *activeSubWindow mdiArea-activeSubWindow())return qobject_castMyChild *(activeSubWindow-widget());return 0;
} 4.3 添加子窗口列表
“myword.h”
class QSignalMapper;private:QSignalMapper *windowMapper;private slots:void updateWindowMenu();
“myword.cpp”
windowMapper new QSignalMapper(this);
connect(windowMapper, SIGNAL(mapped(QWidget*)),this, SLOT(setActiveSubWindow(QWidget*)));
updateWindowMenu();
connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowMenu())); void MyWord::updateWindowMenu()
{windowMenu-clear();windowMenu-addAction(closeAct);windowMenu-addAction(closeAllAct);windowMenu-addSeparator();windowMenu-addAction(tileAct);windowMenu-addAction(cascadeAct);windowMenu-addSeparator();windowMenu-addAction(nextAct);windowMenu-addAction(previousAct);windowMenu-addAction(separatorAct);QListQMdiSubWindow * windows mdiArea-subWindowList();separatorAct-setVisible(!windows.isEmpty());//显示当前打开着的文档子窗口项for (int i 0; i windows.size(); i) {MyChild *child qobject_castMyChild *(windows.at(i)-widget());QString text;if (i 9) {text tr(%1 %2).arg(i 1).arg(child-userFriendlyCurrentFile());} else {text tr(%1 %2).arg(i 1).arg(child-userFriendlyCurrentFile());}QAction *action windowMenu-addAction(text);action-setCheckable(true);action -setChecked(child activeMyChild());connect(action, SIGNAL(triggered()), windowMapper, SLOT(map()));windowMapper-setMapping(action, windows.at(i));}enabledText(); //使得字体设置菜单可用
} 4.4 窗口关闭
protected:void closeEvent(QCloseEvent *event); void MyWord::closeEvent(QCloseEvent *event)
{mdiArea-closeAllSubWindows();if (mdiArea-currentSubWindow()) {event-ignore();} else {event-accept();}
}
新建四个文档然后窗口菜单的显示效果。 然后点击“关闭”就会把当前活动的文档关闭点击 “关闭所有”就会把全部的4个文档关闭。 5. 界面生成试运行
private:void createStatusBar();
void MyWord::createStatusBar()
{statusBar()-showMessage(tr(就绪));
}三、基本编辑功能实现
开发好软件界面后就可以向系统中添加各种各样的功能。
首先实现的基本编辑功能包括打开、保存、另存为、剪切、复制、粘贴、撤销和回复。
1. 打开文件
实现打开文件功能需要在子窗口类 MyChild 中定义加载文件操作。
1.1 加载文件操作步骤
1打开指定的文件并读取文件内容到编辑器。
2设置当前文件的 setCurrentFile() 该函数可以获取文件路径完成文件和窗口状态的设置。
3关联文档内容改变信号到显示文档更改状态槽 documentWasModified() 。
加载文件操作采用 loadFile() 函数实现。 1.2 加载文件操作实现
//mychild.h
public:bool loadFile(const QString fileName);
private:void setCurrentFile(const QString fileName);//mychild.cpp
bool MyChild::loadFile(const QString fileName)
{if (fileName.isEmpty())return false;QFile file(fileName);if (!file.exists()) {qWarning() File does not exist: fileName;return false;}if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {qWarning() Failed to open file for reading: fileName;return false;}// 假设文件是以 UTF-8 编码的这是 HTML 文件的常见情况QTextStream in(file);QString content in.readAll();// 不再需要 QTextCodec因为我们已经读取了 UTF-8 编码的字符串// 检查内容是否为富文本这里简单假设 HTML 就是富文本if (content.contains(html) || content.contains(HTML)) { // 简单的检查可能不够准确this-setHtml(content);} else {// 如果不是明显的 HTML我们可以尝试将其视为纯文本// 注意这里我们不再转换编码因为 content 已经是 QString 了this-setPlainText(content);}setCurrentFile(fileName);// 连接信号和槽以监控文档更改这部分看起来没问题connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified()));return true;
}
void MyChild::setCurrentFile(const QString fileName)
{curFile QFileInfo(fileName).canonicalFilePath();isUntitled false;document()-setModified(false);setWindowModified(false);setWindowTitle(userFriendlyCurrentFile() [*]);
}1.3 加载文件操作的调用
//myword.h
private slots:void fileOpen();
privete:QMdiSubWindow *findMyChild(const QString fileName);//myword.cpp
void MyWord::createActions()
{connect(newAct, SIGNAL(triggered()), this, SLOT(fileNew()));
}void MyWord::fileOpen()
{QString fileName QFileDialog::getOpenFileName(this, tr(打开),QString(), tr(HTML 文档 (*.htm *.html);;所有文件 (*.*)));if (!fileName.isEmpty()) {QMdiSubWindow *existing findMyChild(fileName);if (existing) {mdiArea-setActiveSubWindow(existing);return;}MyChild *child createMyChild();if (child-loadFile(fileName)) {statusBar()-showMessage(tr(文件已载入), 2000);child-show();enabledText(); //使得字体设置菜单可用} else {child-close();}}
}
//打开文件用
QMdiSubWindow *MyWord::findMyChild(const QString fileName)
{QString canonicalFilePath QFileInfo(fileName).canonicalFilePath();foreach (QMdiSubWindow *window, mdiArea-subWindowList()) {MyChild *myChild qobject_castMyChild *(window-widget());if (myChild-currentFile() canonicalFilePath)return window;}return 0;
}
提取准备一个1.html在bulid的Debug目录下。 2. 保存文件操作实现
保存文件功能分为“保存”和“另存为”两种操作这两种操作都需要在子窗口 MyChild 中定义。
2.1 保存文件操作步骤
保存 save() 的逻辑
1如果文件没有被保存过用 isUntitled 判断则执行 “另存为” 操作 saveAs()。
2否则直接 “保存” 文件 saveFile()改函数首先打开指定文件然后将编辑器的内容写入该文件最后设置当前文件 setCurrentFile()。
另存为 saveAs() 的逻辑
1从“文件”对话框获取文件路径。
2如果路径不为空则保存文件 saveFile()。 2.2 保存文件操作实现
//mychild.h
public:bool save();bool saveAs();bool saveFile(QString fileName);//mychild.cpp
bool MyChild::save()
{if (isUntitled) {return saveAs();} else {return saveFile(curFile);}
}bool MyChild::saveAs()
{QString fileName QFileDialog::getSaveFileName(this, tr(另存为),curFile,tr(HTML 文档 (*.htm *.html);;所有文件 (*.*)));if (fileName.isEmpty())return false;return saveFile(fileName);
}bool MyChild::saveFile(QString fileName)
{if (!(fileName.endsWith(.htm, Qt::CaseInsensitive) || fileName.endsWith(.html, Qt::CaseInsensitive))) {fileName .html; // 默认保存为 HTML 文档}QTextDocumentWriter writer(fileName);bool success writer.write(this-document());if (success)setCurrentFile(fileName);return success;
}
2.3 保存文件操作调用
void MyWord::createActions()
{connect(saveAct, SIGNAL(triggered()), this, SLOT(fileSave()));connect(saveAsAct, SIGNAL(triggered()), this, SLOT(fileSaveAs()));
}
//myword.h
private slots:void fileSave();void fileSaveAs();//myword.cpp
void MyWord::fileSave()
{if (activeMyChild() activeMyChild()-save())statusBar()-showMessage(tr(保存成功), 2000);
}void MyWord::fileSaveAs()
{if (activeMyChild() activeMyChild()-saveAs())statusBar()-showMessage(tr(保存成功), 2000);
}
2.4 提醒保存文件
//mychild.h
private:bool maybeSave();
protected:void closeEvent(QCloseEvent *event);//mychild.cpp
bool MyChild::maybeSave()
{if (!document()-isModified())return true;QMessageBox::StandardButton ret;ret QMessageBox::warning(this, tr(Myself Qt Word),tr(文档%1已被修改,保存吗?).arg(userFriendlyCurrentFile()),QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);if (ret QMessageBox::Save)return save();else if (ret QMessageBox::Cancel)return false;return true;
}void MyChild::closeEvent(QCloseEvent *event)
{if (maybeSave()) {event-accept();} else {event-ignore();}
} 3. 文本操作
最基本的文本操作包括撤销、重做、剪切、复制和粘贴。又QTextEdit 类提供。
3.1 撤销与重做
编辑菜单动作集
connect(undoAct, SIGNAL(triggered()), this, SLOT(undo())); //不用子窗口类去实现
connect(redoAct, SIGNAL(triggered()), this, SLOT(redo())); //不用子窗口类去实现 3.2 剪切、复制和粘贴
connect(cutAct, SIGNAL(triggered()), this, SLOT(cut()));
connect(copyAct, SIGNAL(triggered()), this, SLOT(copy()));
connect(pasteAct, SIGNAL(triggered()), this, SLOT(paste())); //不用子窗口类去实现
//myword.h
private slots:void undo();void redo();void cut();void copy();void paste();//myword.cpp
void MyWord::undo()
{if(activeMyChild())activeMyChild()-undo();
}void MyWord::redo()
{if(activeMyChild())activeMyChild()-redo();
}void MyWord::cut()
{if (activeMyChild())activeMyChild()-cut();
}void MyWord::copy()
{if (activeMyChild())activeMyChild()-copy();
}void MyWord::paste()
{if (activeMyChild())activeMyChild()-paste();
}
到此功能完成的差不多了。 四、文档排版美化功能实现
1. 字体格式设置
基本设置包括加粗、倾斜和加下划线。
1.1 子窗口的操作
//mychild.h
pubilc:void mergeFormatOnWordOrSelection(const QTextCharFormat format); //格式字体设置//mychild.cpp
//格式设置
void MyChild::mergeFormatOnWordOrSelection(const QTextCharFormat format)
{QTextCursor cursor this-textCursor();if (!cursor.hasSelection())cursor.select(QTextCursor::WordUnderCursor);cursor.mergeCharFormat(format);this-mergeCurrentCharFormat(format);
}1.2 主窗口调用格式函数
connect(boldAct, SIGNAL(triggered()), this, SLOT(textBold()));
connect(italicAct, SIGNAL(triggered()), this, SLOT(textItalic()));
connect(underlineAct, SIGNAL(triggered()), this, SLOT(textUnderline()));
//myword.h
private slots:void textBold();void textItalic();void textUnderline();//myword.cpp
void MyWord::textBold()
{QTextCharFormat fmt;fmt.setFontWeight(boldAct-isChecked() ? QFont::Bold : QFont::Normal);if(activeMyChild())activeMyChild()-mergeFormatOnWordOrSelection(fmt);
}void MyWord::textItalic()
{QTextCharFormat fmt;fmt.setFontItalic(italicAct-isChecked());if(activeMyChild())activeMyChild()-mergeFormatOnWordOrSelection(fmt);
}void MyWord::textUnderline()
{QTextCharFormat fmt;fmt.setFontUnderline(underlineAct-isChecked());if(activeMyChild())activeMyChild()-mergeFormatOnWordOrSelection(fmt);
} 1.3 字体、字号选择框
void MyWord::createToolBars(){connect(comboFont, SIGNAL(activated(QString)), this, SLOT(textFamily(QString)));connect(comboSize, SIGNAL(activated(QString)), this, SLOT(textSize(QString)));comboSize-setCurrentIndex(comboSize-findText(QString::number(QApplication::font().pointSize())));
}
//myword.h
private slots:void textFamily(const QString f);void textSize(const QString p);//myword.cpp
void MyWord::textFamily(const QString f)
{QTextCharFormat fmt;fmt.setFontFamily(f);if(activeMyChild())activeMyChild()-mergeFormatOnWordOrSelection(fmt);
}void MyWord::textSize(const QString p)
{qreal pointSize p.toFloat();if (p.toFloat() 0) {QTextCharFormat fmt;fmt.setFontPointSize(pointSize);if(activeMyChild())activeMyChild()-mergeFormatOnWordOrSelection(fmt);}
}
这边5代和6代Qt有一定的不同。 2. 段落对齐设置
//mychild.h
public:void setAlign(int align);//mychild.cpp
//段落对齐设置
void MyChild::setAlign(int align)
{if (align 1)this-setAlignment(Qt::AlignLeft | Qt::AlignAbsolute);else if (align 2)this-setAlignment(Qt::AlignHCenter);else if (align 3)this-setAlignment(Qt::AlignRight | Qt::AlignAbsolute);else if (align 4)this-setAlignment(Qt::AlignJustify);
}
//myword.cpp
void MyWord::textAlign(QAction *a)
{if(activeMyChild()){if (a leftAlignAct)activeMyChild()-setAlign(1);else if (a centerAct)activeMyChild()-setAlign(2);else if (a rightAlignAct)activeMyChild()-setAlign(3);else if (a justifyAct)activeMyChild()-setAlign(4);}
} 3. 颜色设置
//Action
connect(colorAct, SIGNAL(triggered()), this, SLOT(textColor()));
//myword.h
private:void colorChanged(const QColor c);private slots:void textColor();//myword.cpp
void MyWord::textColor()
{if(activeMyChild()){QColor col QColorDialog::getColor(activeMyChild()-textColor(), this);if (!col.isValid())return;QTextCharFormat fmt;fmt.setForeground(col);activeMyChild()-mergeFormatOnWordOrSelection(fmt);colorChanged(col);}
}void MyWord::colorChanged(const QColor c)
{QPixmap pix(16, 16);pix.fill(c);colorAct-setIcon(pix);
}4. 段落标号、编号
4.1 子窗口设置段落标号、编号操作
//mychild.h
public:void setStyle(int style);//mychild.cpp
//段落标号、编号
void MyChild::setStyle(int style)
{QTextCursor cursor this-textCursor();if (style ! 0) {QTextListFormat::Style stylename QTextListFormat::ListDisc;switch (style) {default:case 1:stylename QTextListFormat::ListDisc;break;case 2:stylename QTextListFormat::ListCircle;break;case 3:stylename QTextListFormat::ListSquare;break;case 4:stylename QTextListFormat::ListDecimal;break;case 5:stylename QTextListFormat::ListLowerAlpha;break;case 6:stylename QTextListFormat::ListUpperAlpha;break;case 7:stylename QTextListFormat::ListLowerRoman;break;case 8:stylename QTextListFormat::ListUpperRoman;break;}cursor.beginEditBlock();QTextBlockFormat blockFmt cursor.blockFormat();QTextListFormat listFmt;if (cursor.currentList()) {listFmt cursor.currentList()-format();} else {listFmt.setIndent(blockFmt.indent() 1);blockFmt.setIndent(0);cursor.setBlockFormat(blockFmt);}listFmt.setStyle(stylename);cursor.createList(listFmt);cursor.endEditBlock();} else {QTextBlockFormat bfmt;bfmt.setObjectIndex(-1);cursor.mergeBlockFormat(bfmt);}
} 4.2 实现段落标号、编号选择框
//createToolBars()
//组合工具栏
connect(comboStyle, SIGNAL(activated(int)), this, SLOT(textStyle(int))); 4.3 主窗口调用
//myword.h
private slots:void textStyle(int styleIndex);//myword.cpp
void MyWord::textStyle(int styleIndex)
{if(activeMyChild()){activeMyChild()-setStyle(styleIndex);}
} 5. 文档打印与预览
5.1 添加打印模块支持
在 MyselfWord.pro 中添加支持
//6代QT
QT printsupport//5代QT
qtHaveModule(printsupport): QT printsupport
5.2 实现打印及预览功能
//Action
connect(printAct, SIGNAL(triggered()), this, SLOT(filePrint()));connect(printPreviewAct, SIGNAL(triggered()), this, SLOT(filePrintPreview()));
//myword.h
private slots:void filePrint();void filePrintPreview();void printPreview(QPrinter *);//myword.cpp
void MyWord::filePrint()
{QPrinter printer(QPrinter::HighResolution);QPrintDialog *dlg new QPrintDialog(printer, this);if (activeMyChild()-textCursor().hasSelection())//6代QT//dlg-setOption(QAbstractPrintDialog::PrintSelection);dlg-addEnabledOption(QAbstractPrintDialog::PrintSelection);dlg-setWindowTitle(tr(打印文档));if (dlg-exec() QDialog::Accepted)activeMyChild()-print(printer);delete dlg;
}void MyWord::filePrintPreview()
{QPrinter printer(QPrinter::HighResolution);QPrintPreviewDialog preview(printer, this);connect(preview, SIGNAL(paintRequested(QPrinter*)), SLOT(printPreview(QPrinter*)));preview.exec();
}void MyWord::printPreview(QPrinter *printer)
{activeMyChild()-print(printer);
}