多文档编辑器(程序代码+任务书+说明书+外文翻译+演示文稿)_第1页
多文档编辑器(程序代码+任务书+说明书+外文翻译+演示文稿)_第2页
多文档编辑器(程序代码+任务书+说明书+外文翻译+演示文稿)_第3页
多文档编辑器(程序代码+任务书+说明书+外文翻译+演示文稿)_第4页
多文档编辑器(程序代码+任务书+说明书+外文翻译+演示文稿)_第5页
已阅读5页,还剩62页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

多文本编辑器设计与实现摘要在深入研究当前各种文本编辑软件优劣的前提上,分析软件开发中程序员的实际需求,发现他们有时候并不需要打开系统庞大、启动较慢的集成开发环境来阅读改写代码,只需要通过小型的文本编辑器即可。然而大多数小型文本编辑器并不能高亮显示代码中的关键字,或者软件本身闭源,不能根据需要改变高亮显示关键字列表,或者软件只有windows版或Linux版平台移植性较差,这并不能满足经常需要在各个软件系统平台之间交叉开发的程序员的需求,甚至影响了他们的工作效率。本系统运用了平台移植性较好的Qt语言来开发,不同平台之间只需要重新编译即可,且代码易读可重用性良好,程序员只需要修改代码中关键字列表或根据需要自定义自己的高亮显示关键字列表即可,这一软件为程序员阅读改写代码提供了便利。关键词自定义;多文本编辑器;Qt;高亮显示ITheDesignandImplementationofMultipleDocumentEditorAbstractInthefurtherstudyofthecurrentvarioustexteditingsoftwarequalityonthepremiseoftheanalysisoftheactualdemandofsoftwaredevelopmentprogrammers,findthattheysometimesdontneedtoopenthelargesystem,starttheslowerintegrateddevelopmentenvironmenttoreadrewritecode,youjustneedtothroughthesmalltexteditor.Butmostsmalltexteditorisnothighlightedkeywordsinyourcode,orclosedsourcesoftwareitself,notaccordingtotheneedtochangethehighlightedkeywordslist,orsoftwareversiononlyWindowsorLinuxversionofthemovingplatformplantsexisbad,itdoesntmeetoftenneedtocrossbetweendifferentsoftwaresystemplatformdevelopmentdemandforprogrammers,andevenaffecttheirworkefficiency.ThissystemUSEStheplatformportabilitybetterQttodeveloplanguage,youjustneedtorecompile,betweentheplatformandcodeeasytoreadgoodreusability,programmersonlyneedtomodifythecodeinthekeywordslistoraccordingtotheneedtocustomizeyourhighlightedkeywordslist,thissoftwareprovidesconvenienceforprogrammerstoreadrewritingcode.Keywords:multipledocumenteditor;plugins;customhighlightII目录摘要IAbstractII1绪论111现实背景和理论背景112研究目的和意义1121目的1122意义12软件需求分析23开发模型的确定331软件工程及其开发模型概述3311软件工程3312开发模型概述332确定增量模型64QT简介741QT支持的平台742QT的不同发行版本75多文本编辑器的设计和实现851信号/槽机制8511信号/槽机制概述8512一个小例子9513信号11514槽11515元对象信息12516一个实际应用的例子1352QMDIAREA类14521多文档界面程序14522QMDIAREA类1453QSYNTAXHIGHLIGHTER类1654插件的实现机制1755插件的优点18551插件机制加快运行速度18552插件机制使软件的后期维护变得简单1856编写QT插件18561较高级的API18562较低级的API1957QT插件分类19571动态加载的插件19572静态插件206运行测试及界面217关键代码及注释27结论45III参考文献46致谢4701绪论1.1现实背景和理论背景虽然目前国内外的多文本编辑器种类已经不胜其数,在实际应用中,根据自己的需求找到一款很顺手的编辑器却不是每个人都能做到的.windows下绝大多数用户不二的选择的microsoftoffice尽管强大,但它所有的功能并不被人们所一一掌握,程序的庞大对于不需要它额外功能的用户来说,装载如此庞杂的程序到内存并不是必须的,无形中浪费了用户的时间.而Linux下最受欢迎的编辑器非Emacs莫属,通过加载各种插件它的功能已经不再局限于文本编辑器,完全可以胜任编译与测试方面的工作,深受程序员的青睐.然而作为程序员在实际工作中,有时候并不需要那些诸如编译之类的功能,有时候他们只是需要阅读学习或者稍微改动一些代码.这时候,他们需要的是一个轻便、无需浪费过多内存的多文本编辑器,便于多个程序代码之间参照读写。本课题的实践完成了这一需求,并借助于Qt语言“编码一次,多次部署,多平台运行”的宗旨,成功的实现了一个软件的多平台运行。目前,该文本编辑器支持windows、linux和Android三个平台。1.2研究目的和意义1.2.1目的满足广大程序员的现实需求,实现一个可以多平台运行、自定义高亮显示方案的轻便多文本编辑器。1.2.2意义通过该课题的研究,我们能更好地了解在实践中,针对用户分别定制软件需求的重要性。通过在实践中努力贯彻软件工程的思想,可以体会软件工程带给研发工作的高效性。培养自己自主学习的能力,尝试独立完成项目,并总结经验,积累成长。12软件需求分析根据以上在绪论中的分析,我们将满足广大程序员的现实需求,实现一个可以多平台运行、自定义高亮显示方案的轻便多文本编辑器。该软件要实现的具体功能如下所列:多文本编辑器的功能:1.维护各个编辑器的独立状态。2.可以打开多个编辑器,保证各个编辑器简单的复制、粘贴、删除等功能的实现。3.通过主窗口的菜单实现对各个编辑器状态的改变。4.帮助菜单选项显示软件帮助信息。5.实现各个编辑窗口的整理排序,以级联的方式排序各个窗口,方便用户快速文本概要信息。6.通过菜单随时调用显示当前编辑窗体之前之后的相邻窗体。高亮显示端功能:1.设定的搞定显示关键字实现高亮显示。2.保证高亮显示这一功能在编辑器中的正确调用。插件功能:根据当前编辑文件的类型正确的加载相应的自定义插件。根据插件加载情况,实时地在终端打印,方便用户根据需要修改插件。23开发模型的确定3.1软件工程及其开发模型概述3.1.1软件工程该软件的开发完全应用软件工程的思想-将工程化应用于软件来提高软件开发的效率。目前,业界对于软件工程这一概念有以下观点:1.软件工程遵循创立与使用健全的工程原则,以便经济地获得可靠且高效率的软件。2.软件工程需应用系统化,遵从原则,可被计量的方法来发展、操作及维护软件;也就是把工程应用到软件上。3.软件工程是与开发、管理及更新软件产品有关的理论、方法及工具。4.软件工程一种知识或学科,目标是生产质量良好、准时交货、符合预算,并满足用户所需的软件。5.软件工程实际应用科学知识在设计、建构计算机程序,与相伴而来所产生的文件,以及后续的操作和维护上。6.软件工程使用与系统化生产和维护软件产品有关之技术与管理的知识,使软件开发与修改可在有限的时间与费用下进行。7.软件工程是建造由工程师团队所开发之大型软件系统有关的知识学科。8.软件工程是对软件分析、设计、实施及维护的一种系统化方法。9.软件工程是以系统化地应用工具和技术于开发以计算机为主的应用。10.软件工程是关于设计和开发优质软件3.1.2开发模型概述软件工程中,常用的开发模型有四种:瀑布模型、原型模型、增量模型和螺旋模型。瀑布模型包括计划,需求分析、设计、编码、测试、运行维护六个阶段,如图1所示,阶段自上而下,相互衔接,次序固定。瀑布模型具有很强的顺序性和依赖性,即:下一阶段必须以上一阶段的完成为前提。测试工作是在处于开发后期的测试阶段集中进行的,测试中可能发现大量的错误,因此必须返回需求分析、设计或编著码中定位问题,而以前认为已完成的各阶段必须修改,从而代价昂贵。3图1瀑布模型原型模型的主要思想是先通过需求分析并建立一个软件系统的概貌原型(如图2),通过用户与开发者的评价和判断,不断的对原型进行反复的扩充、改进和求精,最终建立符合用户需求的目标系统。开发过程中可能会多次生成更完善的原型,测试人员要对每个原型进行测试,并且在每个原型中投入的工作量及测试目标也将有所不同。图2原型模型4增量模型(如图3)与原型实现模型和其他演化方法一样,本质上是迭代的,但与原型实现不一样的是其强调每一个增量均发布一个可操作产品。早期的增量是最终产品的“可拆卸”版本,但提供了为用户服务的功能,并且为用户提供了评估的平台。图3增量模型螺旋型开发模型结合了瀑布模型和原型模型的特点,并且加入了二者所忽略的风险分析。螺旋模型的每个周期都包含制定计划,风险分析、实施工程和评审四个阶段,如图4所示。开发过程每迭代一次,螺旋线就增加一周,软件开发前进一个层次,系统生成一个新版本,软件开发时间与成本又有新投入,最后得到一个用户满意的软件版本。5图4增量模型3.2确定增量模型基于实际分析后,我认为既然不能一次实现所有的软件框架,那么把需求分解,一点点的累加实现是可行的,这比较贴近增量模型的概念。于是,我把项目的需求分为多文本编辑器、文本高亮显示、插件加载实现附加功能三大块来逐步累加实现。64Qt简介Qt是一个多平台的C+图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的很容易扩展,并且允许真正地组件编程。自从1996年早些时候,Qt进入商业领域,它已经成为全世界范围内数千种成功的应用程序的基础。Qt也是流行的Linux桌面环境KDE的基础,KDE是所有主要的Linux发行版的一个标准组件。4.1Qt支持的平台1.MS/Windows-95、98、NT4.0、ME、和20002.Unix/X11-Linux、SunSolaris、HP-UX、CompaqTru64UNIX、IBMAIX、SGIIRIX和其它很多X11平台3.Macintosh-MacOSX4.Embedded-有帧缓冲(framebuffer)支持的Linux平台。Qt是最初奇趣科技的一个产品,是一个跨平台C+图形用户界面应用程序开发框架,2012年该公司被,Qt被Digia收购,现由其维护运营。4.2Qt的不同发行版本Qt企业版和Qt专业版:提供给商业软件开发。它们提供传统商业软件发行版并且提供免费升级和技术支持服务。企业版比专业版多一些扩展模块。Qt自由版:是Qt仅仅为了开发自由和开放源码软件提供的Unix/X11版本。在Qt公共许可证和GNU通用公共许可证下,它是免费的。Qt/嵌入式自由版:是Qt为了开发自由软件提供的嵌入式版本。在GNU通用公共许可证下,它是免费的。75多文本编辑器的设计和实现在多文本编辑器的实现中不得不提的是Qt用于对象间的通讯的信号/槽机制和用来实现多文档界面(MultipleDocumentInterface)的widget类QMdiArea。5.1信号/槽机制5.1.1信号/槽机制概述信号/槽机制是Qt的一个中心特征并且也许是Qt与其它工具包的最不相同的部分。在图形用户界面编程中,我们经常希望一个窗口部件的一个变化被通知给另一个窗口部件。更一般地,我们希望任何一类的对象可以和其它对象进行通讯。例如,如果我们正在解析一个XML文件,当我们遇到一个新的标签时,我们也许希望通知列表视图我们正在用来表达XML文件的结构。较老的工具包使用一种被称作回调的通讯方式来实现同一目的。回调是指一个函数的指针,所以如果你希望一个处理函数通知你一些事件,你可以把另一个函数(回调)的指针传递给处理函数。处理函数在适当的时候调用回调。回调有两个主要缺点。首先他们不是类型安全的。我们从来都不能确定处理函数使用了正确的参数来调用回调。其次回调和处理函数是非常强有力地联系在一起的,因为处理函数必须知道要调用哪个回调。在Qt中我们有一种可以替代回调的技术。我们使用信号和槽。当一个特定事件发生的时候,一个信号被发射。Qt的窗口部件有很多预定义的信号,但是我们总是可以通过继承来加入我们自己的信号。槽就是一个可以被调用处理特定信号的函数。Qt的窗口部件又很多预定义的槽,但是通常的习惯是你可以加入自己的槽,这样你就可以处理你所感兴趣的信号。信号和槽的机制是类型安全的:一个信号的签名必须与它的接收槽的签名相匹配。(实际上一个槽的签名可以比它接收的信号的签名少,因为它可以忽略额外的签名。)因为签名是一致的,编译器就可以帮助我们检测类型不匹配。信号和槽是宽松地联系在一起的:一个发射信号的类不用知道也不用注意哪个槽要接收这个信号。Qt的信号和槽的机制可以保证如果你把一个信号和一个槽连接起来,槽会在正确的时间使用信号的参数而被调用。信号和槽可以使用任何数量、任何类型的参数。它们是完全类型安全的:不会再有回调核心转储(coredump)。从QObject类或者它的一个子类(比如QWidget类)继承的所有类可以包含信号和槽。当对象改变它们的状态的时候,信号被发送,从某种意义上讲,8它们也许对外面的世界感兴趣。这就是所有的对象通讯时所做的一切。它不知道也不注意无论有没有东西接收它所发射的信号。这就是真正的信息封装,并且确保对象可以用作一个软件组件。槽可以用来接收信号,但它们是正常的成员函数。一个槽不知道它是否被任意信号连接。此外,对象不知道关于这种通讯机制和能够被用作一个真正的软件组件。我们可以把许多信号和你所希望的单一槽相连,并且一个信号也可以和你所期望的许多槽相连。把一个信号和另一个信号直接相连也是可以的。(这时,只要第一个信号被发射时,第二个信号立刻就被发射。)图5是一个关于一些信号和槽连接的摘要图。总体来看,信号和槽构成了一个强有力的组件编程机制。图5一个关于一些信号和槽连接的摘要图5.1.2一个小例子一个最小的C+类声明如下:classFoopublic:Foo();intvalue()constreturnval;voidsetValue(int);9private:intval;一个小的Qt类如下:classFoo:publicQObjectQ_OBJECTpublic:Foo();intvalue()constreturnval;publicslots:voidsetValue(int);signals:voidvalueChanged(int);private:intval;这个类有同样的内部状态,和公有方法来访问状态,但是另外它也支持使用信号和槽的组件编程:这个类可以通过发射一个信号,valueChanged(),来告诉外面的世界它的状态发生了变化,并且它有一个槽,其它对象可以发送信号给这个槽。所有包含信号和/或者槽的类必须在它们的声明中提到Q_OBJECT。槽可以由应用程序的编写者来实现。这里是Foo:setValue()的一个可能的实现:voidFoo:setValue(intv)if(v!=val)val=v;emitvalueChanged(v);emitvalueChanged(v)这一行从对象中发射valueChanged信号。正如你所能看到的,你通过使用emitsignal(arguments)来发射信号。下面是把两个对象连接在一起的一种方法:Fooa,b;connect(&a,SIGNAL(valueChanged(int),&b,SLOT(setValue(int);b.setValue(11);/a=undefinedb=11a.setValue(79);/a=79b=79b.value();调用a.setValue(79)会使a发射一个valueChanged()信号,b将会在它的setValue()槽中接收这个信号,也就是b.setValue(79)被调用。接下来b会发射同样的valueChanged()信号,但是因为没有槽被连接到b的valueChanged()信号,所以没有发生任何事(信号消失了)。10注意只有当v!=val的时候setValue()函数才会设置这个值并且发射信号。这样就避免了在循环连接的情况下(比如b.valueChanged()和a.setValue()连接在一起)出现无休止的循环的情况。这个例子说明了对象之间可以在互相不知道的情况下一起工作,只要在最初的时在它们中间建立连接。预处理程序改变或者移除了signals、slots和emit这些关键字,这样就可以使用标准的C+编译器。在一个定义有信号和槽的类上运行moc。这样就会生成一个可以和其它对象文件编译和连接成引用程序的C+源文件。5.1.3信号当对象的内部状态发生改变,信号就被发射,在某些方面对于对象代理或者所有者也许是很有趣的。只有定义了一个信号的类和它的子类才能发射这个信号。例如,一个列表框同时发射highlighted()和activated()这两个信号。绝大多数对象也许只对activated()这个信号感兴趣,但是有时想知道列表框中的哪个条目在当前是高亮的。如果两个不同的类对同一个信号感兴趣,你可以把这个信号和这两个对象连接起来。当一个信号被发射,它所连接的槽会被立即执行,就像一个普通函数调用一样。信号/槽机制完全不依赖于任何一种图形用户界面的事件回路。当所有的槽都返回后emit也将返回。如果几个槽被连接到一个信号,当信号被发射时,这些槽就会被按任意顺序一个接一个地执行。信号会由moc自动生成并且一定不要在.cpp文件中实现。它们也不能有任何返回类型(比如使用void)。关于参数需要注意。我们的经验显示如果信号和槽不使用特殊的类型,它们都可以多次使用。如果QScrollBar:valueChanged()使用了一个特殊的类型,比如hypotheticalQRangeControl:Range,它就只能被连接到被设计成可以处理QRangeControl的槽。简单的和教程1的第5部分一样的程序将是不可能的。5.1.4槽当一个和槽连接的信号被发射的时候,这个操被调用。槽也是普通的C+函数并且可以像它们一样被调用;它们唯一的特点就是它们可以被信号连接。槽的参数不能含有默认值,并且和信号一样,为了槽的参数而使用自己特定的类型是很不明智的。因为槽就是普通成员函数,但却有一点非常有意思的东西,它们也和普通成员函数一样有访问权限。一个槽的访问权限决定了谁可以和它相连:一个publicslots:区包含了任何信号都可以相连的槽。这对于组件编程来说非常有用:你生成了许多对象,它们互相并不知道,把它们的信号和槽连11接起来,这样信息就可以正确地传递,并且就像一个铁路模型,把它打开然后让它跑起来。一个protectedslots:区包含了之后这个类和它的子类的信号才能连接的槽。这就是说这些槽只是类的实现的一部分,而不是它和外界的接口。一个privateslots:区包含了之后这个类本身的信号可以连接的槽。这就是说它和这个类是非常紧密的,甚至它的子类都没有获得连接权利这样的信任。我们也可以把槽定义为虚的,这在实践中被发现也是非常有用的。信号和槽的机制是非常有效的,但是它不像“真正的”回调那样快。信号和槽稍微有些慢,这是因为它们所提供的灵活性,尽管在实际应用中这些不同可以被忽略。通常,发射一个和槽相连的信号,大约只比直接调用那些非虚函数调用的接收器慢十倍。这是定位连接对象所需的开销,可以安全地重复所有地连接(例如在发射期间检查并发接收器是否被破坏)并且可以按一般的方式安排任何参数。当十个非虚函数调用听起来很多时,举个例子来说,时间开销只不过比任何一个“new”或者“delete”操作要少些。当你执行一个字符串、矢量或者列表操作时,需要“new”或者“delete”,信号和槽仅对一个完整函数调用地时间开销中的一个非常小的部分负责。无论何时你在一个槽中使用一个系统调用和间接地调用超过十个函数的时间是相同的。在一台i585-500机器上,你每秒钟可以发射2,000,000个左右连接到一个接收器上的信号,或者发射1,200,000个左右连接到两个接收器的信号。信号和槽机制的简单性和灵活性对于时间的开销来说是非常值得的,你的用户甚至察觉不出来。图6是一个一个信号和槽连接的例子。图6一个信号和槽连接的例子5.1.5元对象信息元对象编译器(moc)解析一个C+文件中的类声明并且生成初始化元对象的C+代码。元对象包括所有信号和槽函数的名称,还有这些函数的指针。元对象包括一些额外的信息,比如对象的类名称。你也可以检查一个对象是否继承了一个特定的类,比如:if(widget-inherits(QButton)/是的,它是一个PushButton、RadioButton或者其它按钮。125.1.6一个实际应用的例子这是一个注释过的简单的例子(代码片断选自qlcdnumber.h)。#includeqframe.h#includeqbitarray.hclassQLCDNumber:publicQFrameQLCDNumber通过QFrame和QWidget,还有#include这样的相关声明继承了含有绝大多数信号/槽知识的QObject。Q_OBJECTQ_OBJECT是由预处理器展开声明几个由moc来实现的成员函数,如果你得到了几行“virtualfunctionQButton:classNamenotdefined”这样的编译器错误信息,你也许忘记运行moc或者忘记在连接命令中包含moc输出。public:QLCDNumber(QWidget*parent=0,constchar*name=0);QLCDNumber(uintnumDigits,QWidget*parent=0,constchar*name=0);它并不和moc直接相关,但是如果你继承了QWidget,你当然想在你的构造器中获得parent和name这两个参数,而且把它们传递到父类的构造器中。一些解析器和成员函数在这里省略掉了,moc忽略了这些成员函数。signals:voidoverflow();当QLCDNumber被请求显示一个不可能值时,它发射一个信号。如果你没有留意溢出,或者你认为溢出不会发生,你可以忽略overflow()信号,也就是说你可以不把它连接到任何一个槽上。另一方面如果当数字溢出时,你想调用两个不同的错误函数,很简单地你可以把这个信号和两个不同的槽连接起来。Qt将会两个都调用(按任意顺序)。publicslots:voiddisplay(intnum);voiddisplay(doublenum);voiddisplay(constchar*str);voidsetHexMode();voidsetDecMode();voidsetOctMode();voidsetBinMode();voidsmallDecimalPoint(bool);一个槽就是一个接收函数,用来获得其它窗口部件状态变或的信息。QLCDNumber使用它,就像上面的代码一样,来设置显示的数字。因为display()是这个类和程序的其它的部分的一个接口,所以这个槽是公有的。几个例程把QScrollBar的newValue信号连接到display槽,所以LCD数字可以继续显示滚动条的值。请注意display()被重载了,当你把一个信号和这个槽相连的时候,Qt将13会选择适当的版本。如果使用回调,你会发现五个不同的名字并且自己来跟踪类型。一些不相关的成员函数已经从例子中省略了。5.2QMdiArea类5.2.1多文档界面程序在主窗口的中央区域能够提供多个文档的应用程序就被称作多文档界面应用程序(MultipleDocumentInterface)。Qt中的QMidArea类为Qt程序实现多文档界面提供了途径。5.2.2QMdiArea类QMdiArea类,本质上更像一个MDI窗口的窗口管理器。例如,它绘出了它管理的窗口本身,并把它们组织成级联模式或砖模式。QMdiArea通常被用作QMainWindow的中心部件来创建MDI应用程序,但是也可以放置在任何布局中。下面的代码说明了如何添加了一个QMdiArea到主窗口QMainWindow:QMainWindow*mainWindow=newQMainWindow;mainWindow-setCentralWidget(mdiArea);QMdiArea中的子窗口是QMdiSubWindow.类的实例,它们通过addSubWindow()函数被:加到多文本界面区域。子窗口获得键盘焦点或它的setFocus()函数被调用后可以变得活跃,用户通常可以将光标移到子窗口上来使它被激活。当活动窗口变化时多文本界面区域发出subWindowActivated()信号,activeSubWindow()函数返回当前活动的窗口对象。调用subWindowList()函数,程序可以方便的得到一个所有子窗口的列表。子窗口可以按当前预定义的排序方案WindowOrder进行排序。子窗口部件QMdiArea提供了两个内置的布局策略:cascadeSubWindows()和tileSubWindows()来对所有级联排序(如图7)和砖排序窗口(如图8)进行。两者通过信号和槽机制都是很容易和菜单条目相关联的。14图7级联排序图8砖排序155.3QSyntaxHighlighter类要自定义Highlighter每个Editor中的文本语法高亮显示方案,必须对Qt中文本语法高亮显示类-QSyntaxHighlighter类进行特化。因此,我们定义了一个继承自QSyntaxHighlighter类Highlighter来实现特定关键字的高亮显示。这里,对QSyntaxHighlighter进行简单介绍:QSyntaxHighlighter允许你定义语法高亮显示规则,也可以通过这个类来查询当前文本的格式和用户数据。它是一个用来实现QTextDocument语法高亮显示的基类,他可以自动高亮显示QTextDocument的特定文本。语法高亮显示常用于当用户输入文本在一个特定的格式(例如源代码)时,帮助用户阅读文本,找出语法错误。图9是一个应用QSyntaxHighlighter的例子。自定义文本高亮显示方案,我们必须子类化QSyntaxHighlighter并且重写highlightBlock()方法。当你构造QSyntaxHighlighter子类的实例时,需要传入一个QTextDocument类型的参数其告知编译器你希望高亮显示方案的应用文本区域,例如:QTextEdit*editor=newQTextEdit;MyHighlight*highlight=newMyHighlight(editor-document();之后,当程序需要时你定义的highlightBlock()方法会被自动调用,用你自定义的highlightBlock()函数应用格式于部分文本(例如,设置字体和颜色)。QSyntaxHighlighter提供setFormat()函数来给定QTextCharFormat并将其应用于当前的文本块。例如:voidMyHighlighter:highlightBlock(constQString&text)QTextCharFormatmyClassFormat;myClassFormat.setFontWeight(QFont:Bold);myClassFormat.setForeground(Qt:darkMagenta);QStringpattern=bMyA-Za-z+b;QRegExpexpression(pattern);intindex=text.indexOf(expression);while(index=0)intlength=expression.matchedLength();setFormat(index,length,myClassFormat);index=text.indexOf(expression,index+length);16图9应用QSyntaxHighlighter的例子5.4插件的实现机制Qt插件由共享库(Unix/Linux上的.so以及Windows上的.dll)实现。简单来说,一切关于共享库的知识,在Qt插件上同样适用。Qt插件根本上说就是符合某些规定的共享库。从另外一方面说,插件架构是不同于普通的链接的。我们可以将插件理解成一种动态链接技术,而非插件则是静态链接。插件系统机制是,核心系统指定接口和交换的数据格式(通常是以API的形式给出)。这种接口和特定的数据格式形成一种协议,不同模块通过这种协议与核心系统进行交互,或者是能够通过核心系统将自己的某些功能暴露出来(也就是为其它模块提供服务)。仅仅将所需要的功能放到动态链接库里面并不能满足一些特定的需求,比如,我们希望应用程序能够自动发现某一特定文件夹下的动态链接库,能够知道这些动态链接库内部的逻辑是怎样的,我们能够如何使用它们。这些需求,对于一个普通的动态链接库模块是不能实现的(或者说,不是自动提供的功能,而需要编写额外的代码)。于是,我们需要一个插件架构。一般来说,动态链接库能够对外暴露出的是一系列函数。对于链接库内部的变量、类以及对象则不能直接访问。编写插件则可以绕过这个限制,插件内部的变量、对象都可以直接对应用程序暴露出来。175.5插件的优点5.5.1插件机制加快运行速度在Qt中,在插件的运行采用的是一种叫延时加载的模式,也就是只有在平台或是其他插件需要调用某一插件时,操作系统才将该插件调入到内存,但在内存紧张时操作系统可将部分插件从内存中清除掉,这样就明显提高了内存的利用率,正因为此延时加载机制,在Qt住主程序平台启动时,会发现采用插件机制的启动速度较不采用插件机制的平台相对的明显加快。5.5.2插件机制使软件的后期维护变得简单当我们针对于插件的客户需求有变化时,我们只需要重新编译更新插件即可,没必要完全更新软件系统,这使得软件更新的成本变得简单,容易,使客户更易于接受。5.6编写Qt插件Qt提供了两种API创建插件:较高级的API用来编写扩展Qt本身:自定义数据库驱动程序,图像格式,文本编解码器,自定义风格等。较低级别的API扩展Qt应用程序。例如,如果您想要编写一个定制的QStyle子类,Qt应用程序动态地加载它,您将使用更高级的API。因为高级API是建立在低级API之上,所以有一些问题是互通的。如果你想提供插件使用Qt设计器,请参考Qt设计器模块的文档。5.6.1较高级的API较高级的API:扩展Qt本身:编写一个插件,扩展了Qt本身的插件,是通过子类化适当的插件基类,实现一些功能,并添加一个宏。Qt有几个插件基类。子类插件默认存储在父类插件目录的子目录。,如果按此规则他们不存储在正确的目录。Qt将会找不到插件,导致插件无法运行。写一个插件通过以下方式完成:写适当的插件基类的子类,实现几个函数,再添加一个宏。一共有五个插件基类。派生的插件缺省保存于标准插件目录,如图10。18图10插件基类及其插件缺省目录5.6.2较低级的API较低级的API:扩展Qt应用程序.不仅Qt本身,而且Qt应用程序可以通过插件来扩展。这就要求应用程序发现和使用QPluginLoader加载插件。在这种情况下,插件可以提供任意功能和不限于数据库驱动程序,图像格式,文本编解码器,风格,和其他类型的插件,来扩展Qt的功能。使应用程序通过插件扩展包括以下步骤:1.定义一组接口(只有纯虚函数的类)用于跟插件。2.使用Q_DECLARE_INTERFACE()宏告诉Qt的元对象系统的接口。3.在应用程序中使用QPluginLoader加载插件。使用qobject_cast()来测试是否一个插件实现给定的接口。编写一个插件包括以下步骤:1.声明一个插件类,它继承了QObject和插件希望提供的接口。2.使用Q_INTERFACES()宏告诉Qt的元对象系统的接口。3.出插件使用Q_PLUGIN_METADATA()宏。4.用正确的.pro文件配置构建插件。5.7Qt插件分类5.7.1动态加载的插件因为插件存储在标准插件目录,Qt应用会自动知道哪些插件可用。因此应用程序不需要任何代码来查找和加载插件,Qt程序会自动识别调用这些插件。在软件部署中,插件通常被部署在的目录是QTDIR/plugins(QTDIR代表Qt的安装目录),与每一种类型的插件目录的类型,例如风格。如果你想让你的应用程序使用的插件不放在标准的插件路径,你需要使用QSettings,为应用程序在运行时读取安装过程确定的路径要使用插件,并保存路径,。应用程序会调用QCoreApplication:addLibraryPath()这个方法和你的插件将提供给应用程序来使插件正确加载。图11为改项目软件运行时插件的动态加载且终端显示输出。19图11运行时插件的动态加载,终端显示输出5.7.2静态插件最通用和最灵活的让应用程序包含一个插件方式是:,编译成动态库,插件在程序运行时被检测和加载。静态插件可以打包成静态库链接到应用程序。如果你构建Qt的静态版本,这是唯一的选择只能是链接Qt的预定义的插件。使用静态插件虽然可以避免部署时出错,但缺点是正确的部署程序前提要求每个插件都正确。我们需要使用QTPLUGIN宏来添加所需的插件,从而实现插件的静态链接。构建时qmake会自动生成Q_IMPORT_PLUGIN()宏来注册插件到应用程序项目中。206运行测试及界面软件开发工作基本完成之后,笔者对软件进行了简单的黑盒测试。如图12,软件实现了基本的编辑器功能并在终端显示加载了普通文本高亮显示插件。图12多文本编辑器基本功能测试About对话框显示软件版权信息,如图13图13About对话框AboutQt对话框显示软件编辑所用的Qt版本信息,如图14。21图14AboutQt对话框文件菜单运行如图15所示22图15File菜单图16为编辑菜单选项,当编辑窗口中有文本被选中是,菜单中剪切和复制功能变得可用,剪切和复制按钮也变得可用,否则不可用如图17。图16复制剪切可用23图17剪切、复制不可用window菜单显示了窗体选项,列出了当前所有窗体,并提供了窗体排序功能、显示方式以及关闭标签选项,如图18。图18window菜单显示了窗体选项24帮助菜单显示软件相关信息,如图19,提供了两个选项卡分别显示该编辑器软件信息和编写该软件所用的Qt版本信息。图19帮助菜单显示软件相关信息为了用户的文件安全,多文本编辑器还做到了关闭文档时系统提示保存,如图20所示。图20关闭系统提示保存在保存对话框,用户可以选择保存路径,如图21,默认目录为编辑器可执行文件所在目录。25图21其他功能已在前面各章节说明,在此不再赘述。267关键代码及注释该多文本编辑器项目部署结构如图22所示图22Qt中项目选项卡/表明项目依赖关系TEMPLATE=subdirsSUBDIRS=highlightplugins27mdieditormdieditor.depends=highlightplugins/editor.h中定义包含了高亮显示类及interface的接口类#include#include#includeinterfaces.hQT_BEGIN_NAMESPACEclassQTextDocument;QT_END_NAMESPACE/*以下为Highlighter类定义部分,它们放在一个文件中,便于共享全局变量*/classHighlighter:publicQSyntaxHighlighterQ_OBJECTpublic:friendclassEditor;public:Highlighter(QTextDocument*parent=0);boolloadPlugin();protected:voidhighlightBlock(constQStringprivate:structHighlightingRuleQRegExppattern;QTextCharFormatformat;QVectorhighlightingRules;QRegExpcommentStartExpression;QRegExpcommentEndExpression;QTextCharFormatkeywordFormat;QTextCharFormatclassFormat;QTextCharFormatsingleLineCommentFormat;QTextCharFormatmultiLineCommentFormat;QTextCharFormatquotationFormat;QTextCharFormatfunctionFormat;28Interface*interfaces;#endif/HIGHLIGHTER_H#ifndefEDITOR_H#defineEDITOR_H#include/#includehighlighter.hQT_BEGIN_NAMESPACEclassQTextEdit;QT_END_NAMESPACE/!0classEditor:publicQTextEditQ_OBJECTpublic:Editor(QWidget*parent=0);voidnewFile();boolsave();boolsaveAs();QSizesizeHint()const;QAction*windowMenuAction()constreturnaction;staticEditor*open(QWidget*parent=0);staticEditor*openFile(constQString&fileName,QWidget*parent=0);protected:voidcloseEvent(QCloseEvent*event);privateslots:voiddocumentWasModified();private:boolokToContinue();boolsaveFile(constQString29voidsetCurrentFile(constQStringboolreadFile(constQStringboolwriteFile(constQStringQStringstrippedName(constQStringQStringcurFile;boolisUntitled;QAction*action;Highlighter*highlighter;#endif/interfaces.h中定义了接口方法#ifndefINTERFACES_H#defineINTERFACES_H#includeQT_BEGIN_NAMESPACEclassQString;classQStringList;QT_END_NAMESPACE/!0classInterfacepublic:virtualInterface()virtualQStringListsetkeywordPatterns()const=0;QT_BEGIN_NAMESPACE#defineInterface_iidorg.qt-project.Qt.Examples.InterfaceQ_DECLARE_INTERFACE(Interface,Interface_iid)/Q_DECLARE_INTERFACE宏登记接口IDQT_END_NAMESPACE30#endif/java高亮显示插件中设置高亮显示关键字的方法QStringListJavaPlu

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论