出自:yesky wayne
這是本系列的第二篇文章。在上一篇文章中,我們簡(jiǎn)要地討論了XML以及為什么一個(gè)樹(shù)形結(jié)構(gòu)適合顯示XML、如何處理XML數(shù)據(jù)、如何使用JTree Swing 組件以及如何創(chuàng)建一個(gè)可重用的能夠分析XML文檔以及在Jtree顯示數(shù)據(jù)的組件。
在本文中,我們將創(chuàng)建我們的XML編輯器的框架,為了達(dá)到這個(gè)目的,我們將用到許多Swing組件(包括JsplitPane、JscrollPane、Jbutton和JtextArea組件)。
一、問(wèn)題的提出與解決
我如何創(chuàng)建一個(gè)能夠?yàn)g覽文本和瀏覽視圖的XML文本編輯器呢?創(chuàng)建一個(gè)包含Jbutton和JsplitPane的Jframe對(duì)象, 然后讓JsplitPane對(duì)象包含兩個(gè)JscrollPane對(duì)象,一個(gè)用于瀏覽圖形(xTree類(lèi)),另一個(gè)用于瀏覽文本(JtextArea類(lèi))。Jbutton用來(lái)管理刷新圖形瀏覽的操作。
二、增強(qiáng)Xtree類(lèi)的功能
在上一篇文章中,我們開(kāi)發(fā)了Xtree類(lèi),這是一個(gè)可重用的組件,繼承于Jtree類(lèi)并能夠把XML數(shù)據(jù)以圖形樹(shù)的形式顯示。我們現(xiàn)在就增強(qiáng)這個(gè)類(lèi), 通過(guò)提供給它一個(gè)在顯示默認(rèn)的XML樹(shù)來(lái)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. 而且,我們還將添加一些錯(cuò)誤處理邏輯以便程序不會(huì)因?yàn)闊o(wú)效的XML而崩潰。
第一步是創(chuàng)建一個(gè)名為buildTree()的方法:
private DefaultTreeModel buildTree( String text )
{
DefaultMutableTreeNode treeNode;
Node newNode;
// 采用DOM根節(jié)點(diǎn)并把它轉(zhuǎn)化成為一個(gè)Tree模型
newNode = parseXml( text );
if ( newNode != null )
{
treeNode = createTreeNode( newNode );
return new DefaultTreeModel( treeNode );
}
else
return null;
} file://結(jié)束buildTree()
這個(gè)方法取得傳入的 XML字符串,分析這個(gè) XML字符串并構(gòu)造一個(gè)可以用來(lái)從數(shù)據(jù)中構(gòu)造圖形樹(shù)形結(jié)構(gòu)的DefaultTreeModel變量實(shí)例。這個(gè)功能原來(lái)包含在 XTree()構(gòu)造程序中,但是我們把它拿出來(lái)然后把它放進(jìn)一個(gè)單獨(dú)的方法中,這樣我們就有了創(chuàng)建一個(gè)默認(rèn)圖形樹(shù)的伸縮性。這就是我們接下來(lái)想做的事。
接下來(lái)一步是創(chuàng)建一個(gè)叫 buildWelcomeTree()的方法。這個(gè)方法一次構(gòu)建一個(gè)DefaultTreeModel變量,而不是通過(guò)分析一個(gè)現(xiàn)有的XML文字字符串。如果用戶沒(méi)有指定 XML文件就啟動(dòng)這個(gè)應(yīng)用程序,將顯示 DefaultTreeModel。見(jiàn)代碼段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 );
}
接下來(lái)的我們需要添加一個(gè)新的構(gòu)造程序來(lái)簡(jiǎn)化默認(rèn)顯示功能,我們將修改主構(gòu)造程序,這樣它就不能接受任何參數(shù),創(chuàng)建一個(gè)新的能接收單一的 XML文本字符串的構(gòu)造程序。這樣以來(lái),如果沒(méi)有 XML文本被顯示的話就會(huì)創(chuàng)建默認(rèn) XTree對(duì)象,而如果 XML文本被顯示的話將創(chuàng)建一個(gè)唯一的 XTree對(duì)象。代碼段2中給出了兩個(gè)構(gòu)造程序。
代碼段2:
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() );
}
三、創(chuàng)建 XmlEditor類(lèi)
XmlEditor類(lèi)與前面的那篇文章的XTreeTester類(lèi)有相同的用途,不同之處在于 XmlEditor包括一個(gè) JTextArea,允許你操作文本版XML。之后,你可以點(diǎn)擊 “Refresh”按鈕并查看 XTree組件中反映出來(lái)的變化。
如果直接修改第一篇文章中的代碼,你就能節(jié)省很多時(shí)間,你可以把 XTreeTester.java文件重命名為 XmlEditor.java (不過(guò)一定要修改構(gòu)造程序 )并把它當(dāng)成模板文件。
要做的第一件事是添加下列 Swing組件:另一個(gè) JScrollPane、 JSplitPane、 JTextArea和 JButton。通過(guò)聲明所有的這些組件以及其他組件開(kāi)始(看代碼段3)。
代碼段3:
private XTree xTree;
private JScrollPane jScroll, jScrollRt;
private JSplitPane splitPane;
private JButton refreshButton;
private WindowListener winClosing;
首先,我們將創(chuàng)建并添加“ Refresh”按鈕。這個(gè)按鈕用來(lái)指示這個(gè) XTree組件將使用當(dāng)前 XML文本來(lái)刷新。我們還需要使用一個(gè)ActionListener來(lái)注冊(cè)它。(參見(jiàn)代碼段 4 ) 為了攔截按鈕事件,我們需要有這個(gè)類(lèi)還要實(shí)現(xiàn) ActionListener,而且我們還需要?jiǎng)?chuàng)建一個(gè) actionPerformed()方法 (參見(jiàn)代碼段 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() );
}
接下來(lái),我們將創(chuàng)建新的 JScrollPane和 JTextArea并且把 JTextArea添加到 JScrollPane中。這樣,我們將得到包含 XTree組件的原始的 JScrollPane和包含 JTextArea組件的新的 JScrollPane。這個(gè)原始的 XTree構(gòu)造程序還有一個(gè)修改之處。我們將刪除先前傳進(jìn)這個(gè)方法的字符串參數(shù)。(該功能通過(guò)我們接下來(lái)要構(gòu)建的另一個(gè) XmlEditor()構(gòu)造程序操作)我們把這兩個(gè)方框放進(jìn)一個(gè) JSplitPane中,它是一個(gè)有分隔器的組件,可以在這個(gè)分隔器的另一邊包含一個(gè)組件。(參見(jiàn)代碼段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 );
現(xiàn)在我們需要修改這個(gè)構(gòu)造程序來(lái)處理這個(gè)非 XML文件的情景。刪除當(dāng)前構(gòu)造程序需要的第二個(gè)字符串參數(shù)。這個(gè)構(gòu)造程序現(xiàn)在就是默認(rèn)的構(gòu)造程序。我們將創(chuàng)建一個(gè)新的構(gòu)造程序來(lái)接收一個(gè)字符串參數(shù)。它將先調(diào)用默認(rèn)構(gòu)造程序,然后處理這個(gè)參數(shù)。(參見(jiàn)代碼段7 )而且,main()方法必須被修改以便在沒(méi)有XML文件的事件中,仍然能創(chuàng)建一個(gè)默認(rèn)的XmlEditor對(duì)象。(參見(jiàn)代碼段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:
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數(shù)據(jù),還需要最后一次必要的修改。一般我們不把這段文本當(dāng)成一個(gè)長(zhǎng)的字符串,而是把它當(dāng)成一系列字符串,每行表示一個(gè)包含在數(shù)組列表中的字符串。這需要修改我們的構(gòu)造程序接收的參數(shù),并且修改在先前把這個(gè)數(shù)據(jù)作為一個(gè)字符串傳入的那個(gè)main()方法中的任何調(diào)用。這還需要導(dǎo)入 java.util包 (參見(jiàn)代碼段8 ) 。
測(cè)試這個(gè)應(yīng)用程序
最后,我們必須添加一些異常處理到 XTree類(lèi)中。如果你運(yùn)行這個(gè)應(yīng)用程序并輸入無(wú)效的XML數(shù)據(jù)到 JTextArea中,這個(gè)程序就會(huì)崩潰。我們當(dāng)然不想這樣的事情發(fā)生。目前,我們把出錯(cuò)信息打印到命令行中。在下一篇文章中,我們將在一個(gè)圖形對(duì)話框中顯示出錯(cuò)信息。
如果無(wú)效的或格式不好的 XML數(shù)據(jù)被輸入 JTextArea然后按“Refresh”按鈕,然后解析器將拋出一個(gè)錯(cuò)誤,在本例中,parseXML()方法中包含的當(dāng)前異常處理將立即退出。我們想要這個(gè)程序報(bào)告這個(gè)錯(cuò)誤并返回一個(gè)空值來(lái)指出這個(gè)解析是不成功的。(見(jiàn)代碼段9)你可能注意到 XTree類(lèi)中的“buildTree()”和“refresh()”這兩個(gè)方法有一個(gè)條件語(yǔ)句以避免處理空值。這是因?yàn)槿绻鼈冊(cè)囍ヌ幚硪粋€(gè)空值它們也會(huì)報(bào)告異常。這個(gè)事件鏈保持程序流進(jìn)行并且保持 XTree模型穩(wěn)定。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。