In Java, text is just a form of graphics, so we've already been working with graphics. In this next example, I'll create a nontext browser that reads an XML document and uses it to draw graphics figurescircles. Here's what a document that this browser might read, ch11_06.xml, looks like. I'm specifying the (x, y) origin of the circle and the radius of the circle as attributes of the <CIRCLE> element: Listing ch11_06.xml<?xml version = "1.0" ?> <!DOCTYPE DOCUMENT [ <!ELEMENT DOCUMENT (CIRCLE ELLIPSE)*> <!ELEMENT CIRCLE EMPTY> <!ELEMENT ELLIPSE EMPTY> <!ATTLIST CIRCLE X CDATA #IMPLIED Y CDATA #IMPLIED RADIUS CDATA #IMPLIED> <!ATTLIST ELLIPSE X CDATA #IMPLIED Y CDATA #IMPLIED WIDTH CDATA #IMPLIED HEIGHT CDATA #IMPLIED> ]> <DOCUMENT> <CIRCLE X='200' Y='160' RADIUS='50' /> <CIRCLE X='170' Y='100' RADIUS='15' /> <CIRCLE X='80' Y='200' RADIUS='45' /> <CIRCLE X='200' Y='140' RADIUS='35' /> <CIRCLE X='130' Y='240' RADIUS='25' /> <CIRCLE X='270' Y='300' RADIUS='45' /> <CIRCLE X='210' Y='240' RADIUS='25' /> <CIRCLE X='60' Y='160' RADIUS='35' /> <CIRCLE X='160' Y='260' RADIUS='55' /> </DOCUMENT> I'll call this example circles.java. We'll need to decode the XML document and store the specification of each circle. To store that data, I'll create an array named x to hold the x coordinates of the circles, y to hold the y coordinates, and radius to hold the radii of the circles. I'll also store our current location in these arrays in an integer named numberFigures : public class circles { static int numberFigures = 0; static int x[] = new int[100]; static int y[] = new int[100]; static int radius[] = new int[100]; . . . As we parse the document, I'll filter out elements and search for <CIRCLE> elements. When I find a <CIRCLE> element, I'll store its x, y, and radius values in the appropriate array. To check whether the current node is a <CIRCLE> element, I'll compare the node's name , which I get with the getNodeName method, to "CIRCLE" using the Java String method equals , which you must use with String objects instead of the == operator: if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getNodeName().equals("CIRCLE")) { . . . } . . . To find the value of the X , Y , and RADIUS attributes, I'll use the getAttributes method to get a NamedNodeMap object representing all the attributes of this element. To get the value of specific attributes, I get the node corresponding to that attribute with the getNamedItem method. I get the attribute's actual value with getNodeValue like this, where I'm converting the attribute data from strings to integers using the Java Integer class's parseInt method: if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getNodeName().equals("CIRCLE")) { NamedNodeMap attrs = node.getAttributes(); x[numberFigures] = Integer.parseInt((String)attrs.getNamedItem("X").getNodeValue( )); y[numberFigures] = Integer.parseInt((String)attrs.getNamedItem("Y").getNodeValue( )); radius[numberFigures] = Integer.parseInt ((String)attrs.getNamedItem("RADIUS"). getNodeValue()); numberFigures++; } . . . You can find the methods of the NamedNodeMap interface in Table 11-8. Table 11-8. NamedNodeMap Interface Methods
After parsing the document, the required data is in the x , y , and radius arrays. All that's left is to display the corresponding circles, and I'll use the Java Graphics object's drawOval method to do that. This method draws ellipses and takes the (x, y) location of the figure's upper-left corner, as well as the minor and major axes lengths. To draw circles, I'll set both those lengths to the radius value for the circle. It all looks like this in the AppFrame class, which is where we draw the browser's window: class AppFrame extends Frame { int numberFigures; int[] xValues; int[] yValues; int[] radiusValues; public AppFrame(int number, int[] x, int[] y, int[] radius) { numberFigures = number; xValues = x; yValues = y; radiusValues = radius; } public void paint(Graphics g) { for(int loopIndex = 0; loopIndex < numberFigures; loopIndex++){ g.drawOval(xValues[loopIndex], yValues[loopIndex], radiusValues[loopIndex], radiusValues[loopIndex]); } } And that's all it takes. You can see the results in Figure 11-4, where the browser is displaying ch11_06.xml. The complete listing appears in Listing ch11_04.java. Figure 11-4. Creating a graphical XML browser.
Listing ch11_07.javaimport java.awt.*; import java.awt.event.*; import javax.xml.parsers.*; import org.w3c.dom.*; public class ch11_07 { static int numberFigures = 0; static int x[] = new int[100]; static int y[] = new int[100]; static int radius[] = new int[100]; public static void displayDocument(String uri) { try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = null; try { db = dbf.newDocumentBuilder(); } catch (ParserConfigurationException pce) {} Document document = null; document = db.parse(uri); display(document); } catch (Exception e) { e.printStackTrace(System.err); } } public static void display(Node node) { if (node == null) { return; } int type = node.getNodeType(); if (node.getNodeType() == Node.DOCUMENT_NODE) { display(((Document)node).getDocumentElement()); } if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getNodeName().equals("CIRCLE")) { NamedNodeMap attrs = node.getAttributes(); x[numberFigures] = Integer.parseInt((String) attrs.getNamedItem("X"). getNodeValue()); y[numberFigures] = Integer.parseInt((String) attrs.getNamedItem("Y"). getNodeValue()); radius[numberFigures] = Integer.parseInt((String) attrs.getNamedItem( "RADIUS").getNodeValue()); numberFigures++; } NodeList childNodes = node.getChildNodes(); if (childNodes != null) { int length = childNodes.getLength(); for (int loopIndex = 0; loopIndex < length; loopIndex++) { display(childNodes.item(loopIndex)); } } } } public static void main(String args[]) { displayDocument(args[0]); AppFrame f = new AppFrame(numberFigures, x, y, radius); f.setSize(400, 400); f.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {System.exit(0);}}); f.show(); } } class AppFrame extends Frame { int numberFigures; int[] xValues; int[] yValues; int[] radiusValues; public AppFrame(int number, int[] x, int[] y, int[] radius) { numberFigures = number; xValues = x; yValues = y; radiusValues = radius; } public void paint(Graphics g) { for(int loopIndex = 0; loopIndex < numberFigures; loopIndex++){g.drawOval( xValues[loopIndex], yValues[loopIndex], radiusValues[loopIndex], radiusValues[loopIndex]); } } } |