副标题#e#
这是本系列的第二篇文章。在上一篇文章中,我们简腹地接头了XML以及为什么一个树形布局适合显示XML、如那里理惩罚XML数据、如何利用JTree Swing 组件以及如何建设一个可重用的可以或许阐明XML文档以及在Jtree显示数据的组件。
在本文中,我们将建设我们的XML编辑器的框架,为了到达这个目标,我们将用到很多Swing组件(包罗JsplitPane、JscrollPane、Jbutton和JtextArea组件)。
一、问题的提出与办理
我如何建设一个可以或许欣赏文本和欣赏视图的XML文本编辑器呢?建设一个包括Jbutton和JsplitPane的Jframe工具, 然后让JsplitPane工具包括两个JscrollPane工具,一个用于欣赏图形(xTree类),另一个用于欣赏文本(JtextArea类)。Jbutton用来打点刷新图形欣赏的操纵。
二、加强Xtree类的成果
在上一篇文章中,我们开拓了Xtree类,这是一个可重用的组件,担任于Jtree类并可以或许把XML数据以图形树的形式显示。我们此刻就加强这个类, 通过提供应它一个在显示默认的XML树来We will now enhance that class by providing it with a default XML tree to display in the event that an XML file is not supplied at the command-line. 并且,我们还将添加一些错误处理惩罚逻辑以便措施不会因为无效的XML而瓦解。
第一步是建设一个名为buildTree()的要领:
private DefaultTreeModel buildTree( String text )
{
DefaultMutableTreeNode treeNode;
Node newNode;
// 回收DOM根节点并把它转化成为一个Tree模子
newNode = parseXml( text );
if ( newNode != null )
{
treeNode = createTreeNode( newNode );
return new DefaultTreeModel( treeNode );
}
else
return null;
} file://竣事buildTree()
这个要领取得传入的 XML字符串,阐明这个 XML字符串并结构一个可以用来从数据中结构图形树形布局的DefaultTreeModel变量实例。这个成果本来包括在 XTree()结构措施中,可是我们把它拿出来然后把它放进一个单独的要领中,这样我们就有了建设一个默认图形树的伸缩性。这就是我们接下来想做的事。
接下来一步是建设一个叫 buildWelcomeTree()的要领。这个要领一次构建一个DefaultTreeModel变量,而不是通过阐明一个现有的XML文字字符串。假如用户没有指定 XML文件就启动这个应用措施,将显示 DefaultTreeModel。见代码段1
代码段1:
private DefaultTreeModel buildWelcomeTree()
{
DefaultMutableTreeNode root;
DefaultMutableTreeNode instructions, openingDoc,
editingDoc, savingDoc;
DefaultMutableTreeNode openingDocText, editingDocText,
savingDocText;
DefaultMutableTreeNode development, addingFeatures,
contactingKyle;
root = new DefaultMutableTreeNode( "Welcome to XML View 1.0" );
instructions = new DefaultMutableTreeNode( "Instructions" );
openingDoc = new DefaultMutableTreeNode
( "Opening XML Documents" );
openingDocText = new DefaultMutableTreeNode
( "When invoking the XmlEditor from
the command-line, you must specify the filename." );
editingDoc = new DefaultMutableTreeNode
( "Editing an XML Document" );
editingDocText = new DefaultMutableTreeNode
( "XML text in the right hand frame
can be edited directly.
The \"refresh\" button will rebuild
the JTree in the left frame." );
savingDoc = new DefaultMutableTreeNode
( "Saving an XML Document" );
savingDocText = new DefaultMutableTreeNode
( "This iteration of the XmlEditor does
not provide the ability to save your
document. That will come with the
next article." );
root.add( instructions );
instructions.add( openingDoc );
instructions.add( editingDoc );
openingDoc.add( openingDocText );
editingDoc.add( editingDocText );
return new DefaultTreeModel( root );
}
#p#副标题#e#
接下来的我们需要添加一个新的结构措施来简化默认显示成果,我们将修改主结构措施,这样它就不能接管任何参数,建设一个新的能吸收单一的 XML文本字符串的结构措施。这样以来,假如没有 XML文本被显示的话就会建设默认 XTree工具,而假如 XML文本被显示的话将建设一个独一的 XTree工具。代码段2中给出了两个结构措施。
代码段2:
#p#分页标题#e#
public XTree( String text ) throws ParserConfigurationException
{
this();
refresh( text );
}
public XTree() throws ParserConfigurationException
{
super();
getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION );
setShowsRootHandles( true );
setEditable( false );
dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating( false );
db = dbf.newDocumentBuilder();
setModel( buildWelcomeTree() );
}
三、建设 XmlEditor类
XmlEditor类与前面的那篇文章的XTreeTester类有沟通的用途,差异之处在于 XmlEditor包罗一个 JTextArea,答允你操纵文本版XML。之后,你可以点击 “Refresh”按钮并查察 XTree组件中反应出来的变革。
假如直接修改第一篇文章中的代码,你就能节减许多时间,你可以把 XTreeTester.java文件重定名为 XmlEditor.java (不外必然要修改结构措施 )并把它当成模板文件。
要做的第一件事是添加下列 Swing组件:另一个 JScrollPane、 JSplitPane、 JTextArea和 JButton。通过声明所有的这些组件以及其他组件开始(看代码段3)。
代码段3:
private XTree xTree;
private JScrollPane jScroll, jScrollRt;
private JSplitPane splitPane;
private JButton refreshButton;
private WindowListener winClosing;
首先,我们将建设并添加“ Refresh”按钮。这个按钮用来指示这个 XTree组件将利用当前 XML文原来刷新。我们还需要利用一个ActionListener来注册它。(拜见代码段 4 ) 为了拦截按钮事件,我们需要有这个类还要实现 ActionListener,并且我们还需要建设一个 actionPerformed()要领 (拜见代码段 5 )。
代码段4:
refreshButton = new JButton( "Refresh" );
refreshButton.setBorder(
BorderFactory.createRaisedBevelBorder() );
refreshButton.addActionListener( this );
getContentPane().add( refreshButton, BorderLayout.NORTH );
代码段5:
public void actionPerformed( ActionEvent ae )
{
if ( ae.getActionCommand().equals( "Refresh" ) )
xTree.refresh( textArea.getText() );
}
接下来,我们将建设新的 JScrollPane和 JTextArea而且把 JTextArea添加到 JScrollPane中。这样,我们将获得包括 XTree组件的原始的 JScrollPane和包括 JTextArea组件的新的 JScrollPane。这个原始的 XTree结构措施尚有一个修改之处。我们将删除先前传进这个要领的字符串参数。(该成果通过我们接下来要构建的另一个 XmlEditor()结构措施操纵)我们把这两个方框放进一个 JSplitPane中,它是一个有脱离器的组件,可以在这个脱离器的另一边包括一个组件。(拜见代码段6)。
代码段6:
jScroll = new JScrollPane();
jScrollRt = new JScrollPane();
textArea = new JTextArea( 200,150 );
jScrollRt.getViewport().add( textArea );
xTree = new XTree();
xTree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION );
xTree.setShowsRootHandles( true );
xTree.setEditable( false );
jScroll.getViewport().add( xTree );
splitPane = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT,
jScroll, jScrollRt );
splitPane.setOneTouchExpandable(true);
splitPane.setDividerLocation(200);
minimumSize = new Dimension(200, 150);
jScroll.setMinimumSize( minimumSize );
jScrollRt.setMinimumSize( minimumSize );
splitPane.setPreferredSize( new Dimension(400, 300) );
getContentPane().add( splitPane, BorderLayout.CENTER );
此刻我们需要修改这个结构措施来处理惩罚这个非 XML文件的情景。删除当前结构措施需要的第二个字符串参数。这个结构措施此刻就是默认的结构措施。我们将建设一个新的结构措施来吸收一个字符串参数。它将先挪用默认结构措施,然后处理惩罚这个参数。(拜见代码段7 )并且,main()要领必需被修改以便在没有XML文件的事件中,仍然能建设一个默认的XmlEditor工具。(拜见代码段8)
代码段7:
public XmlEditor( String title, ArrayList xmlText ) throws
ParserConfigurationException
{
this( title );
textArea.setText( ( String )xmlText.get( 0 ) + "\n" );
for ( int i = 1; i < xmlText.size(); i++ )
textArea.append( ( String )xmlText.get( i ) + "\n" );
xTree.refresh( textArea.getText() );
}
代码段8:
#p#分页标题#e#
public static void main( String[] args )
{
String fileName = "";
BufferedReader reader;
String line;
ArrayList xmlText = null;
XmlEditor xmlEditor;
try
{
if( args.length > 0 )
{
fileName = args[0];
if ( fileName.substring( fileName.indexOf( '.' ) ).equals( ".xml" ) )
{
reader = new BufferedReader( new FileReader( fileName ) );
xmlText = new ArrayList();
while ( ( line = reader.readLine() ) != null )
{
xmlText.add( line );
}
reader.close();
xmlEditor = new XmlEditor( "XmlEditor 1.0", xmlText );
}
else
{
help();
}
}
else
{
xmlEditor = new XmlEditor( "XmlEditor 1.0" );
}
}
catch( FileNotFoundException fnfEx )
{
System.out.println( fileName + " was not found." );
exit();
}
catch( Exception ex )
{
ex.printStackTrace();
exit();
}
}
为了很容易地处理惩罚 JTextArea数据,还需要最后一次须要的修改。一般我们不把这段文本当成一个长的字符串,而是把它当成一系列字符串,每行暗示一个包括在数组列表中的字符串。这需要修改我们的结构措施吸收的参数,而且修改在先前把这个数据作为一个字符串传入的谁人main()要领中的任何挪用。这还需要导入 java.util包 (拜见代码段8 ) 。
测试这个应用措施
最后,我们必需添加一些异常处理惩罚到 XTree类中。假如你运行这个应用措施并输入无效的XML数据到 JTextArea中,这个措施就会瓦解。我们虽然不想这样的工作产生。今朝,我们把堕落信息打印到呼吁行中。在下一篇文章中,我们将在一个图形对话框中显示堕落信息。
假如无效的或名目欠好的 XML数据被输入 JTextArea然后按“Refresh”按钮,然后理会器将抛出一个错误,在本例中,parseXML()要领中包括的当前异常处理惩罚将当即退出。我们想要这个措施陈诉这个错误并返回一个空值来指出这个理会是不乐成的。(见代码段9)你大概留意到 XTree类中的“buildTree()”和“refresh()”这两个要领有一个条件语句以制止处理惩罚空值。这是因为假如它们试着去处理惩罚一个空值它们也会陈诉异常。这个事件链保持措施流举办而且保持 XTree模子不变。
最后,我们就可以测试这个应用措施,测试进程我在这里就不多说了。