利用Java Swing建设一个XML编辑器之三
副标题#e#
假如你此刻正在寻找一个跨平台、资源开放的XML编辑器的话,您大概很快就可以或许实现这个愿望了。在这个三部门系列文章中,我将带您操作一些最凡是的Java 2 Swing组件开拓一个简朴的 XML编辑器。本系列将有益于那些想编写他们的本身的XML编辑器的伴侣可能辅佐您进修或复习Swing。
这是本系列的第三篇文章。在第一个篇文章中,我们简腹地接头了XML和为什么树形布局适合显示XML、如那里理惩罚XML 数据、如何利用JTree Swing组件,而且我们还构建一个可重用组件用来理会XML文件并在JTree中显示数据。
在第二篇文章中,我们建设了用于我们XML编辑器的框架布局。为了做到这个目标,我们谈到了很多Swing组件(包罗 JSplitPane、JScrollPane、 JButton和JTextArea )。 JSplitPane工具又包括了两个JScrollPane工具,一个用于XML的图形化欣赏,别的一个用于文本欣赏。
在这最后一篇文章中,我们将把最后的界面添加到 XML编辑器中,使它可以或许越发用户友好化。我们将先构建一个菜单系统,然后继承构拜会见下层文件系统的JFileChooser组件来答允生存XML文件并打开新建文档。最后,我们将构建一个JDialog框,利用户可以或许打消一个呼吁并退出应用措施。
那么如何加强我们的Swing应用措施的机能,以使它们操作菜单,会见文件系统并答允用户打消操纵呢?我们需要建设JMenu组件来处理惩罚应用措施的菜单,建设JFileChooser组件来会见下层文件系统,利用JDialog框来答允用户打消操纵。
在以前的文章中,我们开拓了XTree类——一个衍生于 JTree类的可重用组件,可以或许把 XML数据以图形化树来显示。因为我们喜欢利用面向工具原则,我们本日所做的修改不会打仗谁人类。因为我们喜欢利用面向工具原则,我们本日所做的修改不会打仗谁人类。它是一个自包括可反复利用的类,被我们的JFrame容器利用而不是被团结。
第一节 构建菜单组件
一个JMenu组件包罗几个工具:一个菜单栏、一个或更多菜单和一个或更多菜单项。菜单栏包括菜单,而菜单又包括菜单项。这些Swing组件的名称都相当直观的(别离为 JMenuBar、JMenu和 JMenuItem)。
下面是建设一个包括单一菜单项的最小的" File "菜单的全部的代码:
JMenu fileMenu = new JMenu( "File" );
JmenuItem exitItem = new JMenuItem( "Exit" );
fileMenu.add( exitItem );
JmenuBar menuBar = new JMenuBar();
menuBar.add( fileMenu );
setJMenuBar( menuBar );
这个进程我们应该很是熟悉,JMenu组件使在任何其他 Java GUI组件构建时建设的。最内部的元素被加到它们的直接父元素中,直到所有的元素都已界说了一个适当的容器。
返回XmlEditor个案研究中,我们实际上已经建设了一个完整的文件菜单,有建设新的 XML文件、打开一个现有的文件、生存文件和退出的成果。我们将在下一小节中具体谈谈它。
第二节 处理惩罚菜单事件
我们想要建设一个典范的文件菜单,能让我们的用户建设一个新文档,打开一个现有的文件,生存当前的文件并退出应用措施。既然我们知道如何构建这个菜单,那么我们如何响应用户的菜单选择呢?和其他Swing组件一样,谜底就在于事件模子和可用的监听者组件。
处理惩罚一个菜单选择最根基的要领就是把一个浸染监听者添加到菜单项中: exitItem.addActionListener(new exitMenuHandler());当处理惩罚巨大的事件处理惩罚时(因为菜单系统有大概变得很巨大),该当把事件处理惩罚措施界说成单独的类。上面给出的谁人例子添加一个exitMenuHandler范例的动作监听者。这个范例稍后将在这个应用措施中界说。下面是一个界说exitMenuHandler类所需要最少的代码:
class exitMenuHandler implements ActionListener {
public void actionPerformed( ActionEvent ae ) {
System.exit(0);
}
}
固然这个实现用来证明一个单独类的界说大概好像过分简朴了,可是当我们界说用于打开并生存文件的事件处理惩罚代码时,你将认识到把单独的成果性放入单独的类文件的重要性。另外,这个要领将答允你在差异的应用措施之间反复利用民众菜单成果。
#p#副标题#e#
第三节 构建文件系统存取组件
这个Java应用措施经常需要答允用户通过一个图形化文件系统欣赏措施会见文件系统。典范环境下,这是因为用户想要打开或生存一个组件或文件。在我们的XmlEditor应用措施中,我们想要用户可以或许做到这些。
为了会见根基文件系统,javax.swing包中有一个很是好的组件:JFileChooser组件。无疑,在操作 JFileChooser组件之前你已经利用一个 Swing应用措施。
#p#分页标题#e#
为了建设一个JFileChooser,你要先实例化一个 JFileChooser工具,配置它的巨细然后声明它要么用于打开文件要么用于生存文件。你要把这个工具和它的父工具-用来激活它的工具 (在我们的例子中是一个菜单项)接洽起来,然后把它要么配置为打开对话框可能生存对话。为了做到这点,你要利用showSaveDialog()或 showOpenDialog()要领,两个都返回一个int范例的返回值。下面是一个简短的例子:
JFileChooser jfc = new JFileChooser();
jfc.setSize( 500, 250 );
Container parent = openItem.getParent();
int choice = jfc.showOpenDialog(parent);
最后一行返回的整数值指出用户最后到底是打开/生存一个文件照旧按下打消按钮。为了响应打开/生存事件,可以把这个整数值界说在 JFileChooser类中的 APPROVE_OPTION常数较量。此时,你只须利用适当的要领打开/生存用户请求的文件。
请参看代码段1,是这个应用措施的完整的实现;它包括了所有的六个要领用于结构 XmlEditor应用措施的菜单处理惩罚成果。
第四节 构建对话框组件来验证选择
此刻,当你点击 Jframe的封锁窗口时,这个应用措施当即封锁。这不太好。假如用户在操纵一个文件时意外地封锁窗口,那么怎么办?我们想提示用户,询问他们是否真要封锁应用措施。
我们可以利用一个JDialog对话框来实现这个目标。每个图形应用措施可以在用户包围别的一个文件、没有生存就封锁某个文件或在封锁应用措施之前利用它们来提醒用户。为了简化编程,我们就把体贴的重点放在封锁编辑器的时候,提醒用户。
我们需要做的就是建设一个JDialog对话框,这个对话框配有Jlabel,它包括了提示语和两个按钮,一个用来吸收封锁措施的呼吁,别的一个打消封锁措施的呼吁。下面是结构这个组件的代码:
JDialog verifyDialog = new JDialog( this, "Confirm Exit", true );
Jlabel question = new JLabel( "Are you sure you want to exit?" );
Jbutton okButton = new JButton( "OK" );
okButton.addActionListener( this );
Jbutton cancelButton = new JButton( "Cancel" );
cancelButton.addActionListener( this );
verifyDialog.getContentPane().setLayout( new FlowLayout() );
verifyDialog.getContentPane().add( question );
verifyDialog.getContentPane().add( okButton );
verifyDialog.getContentPane().add( cancelButton );
verifyDialog.hide();
此刻,还剩两件事没做。我们必需为这两个按钮编写事件处理惩罚代码并把窗口封锁事件行为用之代替。就处理惩罚这两个按钮而言,我们只要在按下 OK时封锁这个应用措施而当按下 Cancel时埋没对话框。
最后一步就是包围默认的窗口封锁事件行动。默认环境,纵然你建设了一个对话框然后用户单击打消按钮, JFrame仍然吸收到封锁窗口事件。这将造成 JFrame埋没自己,除非我们利用下列配置包围它:
setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
新的配置将使响应窗口封锁事件时绝对不会封锁它自己。它只有响应System.exit()挪用时才会封锁它自己。
一旦你添加了菜单组件,界说用于菜单事件的事件处理惩罚措施并添加打消意外封锁窗口事件的要领,我们就可以测试这个应用措施并开始建设、编辑并生存 XML文件了。
恭喜!恭喜!你已经有了手工编写的基于Swing的XML编辑器。剩下的事情就由你来完成了,你需要验证它,增加它的结实性,还可以增加一些新的成果。
附:代码段1
class newMenuHandler implements ActionListener
{
public void actionPerformed ( ActionEvent ae )
{
textArea.setText( "" );
try
{ // 建设一个新的XTree
xTree = new XTree();
xTree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION );
xTree.setShowsRootHandles( true );
// 这个东西更高级的版本,答允修改JTree
xTree.setEditable( false );
}
catch( Exception ex )
{
String message = ex.getMessage();
ex.printStackTrace();
}
file://竣事try/catch
}
file://竣事actionPerformed()
}
file://竣事class newMenuHandler
class openMenuHandler implements ActionListener
{
JFileChooser jfc;
Container parent;
int choice;
openMenuHandler()
{
super();
jfc = new JFileChooser();
jfc.setSize( 400,300 );
jfc.setFileFilter( new XmlFileFilter() );
parent = openItem.getParent(); }
file://竣事openMenuHandler()
class openMenuHandler implements ActionListener
{
JFileChooser jfc;
Container parent;
int choice;
openMenuHandler()
{
super();
jfc = new JFileChooser();
jfc.setSize( 400,300 );
jfc.setFileFilter( new XmlFileFilter() );
parent = openItem.getParent();
}
public void actionPerformed( ActionEvent ae )
{
choice = jfc.showOpenDialog( parent );
if ( choice == JFileChooser.APPROVE_OPTION )
{
String fileName, line;
BufferedReader reader;
fileName = jfc.getSelectedFile().getAbsolutePath();
try
{
reader = new BufferedReader(
new FileReader( fileName ) );
textArea.setText( reader.readLine() + "\n" );
while ( ( line = reader.readLine() ) != null )
{
textArea.append( line + "\n" );
}
reader.close();
xTree.refresh( textArea.getText() );
}
catch ( Exception ex )
{
String message = ex.getMessage();
ex.printStackTrace();
}
jfc.setCurrentDirectory( new File( fileName ) );
}
}
}
class saveMenuHandler implements ActionListener
{
JFileChooser jfc;
Container parent;
int choice;
saveMenuHandler()
{
super();
jfc = new JFileChooser();
jfc.setSize( 400,300 );
jfc.setFileFilter( new XmlFileFilter() );
parent = saveItem.getParent();
}
public void actionPerformed( ActionEvent ae )
{
choice = jfc.showSaveDialog( parent );
if ( choice == JFileChooser.APPROVE_OPTION )
{
String fileName;
File fObj;
FileWriter writer;
fileName = jfc.getSelectedFile().getAbsolutePath();
try
{
writer = new FileWriter( fileName );
textArea.write( writer );
writer.close();
}
catch ( IOException ioe )
{
ioe.printStackTrace();
}
jfc.setCurrentDirectory( new File( fileName ) );
}
}
}
class exitMenuHandler implements ActionListener
{
public void actionPerformed( ActionEvent ae )
{
verifyDialog.show();
}
}
class XmlFileFilter extends javax.swing.filechooser.FileFilter
{
public boolean accept( File fobj )
{
if ( fobj.isDirectory() )
return true;
else
return fobj.getName().endsWith( ".xml" );
}
public String getDescription()
{
return "*.xml";
}
}