怎么在 Java中构建一个文本编辑器
这篇文章给大家介绍怎么在 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” 菜单会在没有警告的情况下关闭应用程序。这两个 “功能” 都是不安全的,因此你应该想对这段代码进行一点改善,这是一个很好的开始。在内容还没有被保存前,一个友好的警告是任何一个好的文本编辑器都必不可少的一个功能,但是在这里为了简单,这是未来的一个功能。
@Overridepublic 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.javaerror: 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.jarManifest.txtcom.example.textedit.Maincom/example/textedit/*.class
根据命令的语法,你可以推测出它会创建一个新的名称为 TextEdit.jar
的 JAR 文件,它所需要的清单数据位于 Manifest.txt
中。它的主类被定义为软件包名称的一个扩展,并且类自身是 com/example/textedit/Main.class
。
你可以查看 JAR 文件的内容:
$ jar tvf TextEdit.jar0 Wed Nov 25 META-INF/105 Wed Nov 25 META-INF/MANIFEST.MF338 Wed Nov 25 com/example/textedit/textedit/Main.class4373 Wed Nov 25 com/example/textedit/textedit/TextEdit.class
如果你想看看你的元数据是如何被集成到 MANIFEST.MF
文件中的,你甚至可以使用 xvf
选项来提取它。
使用 java
命令来运行你的 JAR 文件:
$ java -jar TextEdit.jar
关于怎么在 Java中构建一个文本编辑器就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。