如何用C#编写文本编辑器

如何用C#编写文本编辑器
如何用C#编写文本编辑器

摘要

本文探讨了使用C#从底层开发一个带格式的文本编辑器的任务,深入探讨了其中的文档对象模型的设计,图形化用户界面的处理和用户操作的响应,说明了其中的某些技术问题和解决之道。

前言

小弟从大学里开始接触编程也有6年了,工作4年也是干编程的活,见过不少程序,自己也编过不少,在学校编程自己觉得是搞艺术品,其实玩一些游戏,比如文明法老王星际等从某些角度看也是搞艺术品,看着自己苦心经营的建筑物和人员由少变多,由简单变复杂,心中有些成就感。编程也一样,程序从几十行写到上万行,功能由HellowWord到相当复杂而强大,心中也有不少成就感。

毕业后工作,才渐渐感悟软件开发本质上是做一个工具,这个工具给别人或者自己用。有了工具,很多问题就迎刃可解了。如此开来偶们程序员和石匠铁匠木匠是同一类人了。不过没什么,程序员本来就没高人一等,人在社会,认认真真的工作就行了。

问题

废话不多说了,现在谈谈标题提出的问题,如何用C#编写文本编辑器。本人有幸开发过一个比较复杂的文本编辑器,因此也算有点经验吧,在此来分享一下。这里所指的文本编辑器不是简单的像Windows自带的单行或多行文本编辑框,而是类似于Word的文本编辑器。

粗看起来,一个编辑器有什么好难的,其实很难的,因为我们认为容易的事对计算机来说确实天大的问题。比如大家经常上网,可以发现最近几年很多网站登录时除了输入用户名和密码后还要输入所谓的验证码,而验证码则在输入框旁边歪歪扭扭的画了出来,就像小学一年纪的学生在一张脏纸上写的一样,这样做只是为了防止程序来模拟登录,因为歪歪扭扭的文字人类可以很容易的辨认,而计算机则很不容易辨认。

例子:注册hotmail使用的验证码,其显示的字符为8UV9BKYR 。

一个文本编辑器主要处理的问题有

文件保存格式的定义,文档保存为文本格式还是二进制格式的,文档中各个信息单元保存什么信息。文档格式很重要。

和文档存储系统的交流,也就是保存和加载文档的功能,这里的文档存储系统可以是操作系统文件子系统,数据库,网络,其实文件格式定下了,各种文档存储系统差别不大。

文档加载后的文档对象维护,面对比较复杂的文档处理,需要使用面向对象的编程思想,认真分析文档结构,将加载的文档数据一点点肢解掉,每一个最小的不可分割的文档数据转换为一个对象,然后使用一个对象树来保存文档内容的层次关系,这样构造一个文档对象树。文档编辑工作就是维护这个文档对象树了。

文档对象的排版,文档加载后需要处理整个文档对象树,计算每个对象的显示大小,然后在视图区中排列要显示的对象,包括段落和文档行的计算,然后计算对象在视图区域中的直角坐标参数。

文档的绘制,这里的绘制包括在计算机屏幕上绘制文档内容和在打印机上绘制。程序根据计算好的对象在视图区中的坐标,进行一些坐标转换,在图形输出对象上绘制对象,比如绘制一个文字或图片。由于.NET框架中,操作屏幕和打印机都是基于GDI+的,两者没有本质差别,因此一些处理的绘制代码可以绘制屏幕,也可以绘制打印机。在屏幕上绘制文档还特别需要优化,尽量减少闪烁。

环境消息的处理,环境消息指一些Windows消息,这些消息应该改变文档内容,比如鼠标键盘消息,系统粘贴板的相关消息。程序处理这些消息,修改文档对象树,向对象树插入删除或修改文档元素对象。文档对象树发生改变后需要重新对文档进行排版,处理进行段落计算和文档行计算,重新计算对象在视图区中的位置,然后根据需要刷新屏幕显示。此外还有用户选择文档内容时也要处理。

文档的保存,程序根据文档对象树生成一些数据,然后保存到文档存储系统,这一步可以看作对象序列化。

应用程序的开放性,提供二次开发的能力,提供类似VBA的功能

一个完整的功能不弱的文本编辑器结构是很复杂的,涉及到的问题非常广泛,没有数万行的代码是搞不定的,这些问题在本文是不可能一一列出来并进行讨论,在此只好挑一些重点来说说。

文档对象模型

在实际开发时不必挨个解决问题,我是首先确定文档对象树的结构,这里使用了文档对象模型的概念,其实我们已经碰到很多种文档对象模型,最多的莫过于HTML文档对象模型,我们用JavaScript来控制HTML页面内容时就是使用HTML文档对象模型,此外还有XML文档对象模型,VBA操作的是Word或Excel文档对象模型。使用文档对象模型,可将文档中所有的内容和内存中的某个对象联系起来,当应用程序修改了内存的对象的数据,则相应的文档内容就修改了。删除了内存中的对象也就删除了相应的文档内容。一些文档对象模型的思想可以参考https://www.360docs.net/doc/6c3328867.html,。

文档对象模型中有很常见的是对象的继承和重载。大家可以看看.NET类库的System.XML名称空间下定义的XML文档对象模型,你可以发现无论是XML文档对象(XMLDocument),XML节点(XMLElement)还是属性(XMLAttribute),甚至注释(XMLComment)纯文本数据(XMLText)都是从抽象类XMLNode继承过来的。这样设计的好处是可以很方便的遍历XML文档对象树,各种对象都是从XMLNode派生的,都根据各自需要重载一些成员方法,其他程序都可把这些对象都看作XMLNode来使用,利用对象方法的重载和多态性来实现各自不同的处理。

基础对象

在这种指导思想下,我也定义了一个抽象类TextElement,所有的文档对象都是从该对象派生的。该类定义了以下虚成员

Left,Top,Width,Height属性,用于表示对象在的位置和显示大小

RealLeft , RealTop 只读属性,表示对象在视图区域中的显示位置

RefreshSize 方法,用于重新计算对象的显示大小

RefreshView 方法,重新绘制对象

HandleMouseDown 方法,处理鼠标按键按下事件

HandleMouseMove 方法,处理鼠标移动事件

HandleMouseUp 方法,处理鼠标按键松开事件

FromXML 方法,从一个XML节点加载对象数据

ToXML 方法,向一个XML节点保存对象的所有的数据

由于文档内容是分层次的,因此还定义一个容器类型TextContainer,该类型从TextElement派生的,其中进行扩展来可以保存若干个子对象,它定义了以下虚成员

MaxWidth 属性,对象内容的最大宽度,一个文档显示宽度就是纸张宽度减去左右页边距的距离,文档所有的内容被限制在这个显示宽度中间,该属性和显示宽度有关ChildElements 只读属性,返回所有子对象的集合,返回类型为

System.Collections.ArrayList

AppendChild 方法,该方法参数为一个TextElement对象,本方法将该对象添加到子对象集合中

RemoveChild 方法,该方法参数为一个TextElement对象,本方法从子对象集合中删除指定的文档元素对象

RemoveChildRange 方法,该方法和RemoveChild类似,只是用于删除一批子对象InsertBefore 方法,该方法参数为两个TextElement对象,第一个参数为要新增的文档元素对象,第二个为插入点所在的文档元素对象

InsertRangeBefore 方法,该方法和InsertBefore类型,只是用于插入一批文档元素对象

在某些容器对象中存在一个特殊的子元素,该子元素为最后一个元素,并且不能删除,比如对于段落对象,在此是一种容器对象,该对象最后一个元素为一个段落结尾标记对象,该对象不能删除,而在其他类型的容器对象中也可能存在类似的结尾对象,因此在TextContainer对象中就考虑这种情况,因此定义了一套虚成员来处理

AddLastElement 虚方法,想容器对象添加段落结尾标记对象来作为最后一个对象,其他派生的容器对象可以重载该方法来实现自己的最后对象

IsLastElement 函数,该函数参数为一个TextElement对象,本函数返回指定的TextElement对象是否是最后对象,程序在删除子元素前都有调用该函数,若要删除的元素为最后元素则不应当删除

TextContainer对象还重载RefreshSize方法来重新计算所有子元素的显示大小,此外还定义了新的虚方法RefreshLine来进行分行处理,为了方便分行处理,还定义了文档行对象TextLine,文档行对象用于保存文档内容分行信息,当文档分行完毕而内容没有发生改变时重新绘制文档内容时就无需重新计算要显示的内容的坐标,文档行对象的成员有

LineSpacing 行间距,也就是本文档行下端和下文本行上端的距离

Elements 属于该文档行的所有的文档元素的集合,该属性为了编程方便

FirstElement 本文档行第一个元素

LastElement 文档行最后一个元素

RealLeft , RealTop 文档行左上角在文档视图区域中的位置

Container 本文档行所在的容器对象

ContentWidth 本文档行所有元素的宽度和

为了保存分行信息,TextContainer对象还定义了一个Lines只读属性,该属性返回System.Collections.ArrayList对象列表,该列表元素为属于该容器的所有文本行对象,容器对象执行RefreshLine进行分行的步骤为

将文本行集合Lines清空

设置所有参与分行的元素集合

从前到后的遍历所有的参与分行的元素集合中的所有子元素

若子元素对象为制表符或水平线对象则重新计算它的宽度

若子元素为一个容器对象则调用它的RefreshLine方法

向当前行的元素列表中添加元素,并累计元素的宽度和,若宽度和大于容器显示宽度(我们称为情况1)或者当前元素单独占据一行则取消向当前行添加元素并结束当前行

若当前元素是强制换行的则结束当前行

在结束当前行前,若当前元素不能出现在行尾或者下一个元素不能出现在行首则取消向当前行添加当前元素(这也算情况1)。按照书写惯例,某些字符例

如!),.:;?]}¨·ˇˉ―‖?”…∶、。〃?〆〈《「『〕〗!"'),.:;?]`|}~?是不能显示在行首,而另外一些字符例如([{·…“々〇〉》」〔〖(.[{?¥是不能显示在行尾,此外在某些特定的应用中可能还有其他类型的元素也出现这种情况,这些情况需要考虑。为此在基础元素对象类型TextElement中定义了方法CanBeLineHead 来判断元素对象是否可以出现在行首,定义了方法CanBeLineEnd来判断元素对象是否可以出现在行尾,这样字符元素对象和其他元素对象可以重载这两个方法来进行所需的判断。在进行这样的判断要特别的小心,若容器显示宽度比较小则有可能由于这种判断而导致死循环,因此还需要额外的进行反死循环的判断(当年为了发现这个错误而呕出了几十两血)。

在结束当前行时需要计算文档元素在当前行中的相对位置,若当前行是由于情况1而导致结束的则需要修正元素间距,由于文档行所有元素的宽度和不一定等于容器的显示宽度,因此若没有进行修正则文档的右边缘参差不齐,影响美观,因此需要计算元素宽度和和容器的显示宽度之差,将该宽度差比较均匀的插入到各个文档元素之间,这样文档的右边缘则比较整齐。为了保存这个修正值,在TextElement中新增一个WidthFix属性来保存该值。其实大家可以观察到IE显示文档内容时没有进行右边缘的修正而Word则进行了类似的修正若当前行是由于最后一个元素强制分行而结束的则无需进行由于情况1而导致的右边缘修正,但计算文档元素位置时需要进行文档对齐方式的修正。首先找到影响当前文本行的段落对象,获得它的对齐方式设置(左对齐,右对齐,居中对齐),根据对齐方式来计算元素见的空白,然后设置元素的WidthFix属性

此外还需要修正元素在文档行中的顶端坐标,由于同一行的文档元素高度不一定一致,此时需要遍历所有的元素,以最高的元素的高度为文档行的高度,以此计算元素在文档行中的顶端位置,以保证各个元素的低边缘在同一水平线上

结束完毕的行对象添加到容器的Lines文档行集合中,然后创建创建一个文档行对象作为当前行,如此循环直到处理了容器对象所有的内容

产生了所有的文档行对象后根据容器对象的在视图区域中的坐标和文档行的行间距设置来计算文档行在视图区域中的坐标,这样文档行中所有的元素的在视图区域中的坐标就是文档行的坐标和元素在文档行中的相对坐标的和

在修改文档行中元素的位置时,需要获得元素旧的在视图区域中的最小外切矩形数据,然后和重新计算过的最小外切矩形进行比较,若两者不一样则表示元素在视图区域中显示的位置发生改变,将这两个矩形添加到文本编辑器重绘矩形集合中,当文档重新分行完毕后,文本编辑器就将所有的重绘矩形进行加法操作,获得的矩形就是需要重新绘制的区域。如此这样是为了优化显示操作,减少页面闪烁;因为用户修改了文档内容后到而导致的分行只是影响显示区域中一部分,而其他部分虽然重新计算了位置但新旧位置没有差别,因此不需要重新绘制

其实关于分行操作应当还有更优化的方法,但本人能力有限,只能提出这种方法。试验

证明,在处理小的文档时程序运行速度还行,但当文档内容很多,有数万个字符时,分行速度就很慢,还望高手提供解决之道。

为了表示整个文档对象,还定义了文档对象TextDocument ,该对象在文档对象模型中是个最大的对象,我没有模仿其他文档对象的模式将其从TextElement派生过来的,而是直接定义的。该对象用于从整体上操作文档,并列出了一些操作文档的基本操作,比如删除,复制粘贴等。此外还提供一套方法来实现VBA的功能。

此外还定义了文档内容管理对象Content ,该对象隶属于TextDocument对象,用于管理所有的文档元素,它定义了属性Elements,该属性为一个保存了文档所有元素对象的列表。该对象还定义了属性SelectStart来表示插入点的位置,SelectLength 来表示选择区域的长度,为0表示没有选中任何元素,为正数则表示从插入点向后选中了若干个元素,为负数则表示从插入点向前选中了若干个元素。本对象还定义了一套处理插入点的函数,比如向左向右移动若干个元素,向上向下移动一行。大家都知道,在文本框中可以直接用光标键来移动插入点,也可以使用光标键时同时按下Shift键来移动插入点并选择文档内容,用户也可以用鼠标点击操作来移动插入点,鼠标点击的同时按下Shift键也能移动插入点选择文档内容;为此在Content对象定义了属性AutoClearSelection,当设置了该属性则移动插入点时设置SelectLength为0,若没有设置该属性则移动插入点时设置SelectLength值,使得新插入点和旧插入点之间的元素被选中,这样文本编辑器根据用户是否按下Shift键来设置AutoClearSelection属性就行了。用户修改了插入点和选择区域,则文本编辑器需要重新绘制用户界面,此时需要优化,只重新绘制选择状态发生改变的元素。可以证明,当选择的元素为连续的,则无论如何的修改选择区域和插入点,最多只有两片区域中的元素的选择状态发生改变。因此只要获得这两片区域的起始位置和长度,然后重新绘制这两个区域中的元素即可。

用户可以对文档进行很多种操作,比如移动插入点,选择元素,设置字符的字体颜色和大小,插入文字和图片,修改元素的设置,删除剪切复制粘贴等等,有好几十种操作,而且这些操作在某个时刻是不可用的,需要进行判断,若这些操作都在TextDocument中定义相应的接口函数,则TextDocument类代码太多,过于臃肿,而且每新增一种操作都需要修改TextDocument,因此在此提出动作这个概念。动作就是一个实现某种文档操作的类型,该类型有统一的接口,并使用TextDocument或其他对象提供的基本的操作来实现比较复杂的操作。为此定义动作基础类EditorAction,该类为抽象类,它的主要接口有

HotKey 字段,动作对应的热键代码,动作对象初始化的时候设置该动作对应的热键KeyCode 字段,触发动作时的键盘按键编码

ShiftKey 字段,触发动作时的Shift键状态

ControlKey 字段,触发动作时的Control键状态

AltKey 字段,触发动作时的Alt键状态

MouseX,MouseY 字段,触发动作时的鼠标光标在视图区域中的坐标

MouseButton 字段,触发动作时的鼠标按键状态

Param1,Param2,Param3 字段,动作的参数,其意义由具体的动作决定

TestHotKey 函数测试键盘热键,本函数由文本编辑器调用来判断是否触发某动作ActionName 只读属性,动作名称

isEnable 动作是否可用

Execute 执行动作

OwnerDocument 动作对象所操作的文档对象

各种实际的动作对象都是从EditorAction派生的,若对象有热键则在初始化时设置HotKey字段,首先重载ActionName给定一个名称,然后重载Execute来实现各自的动作处理过程,还可根据需要重载isEnable或TestHotKey。

在TextDocument中有个属性Actions,该只读属性为包含各种动作对象的列表,当TextDocument初始化时就初始化该动作对象列表,当文本编辑器获得输入焦点时按下键盘按键则程序会遍历Actions中所有的动作,进行热键判断,若命中热键则执行该动作,其他应用程序也可根据各个动作的isEnable属性来设置文本编辑功能按钮和相应菜单的可用性。

比如定义复制动作对象EditorCopyAction,该类型从EditorAction派生的,重载ActionName使其返回"copy";重载isEnable,当文档有被选中的部分则返回True否则返回False,重载Execute来调用TextDocument中实现复制功能的函数,该对象初始化的时候设置HotKey为System.Windows.Forms.Keys.Control |

System.Windows.Forms.Keys.C,这样定义了该动作的热键为Ctl+C。

这种动作处理的模式还便于程序进行扩展,其他应用程序也可往动作列表中添加自定义的动作对象,这样文本编辑器就能自动应用该动作。应用程序还可修改各种动作的热键设置来实现用户操作的个性化。

其实这种动作处理的模式我是看了SharpDevelop的文本编辑器部分的源代码而领悟的,拿过来用用,实践证明还是很不错的。

我既然做的是文本编辑器当然支持复制粘贴功能了,首先将将复制操作。程序可以同时向Windows剪贴板发送多种格式的数据,这些数据可以是纯文本的,也可以是图象或者自定义格式,其他程序在进行粘贴操作是可以选择其中所需格式的数据。例如大家在https://www.360docs.net/doc/6c3328867.html, 的代码窗体中复制某段代码,粘贴到Word和记事本中的结果是不一致的,虽然文本内容是一样的,但粘贴到Word中连代码文本的颜色也显示出来的,而记事本则是纯文本数据。大家可以用剪贴板查看器clipbrd.exe来实时查看Windows剪贴板中的内容。在.NET中向剪贴板发送数据还是比较方便的,首先实例化一个

System.Windows.Forms.DataObject对象,调用它的SetData方法,该方法第一个参数为格式的名称,第二个参数为数据,可以多次调用该方法来保存不同格式的数据,然后调用静态库函数System.Windows.Forms.Clipboard.SetDataObject 方法即可。在这个文本编辑器中复制数据时同时向系统剪切板保存两种数据,首先保存文档中被选中部分的纯文本数据,然后将被选中的部分转换为一个XML字符串,然后使用自定义的格式名称保存进去。这样其他程序就能使用其中的纯文本数据了。程序在进行粘贴操作时首先调用静态库函数System.Windows.Forms.Clipboard.GetDataObject方法,获得一个实现了System.Windows.Forms.IDataObject接口的对象,然后调用它的GetDataPresent 方法,若发现其中有我自定义的数据则读取该数据,然后将其中的数据当作字符串取出来,这是一个XML字符串,解析该XML字符串,并生成一系列的文档元素对象插入到文档当前位置,这种粘贴操作能将所有的文档元素及其格式给粘贴过来。若没有自定义数据但是有纯文本数据,则读取纯文本数据,并根据文本生成一系列文本元素对象,然后插入到文档当前位置。

VBA

文档对象还支持VBA,.NET框架支持https://www.360docs.net/doc/6c3328867.html,脚本语言,.NET类库中的类Microsoft.VisualBasic.Vsa.VsaEngine及接口Microsoft.Vsa.IVsaSite 就支持脚本语言。我参照HTML文档对象模型,在https://www.360docs.net/doc/6c3328867.html,的基础上设计一种处理文档的脚本语言,该语言中直接使用脚本全局对象document就访问了文档对象TextDocument,而使用document.all就能访问文档中的某些做了标记的文档元素对象,使用dbconnection 就能使用文本编辑器后台使用的数据库连接对象,使用eventobj访问文档编辑器触发的事件的信息,使用vbsystem来调用某些例程。首先定义一些类型,用于实现脚本全局对象dbconnection,eventobj,vbsystem的功能,而全局对象document的类型就是TextDocument,已经实现,但document.all还未实现,为此在TextDocument中新增只读属性all,该属性返回一个System.Object类型的对象,由于document.all的类型中定义的字段根据文档的内容而动态改变,因此需要使用.NET的反射机制动态的创建对象类型并实例化对象,其创建过程为

新增一个System.Reflection.AssemblyName对象,设置其Name属性为"RunTimeTextDocumentLib"

使用AppDomain.CurrentDomain.DefineDynamicAssembly来创建一个程序集生成器System.Reflection.Emit.AssemblyBuilder

使用程序集生成器的DefineDynamicModule来创建一个模块生成器

使用模块生成器的DefineType来创建一个类型生成器,类型名称为AllElements

遍历文档内容,根据名称和特定文档对象的对应关系生成一个按名称访问的哈希列表

遍历哈希列表中的名称,使用类型生成器的DefineField方法创建一个公开字段,字段类型为object类型。

使用类型生成器生成一个新的类型System.Type,然后动态创建一个该类型的实例,这样动态生成了AllElements对象

遍历文档元素对象哈希列表,使用System.Type.InvokeMember向该AllElements对象设置字段值

这样应用程序动态的创建了AllElements类型并实例化了一个对象引用,这时https://www.360docs.net/doc/6c3328867.html, 脚本程序就可以直接使用document.all.文档元素对象名称来直接访问文档中特定内容了。注意当文档内容发生改变时需要重新生成AllElements的类型并实例化。

以上的程序模块建好后就可以搭建https://www.360docs.net/doc/6c3328867.html,脚本语言运行环境了,首先定义类型TextDocumentVsaSite来实现IVsaSite接口,实现其中的GetGlobalInstance函数,该函数参数为字符串,返回一个对象,该函数实际上判断若参数"document"则返回文档对象TextDocument ,若参数为"eventobj"则返回刚刚定义了事件对象,若为"dbconnection"则返回数据库连接对象。该对象还实现了IVsaSite.OnCompilerError 来处理脚本编译错误。

程序还从Microsoft.VisualBasic.Vsa.VsaEngine派生了脚本引擎VBScriptEngine。该模块使用VsaEngine的Items.CreateItem来向引擎添加

document,eventobj,dbconnection等全局变量,还添加一些所需的.NET引用,此外还实现了对脚本代码文本的一些处理,比如加密,自动添加某些必须的代码等。

脚本环境还模拟实现了文档事件的处理,比如文档中某些元素对象支持onchange事件,这些元素是有名称的,当用户修改这些元素的内容时,程序会查询脚本引擎来看是否存在名为对象名称_OnChange的过程存在,若存在则执行它,这样就模拟实现了事件处理。

在https://www.360docs.net/doc/6c3328867.html,脚本环境中,全局对象的成员函数可以直接调用,因此在vbsystem中定义一些例程就可以直接调用,可以在vbsystem中定义诸如

Alert,ConFirm,Prompt,DebugPrint等成员函数,脚本中就能直接使用这些函数了。

访问数据库

由于应用需要,本文本编辑器要直接访问数据库,但该文本编辑器既使用于C/S程序又使用于B/S程序,当处于B/S构架时是不好直接连接数据库的,必须通过服务器程序来访问数据库。为了编程方便,应该抹杀掉这两种模式之间的差别。

大家考察一下.NET框架中操作数据库的类型,可以发现无论是专门操作SQLServer

的在System.Data.SqlClient名称空间下面的那套对象还是操作OLEDB的在System.Data.OleDb空间下面的那套对象(其他类似有专门操作ODBC和ORACLE),这些套对象间最大的共同点就是都遵循一套在名称空间System.Data下接口。这些接口包括IDataReader , IDbCommand,IDbConnection,IDbDataParameter, IDataParameterColleciton等等。若我们编了一套对象也实现了这些接口,那就相当于自定义了一套.NET数据库驱动程序。于是小弟很快根据B/S构架特性写了套对象,该套对象通过HTTP协议和WEB服务器交流数据,这套对象将SQL语句及其参数简单打包使用POST方法发送到指定的服务器页面后等待返回,服务器页面解析出SQL语句和参数查询数据库,将查询所得结果经过一定的编码返回为客户端,而客户端根据HTTP返回结果进行一番处理后就可以使用一个实现IDataReader的对象来访问了。这样在应用程序的其他模块若查询数据库则只要坚持使用System.Data.IDbConnection 等接口就可以了,如此就抹杀了C/S和B/S环境下访问数据库的差别了。

这种模式也算是一种WebService了,服务器页面可以使用任何类型,可以使用ASP,https://www.360docs.net/doc/6c3328867.html,,PHP,J2E或JSP等等,只要能解析出SQL语句并返回特定结构的数据就行了。小弟的服务器为J2E,偶JAVA不熟,勉强用JSP实现了一个。我管这种模式叫两层半,实践证明这套还是管用的。

派生对象

定义了基础对象后就开始派生对象了,首先定义字符对象类型TextChar,一个文档内容中最主要的还是字符数据,在此为了实现方便,文档中每一个字符都是一个字符对象,字符对象重载了RefreshSize对象RefreshSize方法,用于根据当前绘制用的绘图对象(System.Drawing.Graph对象)的MeasureString来计算文字大小。注意默认情况下,该方法计算的字符串显示宽度后回额外的附加一些空白,为了计算实际的大小则使用System.Drawing.StringFormat.GenericTypographic参数。此外还有一个比较特殊的字符-制表符。这个字符的宽度是不固定的,需要在进行排版的时候才计算。

字符对象(TextChar)还派生RefreshView方法,该方法比较简单,根据Left,Top值进行坐标转换后算出绘制地点,然后调用System.Drawing.Graph.DrawString方法即

可。字符对象还定义了自己的成员,比如Char属性返回对象表示的字符数据,Font表示绘制对象使用的字体,ForeColor表示绘制文本的颜色。

字符中的制表符比较特殊,因为它的宽度是不定的,而是根据它在文档视图中的位置而定的,因此在TextChar上在派生TextCharTab来转变处理这种情况,它新增了RefreshTabWidth方法,来根据对象在视图区域中的左端位置计算字符宽度。在此处我认定一个制表符步长等于四个下画线字符的宽度,制表符的右端坐标必须是制表符步长的自然数倍,因此根据制表符的位置来进行取模操作和其他操作就可以计算制表符的宽度。

为了表示段落而定义了段落对象TextParagraph,该对象不是容器对象,保存了段落对齐方式的信息,该元素的显示样式类似于Word中的段落符(硬回车)的样式。

还定义了行结束对象TextLineEnd,该对象模拟了Word的分行符(软回车)。

可以定义图片对象,经过对Word处理文档的行为观察,可以发现在Word文档中插入的图片和OLE对象特性很相似,因此为了考虑文本编辑器的可扩展性,首先在TextElement的基础派生出TextObject抽象类,该抽象类表示一个在文档中的对象,该对象由其派生的类决定。

在TextObject对象派生出TextImage表示一个图片对象,该对象重写了RefreshView方法,用于在绘图输出对象上绘制一个图片。还重载了FromXML和ToXML 方法来和XML节点交换数据,可以设计将图片二进制数据以Base64格式保存为XML节点下。

此外还可以根据应用的需要从TextObject对象上派生其他的类型,比如直接读取数据库在界面上绘制曲线图等等,此时文档中的该对象可以动态的展示系统中最新的数据。

图形化用户界面

可以观察到Word中的对象(包括图片)可以改变大小,当用鼠标点击图片对象时,图片四个角和四个边的中点上会显示8个小点。这些小点我称为控制点。用鼠标拖拽这8个点可以动态的改变对象的大小。其实在很多类型的程序中可以碰到这8控制点,例如在https://www.360docs.net/doc/6c3328867.html,的窗体设计器中,当前的控制周围就有这8个控制点。关于如何实现这8个控制点也是有一套的。

控制点可以分为内控制点和外控制点两种类型,我们对这8个点进行从0到7的编号。当鼠标光标移动到这8个控制点上方时需要设置为不同的光标样式。

内控制点

┌─────────────────┐

│■0 1■2■│

││

││

││

│■7 3■│

││

││

││

││

│■6 5■4■│

└─────────────────┘

外控制点

■■■

┌────────────────┐

│0 1 2│

││

││

││

││

■│7 3│■

││

││

││

││

│6 5 4 │

└────────────────┘

■■■

控制点上鼠标光标如下

西北-东南SizeNWSE 南北SizeNS 东北-西南SizeNESW ■■■

┌────────────────┐

│0 1 2│

││

││

││

││

■│7 西-南SizeWE 3│■西-南SizeWE

││

││

││

││

│6 5 4 │

└────────────────┘

东北-西南SizeNESW 南北SizeNS 西北-东南SizeNWSE

根据上图所示,已知主矩形,控制点的类型(是内控制点还是外控制点)和控制点的宽度可以计算出所有的控制点的位置。可以编一个例程,输入3个参数,主矩形区域的Rectangle结构体,是否是内控制点(不是内控制点就是外控制点)和控制点的宽度,该例程计算所有控制点的位置,然后返回一个包含8个Rectangle的数组,该数组就是0到7号的控制矩形的位置和大小。

TextObject对象显示后就应该知道自己在视图区域中的位置,当它相应鼠标移动消息时,就可以根据鼠标光标位置和8个控制矩形进行比较,若鼠标光标在某个控制矩形中时就要通知文本编辑器改变鼠标光标的样式。

一般的控制点被画成一个矩形方框,控制点也被画成两种类型,一种是填充色为深色(蓝色或黑色)和白色边框,另一种是深色边框并填充白色。可以观察https://www.360docs.net/doc/6c3328867.html,窗体设计器,可以在设计器中选择多个控制,其中有一个控件的控制点为填充色为蓝色和白色边框的,该控制为当前控件。而其他选择的控件的控制点为蓝色边框并填充白色,这些控件为选择控件。在文本编辑器中没有这种情况,因此在此可以使用内控制点方式,控制点用黑色填充,边框白色。

当鼠标在控制点上进行拖拽操作就应当可以动态的修改对象的大小,以前我是如此实现的

在鼠标按键按下事件处理(HandleMouseDown)中,若鼠标光标在某个控制点上则设置一个鼠标按键按下标记变量,并记下鼠标光标位置,然后退出事件处理

在鼠标移动事件中(HandleMouseMove),若设置了鼠标按键按下标记变量,则根据当前鼠标光标位置和上一次鼠标光标的位置之差就是鼠标光标移动的距离,该距离的水平分量和垂直分量就是对象宽度和高度的改变量,此时可以使用库函数

System.Windows.Forms.ControlPaint.DrawReversibleFrame在界面上绘制一个虚线框,当鼠标移动时不断的调用该库函数,这样实现了所谓的“橡皮筋”操作

在鼠标按键松开事件(HandleMouseDown)处理中,根据鼠标光标的当前位置和以前记下的鼠标按键按下时的鼠标光标位置计算两者之差,这样就是整个鼠标拖拽操作中鼠标光标移动的距离,程序就可以依据该距离来改变对象的大小

经过一些编程实践,发现该操作比较麻烦,需要编写不少代码,而且代码分散在3个事件处理过程中,多了一些全局变量,很难写出一个通用例程到处调用,经过分析,将这种处理模式改掉了。其实一般的程序正在进行鼠标拖拽操作时,用户是不可能同时进行其他操作(不如边鼠标拖拽边打字),而且进行”橡皮筋“操作时程序用户界面无需重新绘制,这样可以认为进行鼠标拖拽时应用程序应用程序只处理鼠标移动消息和鼠标松开消息而不进行任何其他操作,为了编程简单,甚至连重绘界面的操作也不处理了,因此可以编一个通用例程来处理整个的鼠标拖拽来实现“橡皮筋”操作,该函数处理过程为

在鼠标按键按下事件处理(HandleMouseDown)中就调用该例程

进入例程中,首先记下鼠标光标的当前位置,然后进入一个死循环

该死循环首先调用Win32API函数WaitMessage等待Windows消息,若没有任何Windows消息则退出该循环

调用Win32API函数PeekMessage来获得当前Windows消息

若当前消息为鼠标按键松开消息则退出循环

若当前消息为鼠标移动消息则则获得当前鼠标光标位置,根据开始脱拽的鼠标光标位置来绘制橡皮筋矩形

调用Win32API函数GetMessage将当前Windows消息给“吃”掉,然后进入下一次循环例程退出该循环后就将当前鼠标光标位置和拖拽操作前的鼠标光标位置之差,也就是鼠标光标在整个拖拽操作中移动的距离作为返回值返回给主调函数(HandleMouseDown)

主调函数接受返回的鼠标光标移动的距离,然后根据该距离来进行其他的处理,在这里就是修改对象的大小

在此插上一段,其实.NET框架还是比较适合Win32的API编程,

System.Windows.Form.Control的Handle属性就是窗体的句柄,可以被其他

Win32API作为参数调用,CreateParams属性实际上就是CreateWindowEx的参数,重载它就可以设置控件创建时的样式;WndProc就是控件处理所有的Windows消息的默认过程,也可以重载它自己来处理底层的Windows消息。

System.Windows.Forms.Application的静态函数AddMessageFilter和RemoveMessageFilter就可以很方便的为整个应用程序添加或删除"钩子"程序。C#语言可以使用System.Runtime.InteropServices.DllImport来导入声明DLL文件中的API 函数。

光标的控制

光标就是文本编辑器在获得输入焦点时在当前插入点闪烁显示的一个小方块,当文本编辑器没有获得输入焦点时就不会显示光标。Windows操作系统已经提供了一套处理光标的API函数,包括创建光标CreateCaret,设置光标位置SetCaretPos,显示光标ShowCaret 和隐藏光标HideCaret。使用API创建和显示光标后,操作系统会自动的让光标闪烁。文本编辑器要提供处理光标的例程供其他程序模块调用。文本编辑器首先根据当前插入点的位置计算光标在文档视图区域中的位置,还需要根据文档处理插入模式还是修改模式计算光标的大小。若光标所在位置在用户界面上没有显示出来则还需要滚动文本编辑器已保证光标所在区域处于可视区域。然后调用API来创建和显示光标。文本编辑器还重载OnGotFocus 过程来显示光标,重载OnLostFocus过程隐藏光标。注意重载这两个过程时需要在最后必须调用base.OnGotFocus和base.OnLostFocus,若不这样则文本编辑器嵌入在网页中运行会发生无法获得输入焦点的错误。光标控制还涉及到输入法的控制,我们中国人使用文本编辑器会使用到各种中文输入法。Windows操作系统也提供了一套API来控制输入法。在本文本编辑器中重载OnKeyPress方法来获得用户输入的字符,此时的字符可以是键盘直接输入的ASCI字符,也可以是使用某种输入法输入的汉字。这些操作系统都已经实现了,为什么还要控制输入法。原因是使用默认处理时输入法的浮动窗口会显示在屏幕中间而不会随着插入点的位置而移动。一般的中文输入法的用户界面为一个浮动窗口,各种建议输入的中文字符显示在这个浮动窗口中供人选择。想想看,当插入点在屏幕的某个边角中,而输入法的浮动窗口在屏幕中央,这样输入中文比较累。但若输入的浮动窗体随着插入点的移动而移动,浮动窗体和插入点紧密的靠在一起,这样输入中文就不是很累了。Win32API函数ImmSetCompositionWindow能对指定的窗体控制输入法浮动窗体的显示位置,当插入点改变时调用该API函数就能让输入法浮动窗体随着插入点跑了。

java文本编辑器实验报告

Java考核 课程名称Java程序设计 题目名称文本编辑器的设计与实现学生学院计算机学院 专业班级计算机17(2)班 学号3117004479 学生姓名李泽豪 指导教师赵锐 2018 年12 月11 日

一、课程题目 编程实现一个文本编辑器 使其具有新建、打开、保存,编辑(查找、替换、大小写转换等)、统计(字数、行数、字符数等)、格式(字体设置、字体大小、字体颜色、背景颜色等)等功能。 要求:基于JFrame窗体设计、使用菜单进行功能选择。 提示:字体颜色,背景颜色的设置,可使用javax.swing包中的JColorChooser类的静态方法showDialog()调用标准颜色对话框来完成;文件操作可通过javax.swing包中JColorChooser类中的showSaveDialog()、showOpenDialog()方法调用标准的的文件对话框来完成。 二、题目分析与设计 2.1开发环境 使用Eclipse开发软件 2.2需求分析 简单的文本编辑器提供给用户基本纯文本的文字编辑功能,能够读取计算机本地磁盘中的文本内容,将用户文本导入到磁盘中之中,以及实现基本的字体设置(字体,字号,字体颜色)简单的编辑字体的功能,以及统计(字数,行数,字符数),增强视觉体验的背景颜色功能等,简单而实用。而网络上的各种编辑器,有的功能不足(如自带的记事本),而有些编辑器功能太繁杂,仅以日常应用方面来说,一个文本编辑器只需要简单的功能就够了。 2.3功能构架 本程序要构建的文本编辑器按照题目要求,分为四个方面: (1)“文件”菜单:包括“新建”并提示是否保存已编辑内容,“打开”计算机本地磁盘的文本文件,主动“保存”自己已经编辑好的内容到电脑的磁盘或“另存为”新的文件之中,以及“退出”并提示是否保存已编辑的内容。 (2)“编辑”菜单:包括对已编辑文本的一个“查找与替换”功能,对已编辑英文文本的一个“大小写转换”功能。 (3)“格式”菜单:实现对文本的“字体”设置,“字体大小”以及“字体颜色”,还有

java课设—文本编辑器的设计与实现

淮 海 工 学 院 计算机工程学院
课程设计报告
设计名称: 选题名称: 姓 名: 面向对象课程设计 文本编辑器的设计与实现 学 号:
专业班级: 系 (院) : 设计时间: 设计地点: 计算机工程学院 2015.6.21~2014.7.4 计算机楼机房、教室、宿舍
指导教师评语:
成绩:
签名:
年 月 日

面向对象课程设计报告

1
页,共
14

1.课程设计目的
《面向对象程序设计》是一门实践性很强的计算机专业基础课程,课程设计是学习完该课程 后进行的一次较全面的综合练习。其目的在于通过实践加深学生对面向对象程序设计的理 论、方法和基础知识的理解,掌握使用 Java 语言进行面向对象设计的基本方法,提高运用 面向对象知识分析实际问题、解决实际问题的能力。
2.课程设计任务与要求:
课程设计可选用 NetBeans、Eclipse、JBuilder 等作为开发平台以提高开发效率,尽可能熟 练掌握其中一种集成开发环境。建议采用 UML 建模技术进行系统的分析设计,在 Visio 中画出系 统用例图和类图,并将 UML 图复制到设计报告中。 通过这次设计,要求掌握以下内容: 1)面向对象技术中的继承与多态(重载和覆盖)机制、各种修饰符的使用 2)类、包、接口的定义与使用 3)常用工具类与算法的实现(数组、向量、字符串、链表) 4)Java 常用标准 GUI 组件及其事件处理 5)Java 的异常处理机制 6)Java 的数据库连接技术 7)Java 的多线程技术与动画制作 8)Java 的网络编程 任务: 设计一个类似于 Windows 记事本(Notepad)的 Java 程序。可以打开、新建、保存一个文本 文件;对选中的文本进行各种编辑操作(设置字体、字号、字型、对齐方式、背景、前景色、复 制、粘贴、剪切、查找、替换等) ;在文本中能够插入对象。简单文本编辑器提供给用户基本的 纯文本编辑功能, 能够将用户录入的文本存储到本地磁盘中。 能够读取磁盘中现有的纯文本文件, 以及方便用户进行需要的编辑功能。

基于java的文本编辑器开发

基于java的文本编辑器开发 当今,计算机以及网络技术的飞速发展,社会正快速向信息化社会前进,我们需要更智能,更专业的软件帮助我们完成工作,从而提高了工作效率。 目前文本编辑器种类很多,所提供的功能也很多,但是能满足用户实现多种功能和进行Java的编译与运行很少,不能更好的适应当前用户的要求。本设计所完成的文本编辑器功能是针对学习Java程序语言,因此我们利用Java程序设计虚拟机和软件对用户及使用者的应用过程形成一整套完整的编写代码,编译,运行。 本文本编辑器的开发主要包括界面窗口的菜单栏和工具栏以及树结构,还有链接Java虚拟机实现编译与运行。使用SUN公司的Java中的GUI作为开发技术,利用其提供的各种类与接口,首先建立系统应用原型。 本文本编辑器的开发采用JDK6.0和 UltraEdit为开发工具,操作系统为Windows98/Windows 2000/Windows XP等。

目录 1 前言 (3) 2 问题的提出及可行性研究 (4) 2.1问题的提出及定义 (4) 2.2可行性研究 (5) 2.2.1 对现行文本编辑器的分析 (5) 2.2.2 新文本编辑器的可行性研究分析 (5) 3 用户需求分析 (7) 3.1用户调查 (7) 3.2确定目标系统的功能 (7) 4 系统设计与开发环境 (8) 4.1系统相关类的设计 (8) 4.2开发语言及其开发环境 (12) 4.2.1开发语言概述 (12) 4.2.2 Java开发环境——JDK的介绍 (14) 4.3环境变量的设置 (15) 4.3.1.环境变量的作用 (15) 4.3.2 如何设置环境变量 (16) 5 关键技术和源代码的实现 (18) 5.1关键技术剖析 (18) 5.2源码分析 (19) 6 系统测试 (46) 6.1测试方案 (46) 6.2测试项目 (46) 6.3编辑器截图演示 (47)

java文本编辑器

软件学院 课程设计报告书 课程名称 设计题目文本编辑器的设计与实现 专业班级XXXXXXXXXXX 学号xxxxxxxxxx 姓名xxx 指导教师

2011 年11月

1 设计时间 2011年11月 2 设计目的 《面向对象程序设计》是一门实践性很强的计算机专业基础课程,课程设计是学习完该课程后进行的一次较全面的综合练习。其目的在于通过实践加深学生对面向对象程序设计的理论、方法和基础知识的理解,掌握使用Java语言进行面向对象设计的基本方法,提高运用面向对象知识分析实际问题、解决实际问题的能力,提高学生的应用能力。目前文本编辑器种类很多,所提供的功能也很多,但是能满足用户实现多种功能和进行Java的编译与运行很少,不能更好的适应当前用户的要求。本设计所完成的文本编辑器功能是针对学习Java程序语言,因此我们利用Java程序设计虚拟机和软件对用户及使用者的应用过程形成一整套完整的编写代码,编译,运行。 3设计任务 文本编辑器的设计与实现:设计一个类似于Windows记事本(Notepad)的Java程序。可以打开、新建、保存一个文本文件;对选中的文本进行各种编辑操作(设置字体、字号、字型、对齐方式、背景、前景色、复制、粘贴、剪切、查找、替换等);在文本中能够插入对象。 4 设计内容 4.1需求分析 需求分析的任务是确定功能必须完成的工作,也就是对目标系统提出完整、准确、清晰、具体的要求。简单文本编辑器提供给用户基本的纯文本编辑功能,能够将用户录入的文本存储到本地磁盘中。能够读取磁盘中现有的纯文本文件,以及方便用户进行需要的编辑功能。文件操作能够实现新建、保存、打开文档等,编辑操作能过实现文本的剪贴、复制、粘贴等,格式操作能过实现字体设置、背景等,帮助操作能够实现关于主题的查看等功能。 4.2概要设计 4.2.1程序基本功能概括

Java写的简单文本编辑器代码(word文档良心出品)

import java.awt.*; import java.awt.eve nt.*; import java.io.*; public class Notepad /*impleme nts Action Liste ner , MouseListe ner , MouseMoti on Liste ner , Win dowListe ner , ItemListe ner , KeyListe ner, TextListe ner */ { //成员变量 private Menultem miNew , miOpen , miSave , miSaveAs , miExit ; // 文 件菜单项:新建,打开,保存,另存为,退出 private Menultem miCut , miCopy , miPaste , miDelete ;//编辑菜单项: 剪切,复制,粘贴,删除 private Menultem miFont , miLowtoCapital , miCapitaltoLow , miEncrypt miDisencrypt ; //格式菜单项:字体 private Menultem miAboutNotepad ; // 帮助菜单项:关于记事本 private Frame mainFrame ; // 主框架 private Men uBar mb ; // 菜单条 private Me nu mFile , mEdit , mFormat 式,帮助 mHelp ; //菜单:文件,编辑,格 private TextArea ta ; //文本区 private String tempString ; 〃临时字符串,用于存储需要复制粘贴的字符串 private boolea n textValueCha nged = false private int id_fo nt //字体 Stri ng fileName = "" ; //上次保存后的文件名和地址 //构造函数 public Notepad(){ //框架 main Frame = new Frame ( "Notepad v0.99 by Laun chi ng" ); mb = new Men uBar (); ta = new TextArea (30 ,60); ta .setFont( new Font ( "Times New Rome" , Font. PLAIN , 15)); ta .setBackground( new Color(0,250,200)); //菜单条 mFile = mEdit = new Menu ( new Menu ( "文件"); "编辑");

Java第三次作业 《文本编辑器》

《Java语言》课程期末作业 题目第6题:文本编辑器 学院计算机学院 专业网络工程 班别13级(3 )班 学号 姓名 2015年06月17日

一、课程题目 制作一个简单的文本编辑器,交互性要求:【最大选题人数:5】 (1) 可输入文字(仅要求英文及标点符号) (2) 实现一些常用的编辑功能:如复制和粘贴,查找和替换,首字母自动大写,拼写自动更正…… (3) 可打开并显示TXT文件,并且可以将编辑结果保存为TXT文件 二、题目分析与设计 1. 注明所使用的开发环境(Eclipse、NetBeans,JBuilder)。 开发环境:Eclipse

2. 论述题目的需求。给出软件功能架构图。 本题目要求实现类似于一个记事本的文本编辑器功能。要能够输入文字,能够实现一些常用的编辑功能,可打开并显示TXT文件,并且可以将编辑结果保存为TXT文件。本程序要构建的记事本程序参照了Windows操作系统的记事本工具,其功能有以下几个方面: ① 菜单栏中有“文件”,“编辑”,“字体”三个主菜单。 ②“文件”菜单有“新建”,“打开”,“保存”三个菜单项:分别用于新 建文件,打开文件,保存文件。 ③“编辑”菜单中有“复制”“剪切”“粘贴”“查找”“替换”五个菜单项:用于实现复制所选文字,剪切所选文字,粘贴文字,查找,替换等功能。 ④“字体”中有“格式”一个菜单项:用来控制文本框中文本的字体类型功能; 软件功能架构图:

3. 论述界面设计过程,指出其设计上的创意及组件的布局策略。 这个框架主要运用盒子布局对象和grid布局对象操作。对于文本编辑器的菜单组件如下。 “文件”菜单里: “编辑”菜单里“字体”菜单里 4. 论述程序逻辑的实现,包括类的设计、对象的协作过程等,必要时加以各种图形和表格辅助论述。不得以粘贴代码的方式代替设计部分。 首先,自定义一个editor类,该类继承了JFrame类和ActionListener、ItemListener 接口。在主类的主方法中,用editor创建一个对象bianji。 在editor的构造方法中设计好第一个界面的布局和组件。设计一个菜单条组件,

用Java程序编写一个记事本程序的设计报告

用Java程序编写一个记事本程序的 设计报告 学习中心(点):泾阳学习中心 专业:计算机科学与技术 层次:专升本 姓名:李永固 批次: 112

目录 一、设计分析 (1) 二、程序结构 (1) 三、各模块的功能及程序说明 (2) 1、类设计 (2) 2、主要功能代码实现 (4) 四、源程序 (9) 五、操作方法 (20) 六、试验结果 (20) 七、设计体会 (22)

用Java程序编写一个记事本程序的设计报告 一、设计要求 1.用图形用户界面实现。 2.能实现编辑、保存、另存为、查找替换等功能。 二、程序结构 流程图: 图1基本流程图

本Java文本编辑器功能设计如下: 图2基本功能图 三、各模块的功能及程序说明 1、类设计 (1)类MiniText ,包括initTextPane方法初始化面板,initMenu()方法初始化菜单,initAboutDialog()方法初始化关于对话框,initToolBar()方法初始化工具栏,initRightKey()方法初始化右键设置,等方法。类成员如下:

(2)类Loading (实现登陆)类成员如下:

(3)类runtime (实现时间同步) 类成员如下: (4)类MainFunction (包含主函数) 类成员如下: 2、主要功能代码实现 (1)登陆界面: class Loading extends JWindow implements Runnable { Thread dluThread=null; private JProgressBar progress; public Loading() { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));//设置光标为等待状态JPanel dlu = new JPanel(new BorderLayout()); URL url = getClass().getResource("/images/loading.jpg"); if(url != null){ dlu.add(new JButton(new ImageIcon(url)), BorderLayout.CENTER); } progress = new JProgressBar(1,100); progress.setStringPainted(true); progress.setBorderPainted(true); progress.setBackground(Color.white); progress.setForeground(Color.green); dlu.add(progress,BorderLayout.SOUTH); setContentPane(dlu); //设置窗口属性为登陆面板属性 Dimension screen = getToolkit().getScreenSize(); pack(); //显示登陆界面 setLocation(screen.width/4,screen.height/4); //设置登陆界面始终在屏幕中间显示 } public void start(){ // this.toFront(); dluThread=new Thread(this); dluThread.start(); } public void run(){ show();

JAVA课程设计报告 心得体会——计算器、文本编辑器

用Java设计计算器calculator 内容提要:在本文构造实现了一个计算器擦亮calculator,主要内容包括:calculator的功能需求分析;calculator的基本设计思路和类的划分;calculator的具体实现。 关键字:Java、计算器calculator 引言:设计实现一个Java应用程序的过程如下: (1)功能需求分析; (2)设计和类划分; (3)代码编写实现。 本文就按照这个步骤来实现计算器calculator的制作。 正文: 1.calculator功能需求分析 作为计算器,至少应该具备以下几点功能: (1)计算器要有GUI界面。 (2)能运算小数,并且不会产生精度损失。 (3)用户可以输入所需计算的数值,可以进行加、减、乘、除四种最基本的运算和混合运算。 (4)允许正负数间的运算。 (5)可以求一个数值的平方及倒数,可以进行阶乘运算。 (6)有菜单栏选项。 具体的功能需求和界面我们可以模仿微软公司出品的windowsXP中自带的计算器。如图一: 图一windows XP 中的计算器界面图 2.calculator基本设计思路和类划分 基于第1节中提出对于calculator功能需求的分析,对这个应用程序设计划分类如下:(1)calculator:这个类的功能是实现一个框架 (2)calculatorFrame:这个类作为主类,实现主要功能:运算,按钮排布,菜单,颜色设置,文本显示 3.calculator的具体实现

3.1 calculator类的设计 calculator用来定义一个计算器的框架 1.主要方法 下面以表格的形式列出calculator类至少应该具有的方法和功能描述(如表一所示)。 3.2 calculatorFrame类的设计 calculatorFrame类实现整体功能,包括窗体的初始化、各种用户事件监听和响应(菜单、运算、结果显示等等)。 1.父类和主要接口 设计calculator整体窗口特性继承自JFrame类。 为了对用户命令做出响应(如帮助菜单栏弹出窗口),calculatorFrame类必须能够监听到用户的命令,因此设计calculatorFrame类实现ActionListener接口。 2.主要方法 下面以表格的形式列出calculatorFrame类至少应该具有的方法和功能描述(如表二所示)。 3.基本效果 图二为calculator的基本效果图。

制作一个文本编辑器java课程设计报告

《Java语言程序设计》课程设计报告 设计题目:制作一个文本编辑器 分院:电信分院 班级: 姓名: 学号: 指导教师:黄建华 实验地点:三教机六 课设时间: 2009-12-20——2009-12-25 二OO九年十二月二十五日

《Java语言程序设计课程设计》 目录 一、设计思路 (2) 二、设计过程 (3) 三、测试结果 (12) 四、心得体会 (13) 五、程序代码 (14)

一、设计思路 (一)设计概念 要制作一个文本编辑器,首先得理清思路,要做一个什么样的文本编辑器,做成的编辑器要求要实现哪些功能,要实现这些功能分别需要用到什么方法以及怎样组织编辑器的框架结构等等问题。现把我的设计思路简要介绍如下: 1、明确设计要求 首先要创建了一个窗体,标题为“×××设计的文本编辑器”,设计要要编辑文件和编辑这两个菜单项,要求在文件菜单项上添加新建、打开、保存、退出四个下拉子菜单,要求当用户单击新建时就可以新建一个空白文档;当单击打开时可以从已有的目录下打开需要打开的文本文件,在原有文件中可以选择要打开的文件;当单击保存时可以出现保存的路径,选择自己要保存到的路径将文件保存到指定的文件夹中;单击退出菜单时退出文件的下拉菜单。在编辑菜单下的子菜单复制,可以进行对文本的复制。在文本区要求当单击鼠标右键时可以弹出菜单,要求有两个子菜单为复制和字体,通过单击字体菜单可以实现对字体改变。而且在窗体的右上方有三个按钮可以实现最小化、最大化、和关闭。而且用户也可以根据自己的需要改变窗体的大小。 2、确定设计思路即设计步骤(必须想到要用到哪几个方面的程序、包、方法、以及基本的程序语言) (1)创建一个窗体,包括构造一个文本域为编辑器各种功能的实现提供一个伸展平台;(2)新建一个空的菜单条,然后添加菜单项(文件菜单和编辑菜单); (3)设计程序在菜单项下添加子菜单,文本菜单对应新建、打开、保存和退出,编辑菜单包括的子菜单为复制和粘贴; (4)添加右键快捷弹出式菜单,包括复制、字体等菜单项。 3、上两步都完成以后,就进入程序的检测运行阶段即所谓的编译运行,看是否符合设计要求,是否达到理想中的那种效果,在测验阶段,要一步一步完善自己的作品直至真正意义上的完成整个设计过程。

制作一个文本编辑器 java课程设计报告

封面 《Java语言程序设计》课程设计报告 设计题目:制作一个文本编辑器 分院:电信分院 班级: 姓名: 学号: 指导教师:黄建华 实验地点:三教机六 课设时间:2009-12-20——2009-12-25 二OO九年十二月二十五日

《Java语言程序设计课程设计》 目录 一、设计思路 (2) 二、设计过程 (3) 三、测试结果 (12) 四、心得体会 (13) 五、程序代码 (14)

一、设计思路 (一)设计概念 要制作一个文本编辑器,首先得理清思路,要做一个什么样的文本编辑器,做成的编辑器要求要实现哪些功能,要实现这些功能分别需要用到什么方法以及怎样组织编辑器的框架结构等等问题。现把我的设计思路简要介绍如下: 1、明确设计要求 首先要创建了一个窗体,标题为“×××设计的文本编辑器”,设计要求是要编辑文件和编辑这两个菜单项,要求在文件菜单项上添加新建、打开、保存、退出四个下拉子菜单,要求当用户单击新建时就可以新建一个空白文档;当单击打开时可以从已有的目录下打开需要打开的文本文件,在原有文件中可以选择要打开的文件;当单击保存时可以出现保存的路径,选择自己要保存到的路径将文件保存到指定的文件夹中;单击退出菜单时退出文件的下拉菜单。在编辑菜单下的子菜单复制,可以进行对文本的复制。在文本区内要求当单击鼠标右键时可以弹出菜单,要求有两个子菜单为复制和字体,通过单击字体菜单可以实现对字体改变。而且在窗体的右上方有三个按钮可以实现最小化、最大化、和关闭。而且用户也可以根据自己的需要改变窗体的大小。 2、确定设计思路即设计步骤(必须想到要用到哪几个方面的程序、包、方法、以及基本的程序语言) (1)创建一个窗体,包括构造一个文本域为编辑器各种功能的实现提供一个伸展平台;(2)新建一个空的菜单条,然后添加菜单项(文件菜单和编辑菜单); (3)设计程序在菜单项下添加子菜单,文本菜单对应新建、打开、保存和退出,编辑菜单包括的子菜单为复制和粘贴; (4)添加右键快捷弹出式菜单,包括复制、字体等菜单项。 3、上两步都完成以后,就进入程序的检测运行阶段即所谓的编译运行,看是否符合设计要求,是否达到理想中的那种效果,在测验阶段,要一步一步完善自己的作品直至真正意义上的完成整个设计过程。

代码编辑器的java实现

代码编辑器的java实现 摘要 如果我们把不同的程序开发人员比作三国演义中的各路诸侯大将的话,那么代码编辑器绝对可以称之我们手中的神兵利器。对于每个程序猿来说,内心的深处都想有一把自己的“青龙偃月刀”和属于自己的一个代码编辑器。我也有这个想法,我也想自己写一个代码编辑器来满足我的内心深处。所以这次java的课程作业我选择了这个题目! 关键词:Java;代码编辑器;关键字变色;编译和运行

前言 通过一学期的Java学习,我对Java的理论知识有了一些了解。但是,只有理论联系实际才能更好的掌握理论,所以这次Java课程设计我选择了Java程序编辑器这个课题,希望可以锻炼自己的动手能力。我上交给老师您的代码是我参考的网上的一个牛人写的代码,并在他的代码上进行了功能的增加,至于我增加了多少功能,我会论文的附录中给出详细的对比。 1. 软件的定义 编写一个界面像Windows系统的记事本的代码编辑器,功能比记事本更强大(针对某一方面)具备以下功能: (1)打开、保存文件功能; (2)能够识别Java中的关键字并能将关键字以高亮的形式显示出来; (3)能够批量的删除代码中的注释; (4)能通过按下按钮调用DOS窗口; (5)能编译和运行Java程序; (6)能够检查括号是否匹配。 2.开发环境 IDE: eclipse JDK: jdk-7u45-windows-x64 OS:Windows 7 —X64 3.代码的详细说明 主界面: syntaxcolor.v4包中的DemoFrame.java文件,主界面就是一个Frame,然后在上面加上一个菜单栏,一个工具栏和两个Panel,一个panel里面放着JTextPane,另一个里面放着一个几个JLable,用来显示当前鼠标是在第几行,第几列,该Panel放在Frame最下

Java课程设计文档

Java课程设计报告 题目:文本编辑器 年级专业:07级信息与计算科学 学号: 20074043031 20074043032 20074043033 20074043034 学生姓名:周勇李朝黄峰陈爽指导老师:彭胜 完成时间:2010年 7月 1 日

目录 摘要 (3) 前言 (3) 1 需求分析 (4) 1.1需求分析 (4) 1.2功能设计 (4) 2 概要设计 (4) 2.1程序设计思路 (4) 2.2程序运行界面 (5) 2.3程序相关说明 (5) 3 程序详细设计与分析 (6) 3.1初始化组件 (7) 3.2构建菜单栏及其下拉菜单及其事件监听 (7) 3.3异常处理 (8) 4.测试分析 (9) 5.课程设计总结 (11) 6.参考文献 (11) 7. 附录 (12) 文本编辑器程序的设计

摘要 该报告中的程序是使用Java程序编写,能够进行输入文字操作,并具有,打开文件,保存文件,另存为,退出,撤消,剪切,复制,粘贴,删除,自动换行,关于等功能,该程序主要用到了Java swing包和事件监听等。 关键字:文本编辑器,Java语言,JCreator 前言 Java的前身是Oak,它一开始只是被应用于消费性电子产品中。后来它的开发者们发现它还可以被用于更大范围的Internet上。1995年,Java语言的名字从Oak编程了Java。 1997年J2SE1.1发布。1998年J2SE1.2发布,标志Java2的诞生。十多年来,Java编程语言及平台成功地运用在网络计算及移动等各个领域。Java的体系结构由Java语言、Java class、Java API、Java虚拟机组成。它具有简单、面向对象、健壮、安全、结构中立、可移植和高效能等众多优点。Java支持多线程编程,Java运行时系统在多线程同步方面具有成熟的解决方案。Java的平台标准有Java ME,Java SE和Java EE。Java发展到今天,它的卓越成就及在业界的地位毋庸置疑。目前在众多的支持Java的开发工具中主要的7有Java Development Kit,NetBeans,Jcreator,JBuilder,JDeveloper和Eclipse等。其中Java Development Kit 简称JDK是大多开发工具的基础。以上的每种开发工具都有优缺点,对于开发者来说,重要的是要根据自己的开发规模、开发内容和软硬件环境等因素来选择一种合适的开发工具。 在本程序设计中,因为需要开发的是记事本程序,规模较小,内容较少,所以选择了适合初学者使用的JCreator开发工具。 1需求分析 1.1需求分析 现在网络上各种文本编辑器数不胜数,有EmEditor ,UEStudio ,GridinSoft

制作一个文本编辑器java课程设计报告

制作一个文本编辑器java课程设计报 告

《Java语言程序设计》 课程设计报告 设计题目:制作一个文本编辑器 分院:电信分院 班级: 姓名: 学号: 指导教师:黄建华 实验地点:三教机六 课设时间: -12-20—— -12-25 二OO九年十二月二十五日

《Java语言程序设计课程设计》 目录 一、设计思路 (2) 二、设计过程 (3) 三、测试结果 (12) 四、心得体会 (13) 五、程序代码 (14)

一、设计思路 (一)设计概念 要制作一个文本编辑器,首先得理清思路,要做一个什么样的文本编辑器,做成的编辑器要求要实现哪些功能,要实现这些功能分别需要用到什么方法以及怎样组织编辑器的框架结构等等问题。现把我的设计思路简要介绍如下: 1、明确设计要求 首先要创立了一个窗体,标题为“×××设计的文本编辑器”,设计要求是要编辑文件和编辑这两个菜单项,要求在文件菜单项上添加新建、打开、保存、退出四个下拉子菜单,要求当用户单击新建时就能够新建一个空白文档;当单击打开时能够从已有的目录下打开需要打开的文本文件,在原有文件中能够选择要打开的文件;当单击保存时能够出现保存的路径,选择自己要保存到的路径将文件保存到指定的文件夹中;单击退出菜单时退出文件的下拉菜单。在编辑菜单下的子菜单复制,能够进行对文本的复制。在文本区内要求当单击鼠标右键时能够弹出菜单,要求有两个子菜单为复制和字体,经过单击字体菜单能够实现对字体改变。而且在窗体的右上方有三个按钮能够实现最小化、最大化、和关闭。而且用户也能够根据自己的需要改变窗体的大小。 2、确定设计思路即设计步骤(必须想到要用到哪几个方面的程

制作一个文本编辑器-java课程设计报告

制作一个文本编辑器-java课程设计报告

封面 《Java语言程序设计》课程设计报告 设计题目:制作一个文本编辑器 分院:电信分院 班级: 姓名: 学号: 指导教师:黄建华 实验地点:三教机六 课设时间:2009-12-20——2009-12-25 二OO九年十二月二十五日

《Java语言程序设计课程设计》 目录 一、设计思 路…………………………………………… (2) 二、设计过 程…………………………………………… (3) 三、测试结 果…………………………………………… (12) 四、心得体 会…………………………………………… (13) 五、程序代 码…………………………………………… (14)

一、设计思路 (一)设计概念 要制作一个文本编辑器,首先得理清思路,要做一个什么样的文本编辑器,做成的编辑器要求要实现哪些功能,要实现这些功能分别需要用到什么方法以及怎样组织编辑器的框架结构等等问题。现把我的设计思路简要介绍如下: 1、明确设计要求 首先要创建了一个窗体,标题为“×××设计的

文本编辑器”,设计要求是要编辑文件和编辑这两个菜单项,要求在文件菜单项上添加新建、打开、保存、退出四个下拉子菜单,要求当用户单击新建时就可以新建一个空白文档;当单击打开时可以从已有的目录下打开需要打开的文本文件,在原有文件中可以选择要打开的文件;当单击保存时可以出现保存的路径,选择自己要保存到的路径将文件保存到指定的文件夹中;单击退出菜单时退出文件的下拉菜单。在编辑菜单下的子菜单复制,可以进行对文本的复制。在文本区内要求当单击鼠标右键时可以弹出菜单,要求有两个子菜单为复制和字体,通过单击字体菜单可以实现对字体改变。而且在窗体的右上方有三个按钮可以实现最小化、最大化、和关闭。而且用户也可以根据自己的需要改变窗体的大小。 2、确定设计思路即设计步骤(必须想到要用到哪几个方面的程序、包、方法、以及基本的程序语言) (1)创建一个窗体,包括构造一个文本域为编辑器各种功能的实现提供一个伸展平台;(2)新建一个空的菜单条,然后添加菜单项(文

JAVA程序设计题: 文本编辑器设计

JAVA程序设计题:文本编辑器设计 【问题描述】 实现类似Windows操作系统“记事本”的功能。它是一个简单的文本文档编辑器,可以创建、查看或编辑文本文件。 【实验目的】 要求学生能熟练使用基于Swing的GUI设计,熟练使用常用组件和容器,理解java事件处理机制,会查看API documentation完成设计任务,熟练文件流的操作。 【基本功能】 设计一个文本编辑器,通过菜单组件可以创建、查看或编辑文本文件。 增加对文件的存贮、剪切和黏贴等功能 功能的其他扩展 package com.huangyilun.work; import java.awt.*; import java.awt.event.*; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import javax.swing.*;

public class Notice_B08010332 extends JFrame { public static void main(String[] args) { new Notice_B08010332(); } public Notice_B08010332() { super("新建文本文件"); setUpUIComponent(); setUpEventListener(); setVisible(true); this.showForm(); } private void showForm(){ //侦听窗口关闭操作 setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0);

Java编写的文本编辑器

J a v a编写的文本编辑器 Company number:【0089WT-8898YT-W8CCB-BUUT-202108】

界面: 代码(编译后可直接运行): ; import .*; import .*; public class MyTxt { public static void main(String[] args) { Aframe frame = new Aframe(); ; (); } } class Aframe extends JFrame { public Aframe() { setTitle("我的记事本"); setSize(WIDTH, HEIGHT); Container contentPane = getContentPane(); JPanel txtPanel = new JPanel(); JPanel comboxPanel = new JPanel(); JPanel textPanel = new JPanel(); txtArea=new JTextArea("",17,40); JScrollPane scrollPane =new JScrollPane(txtArea); (scrollPane); (comboxPanel,; (txtPanel); (textPanel,; ."}; daxiaobox=new JComboBox(dax); (daxiaobox); (true); (true); (true); (new FlowLayout);ddUndoableEditListener(um); } quals("")) { (""); }

Java课程设计(文本编辑器)

《Java语言》课程期末作业题目第8题:文本编辑器学院 专业 班别 学号 姓名 2010年12月14日

一、课程题目 第8题:文本编辑器 制作一个简单的文本编辑器,交互性要求:【最大选题人数:8】 (1) 可输入文字(仅要求英文及标点符号) (2) 实现一些常用的编辑功能:如复制和粘贴,查找和替换,首字母自动大写,拼写自动更正…… (3) 可打开并显示TXT文件,并且可以将编辑结果保存为TXT文件 二、题目分析与设计 2.1需求分析 现在网络上各种文档编辑器数不胜数,有EmEditor ,UEStudio ,GridinSoft Notepad ,Notepad++,win32pad ,SkimEdit,UniRed, xint 。功能也是应有尽有,有能改变字体的,有能改变文字颜色的。但是,这些软件又存在各种各样的瑕疵或问题:有的文件体积相对于一般文字编辑来说太大;有的功能太繁杂,使初级使用者一时难以掌握。仅从日常应用方面来说,一个文本编辑器只需一些简单实用的功能就够了。本程序设计就是依照这样一种使用需要设计了一个简单的记事本程序。 2.2功能设计 本程序要构建的记事本程序参照了Windows操作系统的记事本工具,其功能主要有以下几个方面: (1).菜单中有“文件”,“编辑”,“格式”,“查看”,“帮助”五个主菜单。(2)“文件”栏目分别有“新建”,“打开”,“保存”,“打印”,“退出”五个子菜单。分别用于新建文件,打开文件,保存文件,打印文件和退出记事本。(3)“编辑”栏目包括有“全选”,“复制”,“剪切”,“粘贴”,“查找”,“查找下一个”,“替换”七个字菜单。用于全选文字,剪切文字,复制文字,粘贴文字,查找关键字,替换关键字等。 (4)“格式”栏目包括有“自动换行”,“字体”两个功能,点击自动换行可以实现文本自动换行,字体则提供了各种字形字号颜色等选择。 (5)“查看”栏目有“状态”功能。 (6)“帮助”栏目有“帮助主题”,“关于记事本”两个子菜单,帮助主题可以查看windows记事本帮助文件,关于记事本则是作者和版权信息。 2.3模块说明图 类层次调用关系图

Java程序设计实验报告_文本编辑器的设计与实现

Java程序设计实验报告 学生姓名:邵强 学号:0706550222 课程编号:06021801-0 实验名称:文本编辑器的设计与实现 实验内容:设计与实现一个文本编辑器,要求具有方便的图形用户界面,包括标题栏、菜单栏,菜单栏有相关的菜单和菜单项,有快捷键,具有编辑、打开、保存、复制、粘贴等功能(详细功能要求通过运行提供的字节码文件来确定,主类是JNotePadUI)。完成有关类的设计,并调试运行,给出有代表性的程序输出结果(程序运行截图)。 程序代码如下: package note; import java.awt.*; import java.awt.event.*; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.*; import javax.swing.*; public class Mynote extends JFrame implements ActionListener{ JMenu menuFile; JMenu menuEdit ; JMenu menuAbout; JPopupMenu popUpMenu; JTextArea txt=null; //编辑区 JLabel lab=new JLabel("未修改"); JFileChooser fileChooser = new JFileChooser(); File saveFileName = null, fileName = null; public Mynote(String s) { super(s); createMenuBar(); //菜单栏 createContentPane(); //文本编辑区组件 setBounds(100,100,600,450); addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e) { closeFile(); } }); setVisible(true); }

Java课程设计—文本编辑器的设计与实现

面向对象课程设计报告第 1 页,共11 页

主要代码: Write note; { // 新建选项 File_bar_creat = this.AddItem("新建(N) Ctrl+N", File_bar); File_bar_creat.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { // 设置新文件内容 text.setText(""); } }); //打开选项 File_bar_open = this.AddItem("打开(O) Ctrl+O", File_bar); File_bar_open.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { try { jfc.setCurrentDirectory(new File("."));// 设置当前目录 jfc.setFileFilter(new filter()); // 过滤文件 jfc.setAcceptAllFileFilterUsed(false); // 全选文件 jfc.showOpenDialog(null); // 弹出一个 "Open File" 文件选择器对话框。 file = jfc.getSelectedFile(); // 获取已经选择目录 jsb = file.getName(); // 获取目录名 setTitle(jsb); // 显示目录名 int length = (int) (jfc.getSelectedFile()).length();

如何用文本文档编辑与运行java程序

Java实验报告 实验题目实验三、类与对象 实验时间2011年11月1日第8周星期二5,6节 实验地点信息系统实验室 指导老师刘友军 学生姓名李继红学号2009214604 一、实验目的: 1.让学生使用类来封装对象的属性和功能。 2.让学生掌握类变量与实例变量,以及类方法与实例方法的区别。 3.掌握包的建立和导入。 二、实验要求: 模板1:编写一个Java 应用程序,该程序中有2个类:Trangle、Lader,分别用来刻画“三角形”和“梯形”。 具体要求如下: (1)Trangle 类具有类型为double 的三个边,以及周长、面积属性,Trangle 类具有返回周长、面积以及修改三个边的功能。另外,Trangle 类还具 有一个Boolean型的属性,该属性用来判断三个数能否构成一个三角形。 (2)Lader 类具有类型为double 的上底、下底、高、面积属性,具有返回面积的功能。 (3)Circle 类具有类型为double 的半径、周长和面积属性.具有返回周长、面积的功能。 模板2:按程序模板的要求编写源文件特别注意程序的输出结果,并能正确地解释输出的结果。 模板3:将模板1 给出的Java 源文件命名为Trangle.java,将编译后得到的字节码文件复制到C:/1000/tom/jiafei 目录中。 三、实验内容与步骤: 练习一: class Trangle{ double sideA,sideB,sideC,area,length; boolean boo; public Trangle(double a,double b,double c) { this.sideA=a; this.sideB=b; this.sideC=c; if((a+b>c)&&(a+c>b)&&(b+c>a)) boo=true; else boo=false; } double getLength() {

相关文档
最新文档