导读:有时候,除你自己外,没有人能制作你所梦想的工具。以下是如何开始构建你自己的文本编辑器。

本文字数:9393,阅读时长大约:12分钟

https://linux.cn/article-13038-1.html

作者:Seth Kenlon

译者:郑

有很多文本编辑器。有运行在终端中、运行在 GUI 中、运行在浏览器和浏览器引擎中的。有很多是还不错,有一些则是极好的。但是有时候,毫无疑问,最令人满意的就是你自己构建的编辑器。

毫无疑问:构建一个真正优秀的文本编辑器比表面上看上去要困难得多。但话说回来,建立一个基本的文本编辑器也不像你担心的那样难。事实上,大多数编程工具包已经为你准备好了文本编辑器的大部分组件。围绕文本编辑的组件,例如菜单条,文件选择对话框等等,是很容易落到实处。因此,虽然是中级的编程课程,但构建一个基本的文本编辑器是出乎意料的有趣和简明。你可能会发现自己渴望使用一个自己构造的工具,而且你使用得越多,你可能会有更多的灵感来增加它的功能,从而更多地学习你正在使用的编程语言。

为了使这个练习切合实际,最好选择一种具有令人满意的 GUI 工具箱的语言。有很多种选择,包括 Qt 、FLTK 或 GTK ,但是一定要先评审一下它的文档,以确保它有你所期待的功能。对于这篇文章来说,我使用 Java 以及其内置的 Swing 小部件集。如果你想使用一种不同的语言或者一种不同的工具集,这篇文章在如何帮你处理这种问题的方面也仍然是有用的。

不管你选择哪一种,在任何主要的工具箱中编写一个文本编辑器都是惊人的相似。如果你是 Java 新手,需要更多关于开始的信息,请先阅读我的猜谜游戏文章。

工程设置

通常,我使用并推荐像Netbeans或 Eclipse 这样的 IDE,但我发现,当学习一种新的语言时,手工做一些工作是很有帮助的,这样你就能更好地理解使用 IDE 时被隐藏起来的东西。在这篇文章中,我假设你正在使用文本编辑器和终端进行编程。

在开始前,为你自己的工程创建一个工程目录。在工程文件夹中,创建一个名称为src的目录来容纳你的源文件。

$ mkdir -p myTextEditor/src

$ cd myTextEditor

在你的src目录中创建一个名称为TextEdit.java的空白的文件:

$ touch src/TextEditor.java

在你最喜欢的文本编辑器中打开这个空白的文件(我的意思是除你自己编写之外的最喜欢的一款文本编辑器),然后准备好编码吧!

包和导入

为确保你的 Java 应用程序有一个唯一的标识符,你必须声明一个package名称。典型的格式是使用一个反向的域名,如果你真的有一个域名的话,这就特别容易了。如果你没有域名的话,你可以使用local作为最顶层。像 Java 和很多语言一样,行以分号结尾。

在命名你的 Java 的package后,你必须告诉 Java 编译器(javac)使用哪些库来构建你的代码。事实上,这通常是你边编写代码边添加的内容,因为你很少事先知道你自己所需要的库。然而,这里有一些库是显而易见的。例如,你知道这个文本编辑器是基于 Swing GUI 工具箱的,因此,导入javax.swing.JFrame和javax.swing.UIManager和其它相关的特定库。

package com.example.textedit;

import javax.swing.JFileChooser;

import javax.swing.JFrame;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

import javax.swing.JMenuItem;

import javax.swing.JOptionPane;

import javax.swing.JTextArea;

import javax.swing.UIManager;

import javax.swing.UnsupportedLookAndFeelException;

import javax.swing.filechooser.FileSystemView;

import java.awt.Component;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.util.Scanner;

import java.util.logging.Level;

import java.util.logging.Logger;

对于这个练习的目标,你可以提前预知你所需要的所有的库。在真实的生活中,不管你喜欢哪一种语言,你都将在研究如何解决一些问题的时候发现库,然后,你将它导入到你的代码中,并使用它。不需要担心 —— 如果你忘记包含一个库,你的编译器或解释器将警告你!

主窗口

这是一个单窗口应用程序,因此这个应用程序的主类是一个JFrame,其附带有一个捕捉菜单事件的ActionListener。在 Java 中,当你使用一个现有的小部件元素时,你可以使用你的代码“扩展”它。这个主窗口需要三个字段:窗口本身(一个JFrame的实例)、一个用于文件选择器返回值的标识符和文本编辑器本身(JTextArea)。

public final class TextEdit extends JFrame implements ActionListener {

private static JTextArea area;

private static JFrame frame;

private static int returnValue = 0;

令人惊奇的是,这数行代码完成了实现一个基本文本编辑器的 80% 的工作,因为JtextArea是 Java 的文本输入字段。剩下的 80 行代码大部分用于处理辅助功能,比如保存和打开文件。

构建一个菜单

JMenuBar小部件被设计到 JFrame 的顶部,它为你提供你想要的很多菜单项。Java 不是一种 拖放式的编程语言,因此,对于你所添加的每一个菜单,你都还必须编写一个函数。为保持这个工程的可控性,我提供了四个函数:创建一个新的文件,打开一个现有的文件,保存文本到一个文件,和关闭应用程序。

在大多数流行的工具箱中,创建一个菜单的过程基本相同。首先,你创建菜单条本身,然后创建一个顶级菜单(例如 “File” ),再然后创建子菜单项(例如,“New”、“Save” 等)。

public TextEdit() { run(); }

public void run() {

frame = new JFrame("Text Edit");

// Set the look-and-feel (LNF) of the application

// Try to default to whatever the host system prefers

try {

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {

Logger.getLogger(TextEdit.class.getName()).log(Level.SEVERE, null, ex);

}

// Set attributes of the app window

area = new JTextArea();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.add(area);

frame.setSize(640, 480);

frame.setVisible(true);

// Build the menu

JMenuBar menu_main = new JMenuBar();

JMenu menu_file = new JMenu("File");

JMenuItem menuitem_new = new JMenuItem("New");

JMenuItem menuitem_open = new JMenuItem("Open");

JMenuItem menuitem_save = new JMenuItem("Save");

JMenuItem menuitem_quit = new JMenuItem("Quit");

menuitem_new.addActionListener(this);

menuitem_open.addActionListener(this);

menuitem_save.addActionListener(this);

menuitem_quit.addActionListener(this);

menu_main.add(menu_file);

menu_file.add(menuitem_new);

menu_file.add(menuitem_open);

menu_file.add(menuitem_save);

menu_file.add(menuitem_quit);

frame.setJMenuBar(menu_main);

}

现在,所有剩余的工作是实施菜单项所描述的功能。

编程菜单动作

你的应用程序响应菜单选择,是因为你的JFrame有一个附属于它的ActionListener。在 Java 中,当你实施一个事件处理程序时,你必须“重写”其内建的函数。这只是听起来可怕。你不是在重写 Java;你只是在实现已经被定义但尚未实施事件处理程序的函数。

在这种情况下,你必须重写actionPerformed方法。因为在 “File” 菜单中的所有条目都与处理文件有关,所以在我的代码中很早就定义了一个JFileChooser。代码其它部分被划分到一个if语句的子语句中,这起来像接收到什么事件就相应地执行什么动作。每个子语句都与其它的子语句完全不同,因为每个项目都标示着一些完全唯一的东西。最相似的是 “Open” 和 “Save”,因为它们都使用JFileChooser选择文件系统中的一个位置来获取或放置数据。

“New” 菜单会在没有警告的情况下清理 JTextArea ,“Quit” 菜单会在没有警告的情况下关闭应用程序。这两个 “功能” 都是不安全的,因此你应该想对这段代码进行一点改善,这是一个很好的开始。在内容还没有被保存前,一个友好的警告是任何一个好的文本编辑器都必不可少的一个功能,但是在这里为了简单,这是未来的一个功能。

@Override

public void actionPerformed(ActionEvent e) {

String ingest = null;

JFileChooser jfc = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());

jfc.setDialogTitle("Choose destination.");

jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);

String ae = e.getActionCommand();

if (ae.equals("Open")) {

returnValue = jfc.showOpenDialog(null);

if (returnValue == JFileChooser.APPROVE_OPTION) {

File f = new File(jfc.getSelectedFile().getAbsolutePath());

try{

FileReader read = new FileReader(f);

Scanner scan = new Scanner(read);

while(scan.hasNextLine()){

String line = scan.nextLine() + "\n";

ingest = ingest + line;

}

area.setText(ingest);

}

catch ( FileNotFoundException ex) { ex.printStackTrace(); }

}

// 保存

} else if (ae.equals("Save")) {

returnValue = jfc.showSaveDialog(null);

try {

File f = new File(jfc.getSelectedFile().getAbsolutePath());

FileWriter out = new FileWriter(f);

out.write(area.getText());

out.close();

} catch (FileNotFoundException ex) {

Component f = null;

JOptionPane.showMessageDialog(f,"File not found.");

} catch (IOException ex) {

Component f = null;

JOptionPane.showMessageDialog(f,"Error.");

}

} else if (ae.equals("New")) {

area.setText("");

} else if (ae.equals("Quit")) { System.exit(0); }

}

}

从技术上来说,这就是这个文本编辑器的全部。当然,并没有真正做什么,除此之外,在这里仍然有测试和打包步骤,因此仍然有很多时间来发现缺少的必需品。假设你没有注意到提示:在这段代码中 肯定 缺少一些东西。你现在知道缺少的是什么吗?(在猜谜游戏文章中被大量的提到。)

测试

你现在可以测试你的应用程序。从终端中启动你所编写的文本编辑器:

$ java ./src/TextEdit.java

error: can’t find main(String[]) method in class: com.example.textedit.TextEdit

它看起来像在代码中没有获得main方法。这里有一些方法来修复这个问题:你可以在TextEdit.java中创建一个main方法,并让它运行一个TextEdit类实例,或者你可以创建一个单独的包含main方法的文件。两种方法都可以工作,但从大型工程的预期来看,使用后者更为明智,因此,使用单独的文件与其一起工作使之成为一个完整的应用程序的方法是值得使用的。

在src中创建一个Main.java文件,并在最喜欢的编辑器中打开:

package com.example.textedit;

public class Main {

public static void main(String[] args) {

TextEdit runner = new TextEdit();

}

}

你可以再次尝试,但是现在有两个相互依赖的文件要运行,因此你必须编译代码。Java 使用javac编译器,并且你可以使用-d选项来设置目标目录:

$ javac src/*java -d .

这会在你的软件包名称com/example/textedit后创建一个准确地模型化的新的目录结构。这个新的类路径包含文件Main.class和TextEdit.class,这两个文件构成了你的应用程序。你可以使用java并通过引用你的 Main 类的位置和 名称(非文件名称)来运行它们:

$ java info/slackermedia/textedit/Main`

你的文本编辑器打开了,你可以在其中输入文字,打开文件,甚至保存你的工作。

带有单个下拉菜单的白色文本编辑器框,有 File、New、Open、Save 和 Quit 菜单

以 Java 软件包的形式分享你的工作

虽然一些程序员似乎看起来认可以各种各样的源文件的形式分发软件包,并鼓励其他人来学习如何运行它,但是,Java 让打包应用程序变得真地很容易,以至其他人可以很容易的运行它。你已经有了必备的大部分结构体,但是你仍然需要一些元数据到一个Manifest.txt文件中:

$ echo "Manifest-Version: 1.0" > Manifest.txt

用于打包的jar命令,与tar命令非常相似,因此很多选项对你来说可能会很熟悉。要创建一个 JAR 文件:

$ jar cvfme TextEdit.jar

Manifest.txt

com.example.textedit.Main

com/example/textedit/*.class

根据命令的语法,你可以推测出它会创建一个新的名称为TextEdit.jar的 JAR 文件,它所需要的清单数据位于Manifest.txt中。它的主类被定义为软件包名称的一个扩展,并且类自身是com/example/textedit/Main.class。

你可以查看 JAR 文件的内容:

$ jar tvf TextEdit.jar

0 Wed Nov 25 META-INF/

105 Wed Nov 25 META-INF/MANIFEST.MF

338 Wed Nov 25 com/example/textedit/textedit/Main.class

4373 Wed Nov 25 com/example/textedit/textedit/TextEdit.class

如果你想看看你的元数据是如何被集成到MANIFEST.MF文件中的,你甚至可以使用xvf选项来提取它。

使用java命令来运行你的 JAR 文件:

$ java -jar TextEdit.jar

你甚至可以创建一个桌面文件,这样,在单击应用程序菜单中的图标时,应用程序就会启动。

改进它

在当前状态下,这是一个非常基本的文本编辑器,最适合做快速笔记或简短自述文档。一些改进(比如添加垂直滚动条)只要稍加研究就能快速简单地完成,而另一些改进(比如实现一个广泛的偏好系统)则需要真正的工作。

但如果你一直在想学一种新的语言,这可能是一个完美的自我学习实用工程。创建一个文本编辑器,如你所见,它在代码方面并不难对付,它在一定范围是可控的。如果你经常使用文本编辑器,那么编写你自己的文本编辑器可能会使你满意和乐趣。因此打开你最喜欢的文本编辑器(你写的那个),开始添加功能吧!

via:https://opensource.com/article/20/12/write-your-own-text-editor

作者:Seth Kenlon选题:lujun9972译者:robsean校对:wxy

本文由LCTT原创编译,Linux中国荣誉推出

欢迎遵照 CC-BY-NC-SA 协议规定转载,

如需转载,请在文章下留言 “转载:公众号名称”,

我们将为您添加白名单,授权“转载文章时可以修改”。

java 新闻编辑_使用 Java 构建你自己的文本编辑器|Linux 中国相关推荐

  1. java 新闻采集系统_基于Java技术的新闻采集器设计与实现

    基于 Java 技术的新闻采集器设计与实现 赵敏涯 ; 华英 ; 吴笛 ; 黄鹏 ; 赵明明 [期刊名称] <电脑编程技巧与维护> [年 ( 卷 ), 期] 2019(000)004 [摘 ...

  2. java写新闻模板_基于java新闻发布及管理系统

    基于java新闻发布及管理系统 java 2020-10-18 下载地址 https://www.codedown123.com/44681.html Java新闻发布系统新闻发布及管理系统就是一个能 ...

  3. bigint对应java什么类型_「JAVA」从格式化输出到扫描输入,深究Java正则表达式匹配之道

    字符串是不可变的 字符串是不可变的,也就是说当字符串的内容发生改变的时候,会创建一个新的String对象:但是如果内容没有发生改变的时候,String类的方法会返回原字符串对象的引用. 而正则表达式往 ...

  4. java 持续交付_【Java架构:持续交付】一篇文章搞掂:Jenkins

    1.1.使用yum安装JDK a.检查系统是否有安装open-jdk rpm -qa |grep java rpm -qa |grep jdk rpm -qa |grep gcj 如果没有输入信息表示 ...

  5. java 分割一个_分割java

    [java]分割字符串工具类,霸气 jdk自带的 java 分割字符串,分割string,可以根据多个条件去分割.比如逗号,分号,逗号或者分号. 比如一个字符串:"abc,def;gh,ij ...

  6. java楼盘管理系统_基于Java的楼盘销售管理系统的设计与实现

    科技信息SCIENCE & TECHNOLOGY INFORMATION2010 年 第 33 期 (上接第 456 页)3.3.1 在保卫目标上空 30-50m 的高度上,配置一定数量的球载 ...

  7. java 字符串包_包java字符串

    Java核心技术卷I基础知识3.6.3 不可变字符串 3.6.3 不可变字符串 String类没有提供用于修改字符串的方法.如果希望将greeting的内容修改为"Help!",不 ...

  8. java武功秘籍_请问java全套内容都有什么呢?

    我整理的Java全套内容学习路线,分为6个阶段(大阶段)第一阶段:java内功心法篇 第二阶段:Java武功秘籍(经典框架) 第三阶段:Java高级功法(主流框架) 第四阶段:Java成神之路 第五阶 ...

  9. java教学目标_成为Java高手的25个学习目标

    1.需要精通面向对象分析与设计(OOA/OOD).涉及模式(GOF,J2EEDP)以及综合模式,应该了解UML,尤其是 class,object,interaction以及statediagrams. ...

最新文章

  1. php 大牛生小牛,C#算法之关于大牛生小牛的问题
  2. Javascript Throttle Debounce
  3. 【BZOJ 1001】[BJOI2006]狼抓兔子(最大流)
  4. [HNOI2015]开店(树剖+主席树+标记永久化)
  5. AdobeFlashPlayer:GPU加速原理解析
  6. SpringBoot+Vue的租房管理系统(毕设, 包含前后台)
  7. 中国各地高考难度地图:最难的省份不出所料!
  8. c语言中6 2等于多少,概率中C62怎么算(6是下标,2标在上面)
  9. 于娟的忠告----生命只有一次,活着才是王道啊!!!
  10. 只用 Markdown 就写出好看的简历,在线简历应用闪亮登场!
  11. 今天零晨的大雨好厉害呀
  12. Sansen精粹阅读笔记(1)OTA和OCA (电流放大器)
  13. 塔菲尔曲线如何分析_Tafel曲线是做什么的
  14. ORA-01843 月份无效
  15. Linux安装Erlang
  16. win10下的dos基本命令
  17. [Vue warn]: Unknown custom element: <mycom> - did you register the component correctly? For recursiv
  18. NAO机器人——运动控制(3)
  19. 时针分针一天到底重合多少次?
  20. numpy中的clip()函数

热门文章

  1. 阿里云迎来 2.0,重新定义软件系统应用开发方式
  2. TypeScript 的存在削弱了 JavaScript 生态系统?
  3. 苹果市值突破2万亿美元;华为推出PC版HMS“擎云生态”;Android11将强制应用使用内置相机 | 极客头条
  4. 2020 存储技术热点与趋势总结
  5. 如何“发现”失联多年好友?代码告诉你!
  6. 华为百度美团驰援抗击疫情;自由软件基金会建议开源 Windows 7;印度超越美国成第二大智能手机市场 | 极客头条...
  7. PHP 是生还是死?
  8. 程序员为什么非得参加一场编程竞赛?
  9. 华为主导 5G 入网之争?
  10. 关于 CSDN 下载频道知识产权保护的声明