archive-edu.com » EDU » H » HWS.EDU

Total: 727

Choose link from "Titles, links and description words view":

Or switch to "Titles and links view".
  • Index of /javanotes/source/chapter12/netgame/fivecarddraw
    31 07 30 6 0K PokerDeck java 2015 07 31 07 30 3 9K PokerGameState java 2015 07 31 07 30 3 2K PokerHub java 2015 07 31 07 30 18K PokerRank java 2015 07 31 07 30 25K PokerWindow

    Original URL path: http://math.hws.edu/javanotes/source/chapter12/netgame/fivecarddraw/ (2016-02-07)
    Open archived version from archive


  • Javanotes 7.0, Section 13.1 -- Images and Resources
    7 3 3 where the user s drawing is recorded as a list of objects that represent the shapes that the user drew You should try the program Try drawing a Filled Rectangle on top of some other shapes As you drag the mouse the rectangle stretches from the starting point of the mouse drag to the current mouse location As the mouse moves the underlying picture seems to be unaffected parts of the picture can be covered up by the rectangle and later uncovered as the mouse moves and they are still there What this means is that the rectangle that is shown as you drag the mouse can t actually be part of the off screen canvas since drawing something into an image means changing the color of some pixels in the image The previous colors of those pixels are not stored anywhere else and so are permanently lost In fact as you draw a line rectangle or oval in PaintWithOffScreenCanvas the shape that is shown as you drag the mouse is not drawn to the off screen canvas at all Instead the paintComponent method draws the shape on top of the contents of the canvas Only when you release the mouse does the shape become a permanent part of the off screen canvas This illustrates the point that when an off screen canvas is used not everything that is visible on the screen has to be drawn on the canvas Some extra stuff can be drawn on top of the contents of the canvas by the paintComponent method The other tools are handled differently from the shape tools For the curve erase and smudge tools the changes are made to the canvas immediately as the mouse is being dragged Let s look at how an off screen canvas is used in this program The canvas is represented by an instance variable OSC of type BufferedImage The size of the canvas must be the same size as the panel on which the canvas is displayed The size can be determined by calling the getWidth and getHeight instance methods of the panel Furthermore when the canvas is first created it should be filled with the background color which is represented in the program by an instance variable named fillColor All this is done by the method This method creates the off screen canvas and fills it with the current fill color private void createOSC OSC new BufferedImage getWidth getHeight BufferedImage TYPE INT RGB Graphics osg OSC createGraphics osg setColor fillColor osg fillRect 0 0 getWidth getHeight osg dispose Note how it uses OSC createGraphics to obtain a graphics context for drawing to the image Also note that the graphics context is disposed at the end of the method When you create a graphics context it is good practice to dispose of it when you are finished with it There still remains the problem of where to call this method The problem is that the width and height of the panel object are not set until some time after the panel object is constructed If createOSC is called in the constructor getWidth and getHeight will return the value zero and we won t get an off screen image of the correct size The approach that I take in PaintWithOffScreenCanvas is to call createOSC in the paintComponent method the first time the paintComponent method is called At that time the size of the panel has definitely been set but the user has not yet had a chance to draw anything With this in mind you are ready to understand the paintComponent method public void paintComponent Graphics g First create the off screen canvas if it does not already exist if OSC null createOSC Copy the off screen canvas to the panel Since we know that the image is already completely available the fourth ImageObserver parameter to g drawImage can be null Since the canvas completely fills the panel there is no need to call super paintComponent g g drawImage OSC 0 0 null If the user is currently dragging the mouse to draw a line oval or rectangle draw the shape on top of the image from the off screen canvas using the current drawing color This is not done if the user is drawing a curve or using the smudge curve or erase tool if dragging SHAPE TOOLS contains currentTool g setColor currentColor putCurrentShape g Here dragging is a boolean instance variable that is set to true while the user is dragging the mouse and currentTool tells which tool is currently in use The possible tools are defined by an enum named Tool and SHAPE TOOLS is a variable of type EnumSet Tool that contains the line oval rectangle filled oval and filled rectangle tools See Subsection 10 2 4 You might notice that there is a problem if the size of the panel is ever changed since the size of the off screen canvas will not be changed to match The PaintWithOffScreenCanvas program does not allow the user to resize the program s window so this is not an issue in that program If we want to allow resizing however a new off screen canvas must be created whenever the size of the panel changes One simple way to do this is to check the size of the canvas in the paintComponent method and to create a new canvas if the size of the canvas does not match the size of the panel if OSC null getWidth OSC getWidth getHeight OSC getHeight createOSC Of course this will discard the picture that was contained in the old canvas unless some arrangement is made to copy the picture from the old canvas to the new one before the old canvas is discarded The other point in the program where the off screen canvas is used is during a mouse drag operation which is handled in the mousePressed mouseDragged and mouseReleased methods The strategy that is implemented was discussed above Shapes are drawn to the off screen canvas only at the end of the drag operation in the mouseReleased method However as the user drags the mouse the part of the image over which the shape appears is re copied from the canvas onto the screen each time the mouse is moved Then the paintComponent method draws the shape that the user is creating on top of the image from the canvas For the non shape curve smudge and erase tools on the other hand changes are made directly to the canvas and the region that was changed is repainted so that the change will appear on the screen By the way the program uses a version of the repaint method that repaints just a part of a component The command repaint x y width height tells the system to repaint the rectangle with upper left corner x y and with the specified width and height This can be substantially faster than repainting the entire component See the source code PaintWithOffScreenCanvas java if you want to see how it s all done One traditional use of off screen canvasses is for double buffering In double buffering the off screen image is an exact copy of the image that appears on screen whenever the on screen picture needs to be redrawn the new picture is drawn step by step to an off screen image This can take some time If all this drawing were done on screen the user might see the image flicker as it is drawn Instead the long drawing process takes place off screen and the completed image is then copied very quickly onto the screen The user doesn t see all the steps involved in redrawing This technique can be used to implement smooth flicker free animation The term double buffering comes from the term frame buffer which refers to the region in memory that holds the image on the screen In fact true double buffering uses two frame buffers The video card can display either frame buffer on the screen and can switch instantaneously from one frame buffer to the other One frame buffer is used to draw a new image for the screen Then the video card is told to switch from one frame buffer to the other No copying of memory is involved Double buffering as it is implemented in Java does require copying which takes some time and is not perfectly flicker free In Java s older AWT graphical API it was up to the programmer to do double buffering by hand In the Swing graphical API double buffering is applied automatically by the system and the programmer doesn t have to worry about it It is possible to turn this automatic double buffering off in Swing but there is seldom a good reason to do so One final historical note about off screen canvasses There is an alternative way to create them The Component class defines the following instance method which can be used in any GUI component object public Image createImage int width int height This method creates an Image with a specified width and height You can use this image as an off screen canvas in the same way that you would a BufferedImage In fact you can expect that in a modern version of Java the image that is returned by this method is in fact a BufferedImage The createImage method was part of Java from the beginning before the BufferedImage class was introduced 13 1 2 Working With Pixels One good reason to use a BufferedImage is that it allows easy access to the colors of individual pixels If image is of type BufferedImage then we have the methods image getRGB x y returns an int that encodes the color of the pixel at coordinates x y in the image The values of the integers x and y must lie within the image That is it must be true that 0 x image getWidth and 0 y image getHeight if not then an exception is thrown image setRGB x y rgb sets the color of the pixel at coordinates x y to the color encoded by rgb Again x and y must be in the valid range The third parameter rgb is an integer that encodes the color These methods use integer codes for colors If c is of type Color the integer code for the color can be obtained by calling c getRGB Conversely if rgb is an integer that encodes a color the corresponding Color object can be obtained with the constructor call new Color rgb This means that you can use Color c new Color image getRGB x y to get the color of a pixel as a value of type Color And if c is of type Color you can set a pixel to that color with image setRGB x y c getRGB The red green and blue components of a color are represented as 8 bit integers in the range 0 to 255 When a color is encoded as a single int the blue component is contained in the eight low order bits of the int the green component in the next lowest eight bits and the red component in the next eight bits The eight high order bits store the alpha component of the color which we ll encounter in the next section It is easy to translate between the two representations using the shift operators and and the bitwise logical operators and I have not covered these operators previously in this book Briefly If A and B are integers then A B is the integer obtained by shifting each bit of A B bit positions to the left A B is the integer obtained by shifting each bit of A B bit positions to the right A B is the integer obtained by applying the logical and operation to each pair of bits in A and B and A B is obtained similarly using the logical or operation For example using 8 bit binary numbers we have 01100101 10100001 is 00100001 while 01100101 10100001 is 11100101 You don t necessarily need to understand these operators Here are incantations that you can use to work with color codes Suppose that rgb is an int that encodes a color To get separate red green and blue color components int red rgb 16 0xFF int green rgb 8 0xFF int blue rgb 0xFF Suppose that red green and blue are color components in the range 0 to 255 To combine them into a single int int rgb red 16 green 8 blue An example of using pixel colors in a BufferedImage is provided by the smudge tool in the sample program PaintWithOffScreenCanvas java The purpose of this tool is to smear the colors of an image as if it were drawn in wet paint For example if you rub the middle of a black rectangle with the smudge tool you ll get something like this This is an effect that can only be achieved by manipulating the colors of individual pixels Here s how it works when the user presses the mouse using the smudge tool the color components of a 7 by 7 block of pixels are copied from the off screen canvas into arrays named smudgeRed smudgeGreen and smudgeBlue This is done in the mousePressed routine with the following code int w OSC getWidth int h OSC getHeight int x evt getX int y evt getY for int i 0 i 7 i for int j 0 j 7 j int r y j 3 int c x i 3 if r 0 r h c 0 c w A 1 in the smudgeRed array indicates that the corresponding pixel was outside the canvas smudgeRed i j 1 else int color OSC getRGB c r smudgeRed i j color 16 0xFF smudgeGreen i j color 8 0xFF smudgeBlue i j color 0xFF The arrays are of type double because I am going to do some computations with them that require real numbers As the user moves the mouse the colors in the array are blended with the colors in the image just as if you were mixing wet paint by smudging it with your finger That is the colors at the new mouse position in the image are replaced with a weighted average of the current colors in the image and the colors in the arrays This has the effect of moving some of the color from the previous mouse position to the new mouse position At the same time the colors in the arrays are replaced by a weighted average of the old colors in the arrays and the colors from the image This has the effect of moving some color from the image into the arrays This is done using the following code for each pixel position c r in a 7 by 7 block around the new mouse location int curCol OSC getRGB c r int curRed curCol 16 0xFF int curGreen curCol 8 0xFF int curBlue curCol 0xFF int newRed int curRed 0 7 smudgeRed i j 0 3 int newGreen int curGreen 0 7 smudgeGreen i j 0 3 int newBlue int curBlue 0 7 smudgeBlue i j 0 3 int newCol newRed 16 newGreen 8 newBlue OSC setRGB c r newCol smudgeRed i j curRed 0 3 smudgeRed i j 0 7 smudgeGreen i j curGreen 0 3 smudgeGreen i j 0 7 smudgeBlue i j curBlue 0 3 smudgeBlue i j 0 7 13 1 3 Resources Throughout this textbook up until now we have been thinking of a program as made up entirely of Java code However programs often use other types of data including images sounds and text as part of their basic structure These data are referred to as resources An example is the image file cards png that was used in the HighLowWithImages java program earlier in this section This file is part of the program The program needs it in order to run The user of the program doesn t need to know that this file exists or where it is located as far as the user is concerned it is just part of the program The program of course does need some way of locating the resource file and loading its data Resources are ordinarily stored in files that are in the same locations as the compiled class files for the program Class files are located and loaded by something called a class loader which is represented in Java by an object of type ClassLoader A class loader has a list of locations where it will look for class files This list is called the class path It includes the location where Java s standard classes are stored It generally includes the current directory If the program is stored in a jar file the jar file is included on the class path In addition to class files a ClassLoader is capable of finding resource files that are located on the class path or in subdirectories of locations that are on the class path The first step in using a resource is to obtain a ClassLoader and to use it to locate the resource file In the HighLowWithImages program this is done with ClassLoader cl getClass getClassLoader URL imageURL cl getResource cards png The idea of the first line is that in order to get a class loader you have to ask a class that was loaded by the class loader Here getClass is a is a reference to object that represents the actual class HighLowWithImages The getClass method is an instance method in class Object and so can be used with any object Another way to get a reference to a class loader is to use ClassName class where ClassName is the name of any class For example I could have used HighLoadWithImages class getClassLoader to get the class loader in

    Original URL path: http://math.hws.edu/javanotes/c13/s1.html (2016-02-07)
    Open archived version from archive

  • Javanotes 7.0, Section 13.2 -- Fancier Graphics
    display area containing a triangle an oval a rectangle and some text Sliders at the bottom of the window allow you to control the degree of transparency of each shape When a slider is moved all the way to the right the corresponding shape is fully opaque all the way to the left and the shape is fully transparent Colors with alpha components were introduced in Java along with Graphics2D but they can be used with ordinary Graphics objects as well To specify the alpha component of a color you can create the Color object using one of the following constructors from the Color class public Color int red int green int blue int alpha public Color float red float green float blue float alpha In the first constructor all the parameters must be integers in the range 0 to 255 In the second the parameters must be in the range 0 0 to 1 0 For example Color transparentRed new Color 255 0 0 200 makes a slightly transparent red while Color tranparentCyan new Color 0 0F 1 0F 1 0F 0 5F makes a blue green color that is 50 opaque The advantage of the constructor that takes parameters of type float is that it lets you think in terms of percentages When you create an ordinary RGB color as in new Color 255 0 0 you just get a fully opaque color Once you have a transparent color you can use it in the same way as any other color That is if you want to use a Color c to draw in a graphics context g you just say g setColor c and subsequent drawing operations will use that color As you can see transparent colors are very easy to use A BufferedImage with image type BufferedImage TYPE INT ARGB can use transparency The color of each pixel in the image can have its own alpha component which tells how transparent that pixel will be when the image is drawn over some background A pixel whose alpha component is zero is perfectly transparent and has no effect at all when the image is drawn in effect it s not part of the image at all It is also possible for pixels to be partly transparent When an image is saved to a file information about transparency might be lost depending on the file format The PNG image format supports transparency JPEG does not If you look at the images of playing cards that are used in the program HighLowWithImages in Subsection 13 1 1 you might notice that the tips of the corners of the cards are fully transparent The card images are from a PNG file cards png An ARGB BufferedImage should be fully transparent when it is first created but if you want to make sure here is one way of doing so The Graphics2D class has a method setBackground that can be used to set a background color for the graphics context and it has a clearRect method that fills a rectangle with the current background color To create a fully transparent image with width w and height h you can use BufferedImage image new BufferedImage w h BufferedImage TYPE INT ARGB Graphics2D g2 image createGraphics g2 setBackground new Color 0 0 0 0 The R G and B values don t matter g2 clearRect 0 0 w h Note that simply drawing with a transparent color will not make pixels in the image transparent The alpha component of a Color makes the color transparent when it is used for drawing it does not change the transparency of the pixels that are modified by the drawing operation As an example just for fun here is a method that will set the cursor of a component to be a red square with a transparent interior private void useRedSquareCursor BufferedImage image new BufferedImage 24 24 BufferedImage TYPE INT ARGB Graphics2D g2 image createGraphics g2 setBackground new Color 0 0 0 0 g2 clearRect 0 0 24 24 should not be necessary in a new image g2 setColor Color RED g2 drawRect 0 0 23 23 draw a red border of width 3 around the square g2 drawRect 1 1 21 21 g2 drawRect 2 2 19 19 g2 dispose Point hotSpot new Point 12 12 Toolkit tk Toolkit getDefaultToolkit Cursor cursor tk createCustomCursor image hotSpot square setCursor cursor 13 2 3 Antialiasing To draw a geometric figure such as a line or circle you just have to color the pixels that are part of the figure right Actually there is a problem with this Pixels are little squares Geometric figures on the other hand are made of geometric points that have no size at all Think about drawing a circle and think about a pixel on the boundary of that circle The infinitely thin geometric boundary of the circle cuts through the pixel Part of the pixel lies inside the circle part lies outside So when we are filling the circle with color do we color that pixel or not A possible solution is to color the pixel if the geometric circle covers 50 or more of the pixel Following this procedure however leads to a visual defect known as aliasing It is visible in images as a jaggedness or staircasing effect along the borders of curved shapes Lines that are not horizontal or vertical also have a jagged aliased appearance The term aliasing seems to refer to the fact that many different geometric points map to the same pixel If you think of the real number coordinates of a geometric point as a name for the pixel that contains that point then each pixel has many different names or aliases It s not possible to build a circle out of squares but there is a technique that can eliminate some of the jaggedness of aliased images The technique is called antialiasing Antialiasing is based on transparency The idea is simple If 50 of a pixel is covered by the geometric figure that you are trying to draw then color that pixel with a color that is 50 transparent If 25 of the pixel is covered use a color that is 75 transparent 25 opaque If the entire pixel is covered by the figure of course use a color that is 100 opaque antialiasing only affects pixels that are only partly covered by the geometric shape In antialiasing the color that you are drawing with is blended with the original color of the pixel and the amount of blending depends on the fraction of the pixel that is covered by the geometric shape The fraction is difficult to compute exactly so in practice various methods are used to approximate it Of course you still don t get a picture of the exact geometric shape but antialiased images do tend to look better than jagged aliased images For an example look at the picture in the next subsection Antialiasing is used to draw the panels in the second and third row of the picture but it is not used in the top row You should note the jagged appearance of the lines in the top row By the way when antialiasing is applied to a line the line is treated as a geometric rectangle whose width is equal to the line width Antialiasing is supported in Graphics2D By default antialiasing is turned off If g2 is a graphics context of type Graphics2D you can turn on antialiasing in g2 by saying g2 setRenderingHint RenderingHints KEY ANTIALIASING RenderingHints VALUE ANTIALIAS ON As you can see this is only a hint that you would like to use antialiasing and it is even possible that the hint will be ignored However it is likely that subsequent drawing operations in g2 will be antialiased If you want to turn antialiasing off in g2 you should say g2 setRenderingHint RenderingHints KEY ANTIALIASING RenderingHints VALUE ANTIALIAS OFF 13 2 4 Strokes and Paints When using the Graphics class any line that you draw will be a solid line that is one pixel thick The Graphics2D class makes it possible to draw a much greater variety of lines You can draw lines of any thickness and you can draw lines that are dotted or dashed instead of solid An object of type Stroke contains information about how lines should be drawn including how thick the line should be and what pattern of dashes and dots if any should be used Every Graphics2D has an associated Stroke object The default Stroke draws a solid line of thickness one To get lines with different properties you just have to install a different stroke into the graphics context Stroke is an interface not a class The class BasicStroke which implements the Stroke interface is the one that is actually used to create stroke objects For example to create a stroke that draws solid lines with thickness equal to 3 use BasicStroke line3 new BasicStroke 3 If g2 is of type Graphics2D the stroke can be installed in g2 by calling its setStroke command g2 setStroke line3 After calling this method subsequent drawing operations will use lines that are three times as wide as the usual thickness The thickness of a line can be given by a value of type float not just by an int For example to use lines of thickness 2 5 in the graphics context g2 you can say g2 setStroke new BasicStroke 2 5F Fractional widths make more sense if antialiasing is turned on When you have a thick line the question comes up what to do at the ends of the line If you draw a physical line with a large round piece of chalk the ends of the line will be rounded When you draw a line on the computer screen should the ends be rounded or should the line simply be cut off flat With the BasicStroke class the choice is up to you Maybe it s time to look at examples This illustration shows fifteen lines drawn using different BasicStrokes Lines in the middle row have rounded ends lines in the other two rows are simply cut off at their endpoints Lines of various thicknesses are shown and the bottom row shows dashed lines And as mentioned above only the bottom two rows are antialiased This illustration is a screenshot from the sample program StrokeDemo java In that program you can click and drag in any of the small panels and the lines in all the panels will be redrawn as you move the mouse In addition if you right click and drag then rectangles will be drawn instead of lines this shows that strokes are used for drawing the outlines of shapes and not just for straight lines If you look at the corners of the rectangles that are drawn by the program you ll see that there are several ways of drawing a corner where two wide line segments meet All the options that you want for a BasicStroke have to be specified in the constructor Once the stroke object is created there is no way to change the options There is one constructor that lets you specify all possible options public BasicStroke float width int capType int joinType float miterlimit float dashPattern float dashPhase I don t want to cover all the options in detail but here s some basic info width specifies the thickness of the line capType specifies how the ends of a line are capped The possible values are BasicStroke CAP SQUARE BasicStroke CAP ROUND and BasicStroke CAP BUTT These values are used respectively in the first second and third rows of the above picture The default is BasicStroke CAP SQUARE joinType specifies how two line segments are joined together at corners Possible values are BasicStroke JOIN MITER BasicStroke JOIN ROUND and BasicStroke JOIN BEVEL Again these are used in the three rows of panels in the sample program you will only see the effect if you run the program and draw some rectangles The default is BasicStroke JOIN MITER miterLimit is used only if the value of joinType is JOIN MITER just use the default value 10 0F dashPattern is used to specify dotted and dashed lines The values in the array specify lengths in the dot dash pattern The numbers in the array represent the length of a solid piece followed by the length of a transparent piece followed by the length of a solid piece and so on At the end of the array the pattern wraps back to the beginning of the array If you want a solid line use a different constructor that has fewer parameters dashPhase tells the computer where to start in the dashPattern array for the first segment of the line Use 0 for this parameter in most cases For the third row in the above picture the dashPattern is set to new float 5 5 This means that the lines are drawn starting with a solid segment of length 5 followed by a transparent section of length 5 and then repeating the same pattern A simple dotted line would have thickness 1 and dashPattern new float 1 1 A pattern of short and long dashes could be made by using new float 10 4 4 4 For more information see the Java documentation or try experimenting with the source code for the sample program So now we can draw fancier lines But any drawing operation is still restricted to drawing with a single color We can get around that restriction by using Paint An object of type Paint is used to assign color to each pixel that is hit by a drawing operation Paint is an interface and the Color class implements the Paint interface When a color is used for painting it applies the same color to every pixel that is hit However there are other types of paint where the color that is applied to a pixel depends on the coordinates of that pixel Standard Java includes several classes that define paint with this property TexturePaint and several types of gradient paint In a texture the pixel colors come from an image which is repeated if necessary like a wallpaper pattern to cover the entire xy plane In a gradient the color that is applied to pixels changes gradually from one color to another color as you move from point to point Java has three types of gradient paints GradientPaint LinearGradientPaint and RadialGradientPaint It will be helpful to look at some examples This illustration shows a polygon filled with two different paints The polygon on the left uses a GradientPaint while the one on the right uses a TexturePaint Note that in this picture the paint is used only for filling the polygon The outline of the polygon is drawn in a plain black color However Paint objects can be used for drawing lines as well as for filling shapes These pictures were made by the sample program PaintDemo java In that program you can select among several different paints and you can control certain properties of the paints Basic gradient paints are created using the constructor public GradientPaint float x1 float y1 Color c1 float x2 float y2 Color c2 boolean cyclic This constructs a gradient that has color c1 at the point with coordinates x1 y1 and color c2 at the point x2 y2 As you move along the line between the two points the color of the gradient changes from c1 to c2 along lines perpendicular to this line the color is constant The last parameter cyclic tells what happens if you move past the point x2 y2 on the line from x1 y1 to x2 y2 If cyclic is false the color stops changing and any point beyond x2 y2 has color c2 If cyclic is true then the colors continue to change in a cyclic pattern after you move past x2 y2 It works the same way if you move past the other endpoint x1 y1 In most cases you will set cyclic to true Note that you can vary the points x1 y1 and x2 y2 to change the width and direction of the gradient For example to create a cyclic gradient that varies from black to light gray along the line from 0 0 to 100 100 use new GradientPaint 0 0 Color BLACK 100 100 Color LIGHT GRAY true The other two gradient paint classes LinearGradientPaint and RadialGradientPaint are more sophisticated Linear gradient paints are similar to GradientPaint but can be based on more than two colors Radial gradients color pixels based on their distance from a central point which produces rings of constant color instead of lines of constant color See the API documentation for details To construct a TexturePaint you need a BufferedImage that contains the image that will be used for the texture You also specify a rectangle in which the image will be drawn The image will be scaled if necessary to exactly fill the rectangle Outside the specified rectangle the image will be repeated horizontally and vertically to fill the plane You can vary the size and position of the rectangle to change the scale of the texture and its positioning on the plane Ordinarily however the upper left corner of the rectangle is placed at 0 0 and the size of the rectangle is the same as the actual size of the image The constructor for TexturePaint is defined as public TexturePaint BufferedImage textureImage Rectangle2D anchorRect The Rectangle2D class is part of the Graphics2D framework and will be discussed at the end of this section Often a call to the constructor takes the following form which will show the image at its actual size new TexturePaint image new Rectangle2D Double 0 0 image getWidth image getHeight Once you have a Paint object you can use the setPaint method of a Graphics2D object to install the paint in

    Original URL path: http://math.hws.edu/javanotes/c13/s2.html (2016-02-07)
    Open archived version from archive

  • Javanotes 7.0, Section 13.3 -- Actions and Buttons
    button shown above I created an ImageIcon from a BufferedImage on which I drew the picture that I wanted and I constructed the JButton using a constructor that takes both the text and the icon for the button as parameters Here s the code segment that does it BufferedImage image new BufferedImage 24 24 BufferedImage TYPE INT RGB Graphics2D g2 Graphics2D image getGraphics g2 setColor Color LIGHT GRAY Draw the image for the icon g2 fillRect 0 0 24 24 g2 setStroke new BasicStroke 3 Use thick lines g2 setColor Color BLACK g2 drawLine 4 4 20 20 Draw the X g2 drawLine 4 20 20 4 g2 dispose Icon clearIcon new ImageIcon image Create the icon JButton clearButton new JButton Clear the Display clearIcon You can create a button with an icon but no text by using a constructor that takes just the icon as parameter Another alternative is for the button to get its icon from an Action When a button is constructed from an action it takes its icon from the value of the action property Action SMALL ICON For example suppose that we want to use an action named clearAction to create the button shown above This could be done with clearAction putValue Action SMALL ICON clearIcon JButton clearButton new JButton clearAction The icon could also be associated with the action by passing it as a parameter to the constructor of an AbstractAction Action clearAction new AbstractAction Clear the Display clearIcon public void actionPerformed ActionEvent evt Carry out the action JButton clearButton new JButton clearAction The SMALL ICON for an Action will also be used by a JMenuItem created brom the action An action can also have an icon associated with the key Action LARGE ICON KEY If it does then a JButton will use the large icon in preference to the small icon However a JMenuItem will only use a small icon The appearance of buttons can be tweaked in many ways For example you can change the size of the gap between the button s text and its icon You can associate additional icons with a button that are used when the button is in certain states such as when it is pressed or when it is disabled It is even possible to change the positioning of the text with respect to the icon For example to place the text centered below the icon on a button you can say button setHorizontalTextPosition JButton CENTER button setVerticalTextPosition JButton BOTTOM These methods and many others are defined in the class AbstractButton This class is a superclass for JMenuItem as well as for JButton and for the classes that define check boxes and radio buttons Finally I will mention that it is possible to use icons on JLabels in much the same way that they can be used on JButtons Placing an ImageIcon on a JLabel can be a convenient way to add a static image to your GUI 13 3 3 Making Choices The JCheckBox class was covered in Subsection 6 5 3 and the equivalent for use in menus JCheckBoxMenuItem in Subsection 6 7 1 A checkbox lets the user make a choice between two alternatives A checkbox has two states selected and not selected and the user can change the state by clicking on the check box The state of a checkbox can also be set programmatically by calling its setSelected method and the current value of the state can be checked using the isSelected method Closely related to checkboxes are radio buttons Like a checkbox a radio button can be either selected or not However radio buttons are expected to occur in groups and at most one radio button in a group can be selected at any given time Radio button groups let the user make a choice among several alternatives In Java a radio button is represented by an object of type JRadioButton When used in isolation a JRadioButton acts just like a JCheckBox and it has the same methods and events Ordinarily however a JRadioButton is used in a group A group of radio buttons is represented by an object belonging to the class ButtonGroup A ButtonGroup is not a component and does not itself have a visible representation on the screen A ButtonGroup works behind the scenes to organize a group of radio buttons to ensure that at most one button in the group can be selected at any given time To use a group of radio buttons you must create a JRadioButton object for each button in the group and you must create one object of type ButtonGroup to organize the individual buttons into a group Each JRadioButton must be added individually to some container so that it will appear on the screen A ButtonGroup plays no role in the placement of the buttons on the screen Each JRadioButton must also be added to the ButtonGroup which has an add method for this purpose If you want one of the buttons to be selected initially you can call setSelected true for that button If you don t do this then none of the buttons will be selected until the user clicks on one of them As an example here is how you could set up a set of radio buttons that can be used to select a color JRadioButton redRadio blueRadio greenRadio yellowRadio Variables to represent the radio buttons These should probably be instance variables so that they can be used throughout the program ButtonGroup colorGroup new ButtonGroup redRadio new JRadioButton Red Create a button colorGroup add redRadio Add it to the group blueRadio new JRadioButton Blue colorGroup add blueRadio greenRadio new JRadioButton Green colorGroup add greenRadio yellowRadio new JRadioButton Yellow colorGroup add yellowRadio redRadio setSelected true Make an initial selection The individual buttons must still be added to a container if they are to appear on the screen If you want to respond immediately when the user clicks on one of the radio buttons you can register an ActionListener for each button Just as for checkboxes it is not always necessary to register listeners for radio buttons In some cases you can simply check the state of each button when you need to know it using the button s isSelected method You can add the equivalent of a group of radio buttons to a menu by using the class JRadioButtonMenuItem To use this class create several objects of this type and create a ButtonGroup to manage them Add each JRadioButtonMenuItem to the ButtonGroup and also add them to a JMenu If you want one of the items to be selected initially call its setSelected method to set its selection state to true You can add ActionListeners to each JRadioButtonMenuItem if you need to take some action when the user selects the menu item if not you can simply check the selected states of the buttons whenever you need to know them As an example suppose that menu is a JMenu Then you can add a group of buttons to menu as follows JRadioButtonMenuItem selectRedItem selectGreenItem selectBlueItem These might be defined as instance variables ButtonGroup group new ButtonGroup selectRedItem new JRadioButtonMenuItem Red group add selectRedItem menu add selectRedItem selectGreenItem new JRadioButtonMenuItem Green group add selectGreenItem menu add selectGreenItem selectBlueItem new JRadioButtonMenuItem Blue group add selectBlueItem menu add selectBlueItem When it s drawn on the screen a JCheckBox includes a little box that is either checked or unchecked to show the state of the box That box is actually a pair of Icons One icon is shown when the check box is unselected the other is shown when it is selected You can change the appearance of the check box by substituting different icons for the standard ones The icon that is shown when the check box is unselected is just the main icon for the JCheckBox You can provide a different unselected icon in the constructor or you can change the icon using the setIcon method of the JCheckBox object To change the icon that is shown when the check box is selected use the setSelectedIcon method of the JCheckBox All this applies equally to JRadioButton JCheckBoxMenuItem and JRadioButtonMenuItem An example of this can be found in the sample program ToolBarDemo java which is discussed in the next subsection That program creates a set of radio buttons that use custom icons The buttons are created by the following method Create a JRadioButton and add it to a specified button group The button is meant for selecting a drawing color in the display The color is used to create two custom icons one for the unselected state of the button and one for the selected state These icons are used instead of the usual radio button icons param c the color of the button and the color to be used for drawing Note that c has to be final since it is used in the anonymous inner class that defines the response to ActionEvents on the button param grp the ButtonGroup to which the radio button will be added param selected if true then the state of the button is set to selected return the radio button that was just created sorry but the button is not as pretty as I would like private JRadioButton makeColorRadioButton final Color c ButtonGroup grp boolean selected Create an ImageIcon for the normal unselected state of the button using a BufferedImage that is drawn here from scratch BufferedImage image new BufferedImage 30 30 BufferedImage TYPE INT RGB Graphics g image getGraphics g setColor Color LIGHT GRAY g fillRect 0 0 30 30 g setColor c g fill3DRect 1 1 24 24 true g dispose Icon unselectedIcon new ImageIcon image Create an ImageIcon for the selected state of the button image new BufferedImage 30 30 BufferedImage TYPE INT RGB g image getGraphics g setColor Color DARK GRAY g fillRect 0 0 30 30 g setColor c g fill3DRect 3 3 24 24 false g dispose Icon selectedIcon new ImageIcon image Create and configure the button JRadioButton button new JRadioButton unselectedIcon button setSelectedIcon selectedIcon button addActionListener new ActionListener public void actionPerformed ActionEvent e The action for this button sets the current drawing color in the display to c display setCurrentColor c grp add button if selected button setSelected true return button end makeColorRadioButton It is possible to create radio buttons and check boxes both the regular sort and the corresponding menu items from Actions The button or checkbox takes its name main icon tooltip text and enabled disabled state from the action And the Action s actionPerformed method is called when the user changes the state Furthermore an action has a property named Action SELECTED KEY which means that the action itself can have a selected state By default the value of the SELECTED KEY property is null and is not used for anything However you can set the value to be true or false by calling action putValue Action SELECTED KEY true or action putValue Action SELECTED KEY false Once you have done so the action s SELECTED KEY property and the selected state of any checkbox or radio button created from the action will automatically be kept in sync You can find out the current value of the property by calling action getValue Action SELECTED KEY Note that the value of a property is actually an object When you set the value to true or false the value is wrapped in an object of type Boolean The return type of action getValue is Object so you will probably need to type cast the return value to Boolean Java has another component that lets the user choose from a set of options the JComboBox A combo box contains a list of items but only displays the currently selected items The user clicks the combo box to see a pop up list of options and can then select from the list The functionality is similar to a group of radio buttons JComboBox is a parameterized class where the type parameter specifies the type of items that that combo box can hold Most commonly the items are strings and the type is JComboBox String This is the only case I will discuss When a JComboBox String object is first constructed it initially contains no items An item is added to the bottom of the list of options by calling the combo box s instance method addItem str where str is the string that will be displayed in the menu For example the following code will create an object of type JComboBox that contains the options Red Blue Green and Black JComboBox String colorChoice new JComboBox String colorChoice addItem Red colorChoice addItem Blue colorChoice addItem Green colorChoice addItem Black You can call the getSelectedIndex method of a JComboBox to find out which item is currently selected This method returns an integer that gives the position of the selected item in the list where the items are numbered starting from zero Alternatively you can call getSelectedItem to get the selected item itself This method returns a value of type Object even when the items are limited to being strings You can change the selection by calling the method setSelectedIndex n where n is an integer giving the position of the item that you want to select The most common way to use a JComboBox is to call its getSelectedIndex method when you have a need to know which item is currently selected However JComboBox components generate ActionEvents when the user selects an item and you can register an ActionListener with the JComboBox if you want to respond to such events as they occur JComboBoxes have a nifty feature which is probably not all that useful in practice You can make a JComboBox editable by calling its method setEditable true If you do this the user can edit the selection by clicking on the JComboBox and typing This allows the user to make a selection that is not in the pre configured list that you provide The Combo in the name JComboBox refers to the fact that it s a kind of combination of menu and text input box If the user has edited the selection in this way then the getSelectedIndex method will return the value 1 and getSelectedItem will return the string that the user typed An ActionEvent is triggered if the user presses return while typing in the JComboBox There is a lot of information in this section The sample program ChoiceDemo java demonstrates the use of combo boxes check boxes and radio buttons including the use of Actions with check boxes and radio buttons I encourage you to run the program to see how these things work and to read the source code The source code has a lot of comments to explain what is going on 13 3 4 Toolbars It has become increasingly common for programs to have a row of small buttons along the top or side of the program window that offer access to some of the commonly used features of the program The row of buttons is known as a tool bar Typically the buttons in a tool bar are presented as small icons with no text Tool bars can also contain other components such as JTextFields and JLabels In Swing tool bars are represented by the class JToolBar A JToolBar is a container that can hold other components It is also itself a component and so can be added to other containers In general the parent component of the tool bar should use a BorderLayout The tool bar should occupy one of the edge positions NORTH SOUTH EAST or WEST in the BorderLayout Furthermore the other three edge positions should be empty The reason for this is that it might be possible depending on the platform and configuration for the user to drag the tool bar from one edge position in the parent container to another It might even be possible for the user to drag the tool bar off its parent entirely so that it becomes a separate window Here is a picture of a toolbar This is from the sample program ToolBarDemo java which I discuss below In the demo program the user can draw colored curves in a large drawing area The first three buttons in the tool bar are a set of radio buttons that control the drawing color The fourth button is a push button that the user can click to clear the drawing Tool bars are easy to use You just have to create the JToolBar object add it to a container and add some buttons and possibly other components to the tool bar One fine point is adding space to a tool bar such as the gap between the radio buttons and the push button in the above picture You can leave a gap by adding a separator to the tool bar For example toolbar addSeparator new Dimension 20 20 This adds an invisible 20 by 20 pixel block to the tool bar This will appear as a 20 pixel gap between components Here is the constructor from the ToolBarDemo program It shows how to create the tool bar and place it in a container Note that class ToolBarDemo is a subclass of JPanel and the tool bar and display are added to the panel object that is being constructed public ToolBarDemo setLayout new BorderLayout 2 2 setBackground Color GRAY setBorder BorderFactory createLineBorder Color GRAY 2 display new Display the area where the user draws add display BorderLayout CENTER JToolBar toolbar new JToolBar add toolbar BorderLayout NORTH ButtonGroup group new ButtonGroup toolbar add makeColorRadioButton Color RED group true toolbar add makeColorRadioButton Color GREEN group false toolbar add makeColorRadioButton Color BLUE group false toolbar addSeparator new Dimension 20 20 toolbar add makeClearButton If you want a vertical tool bar that can be placed in the EAST or WEST position of a BorderLayout you should specify the orientation in the tool bar s constructor JToolBar

    Original URL path: http://math.hws.edu/javanotes/c13/s3.html (2016-02-07)
    Open archived version from archive

  • Javanotes 7.0, Section 13.4 -- Complex Components and MVC
    that position in the list are moved down to make room for the new item dlmodel setElementAt item index Replaces the item that is currently at position index in the list with item dlmodel remove index removes the item at position index in the list dlmodel removeAllElements removes everything from the list leaving it empty To use a modifiable JList T you should create a DefaultListModel T add any items to it that should be in the list initially and pass it to the JList constructor For example DefaultListModel String listModel JList String flavorList listModel new DefaultListModel String Create the model object listModel addElement Chocolate Add items to the model listModel addElement Vanilla listModel addElement Strawberry listModel addElement Rum Raisin flavorList new JList String listModel Create the list component By keeping a reference to the model around in an instance variable you will be able to add and delete flavors as the program is running by calling the appropriate methods in listModel Keep in mind that changes that are made to the model will automatically be reflected in the view Behind the scenes when a list model is modified it generates an event of type ListDataEvent The JList registers itself with its model as a listener for these events and it responds to an event by redrawing itself to reflect the changes in the model The programmer doesn t have to take any extra action beyond changing the model By the way the model for a JList actually has another part in addition to the ListModel An object of type ListSelectionModel stores information about which items in the list are currently selected When the model is complex it s not uncommon to use several model objects to store different aspects of the state 13 4 3 Tables and TableModels Like a JList a JTable displays a collection of items to the user However tables are much more complicated than lists Perhaps the most important difference is that it is possible for the user to edit items in the table Table items are arranged in a grid of rows and columns Each grid position is called a cell of the table Each column can have a header which appears at the top of the column and contains a name for the column It is easy to create a JTable from an array that contains the names of the columns and a two dimensional array that contains the items that go into the cells of the table As an example the sample program StatesAndCapitalsTableDemo java creates a table with two columns named State and Capital City The first column contains a list of the states of the United States and the second column contains the name of the capital city of each state The table can be created as follows String statesAndCapitals new String Alabama Montgomery Alaska Juneau Arizona Phoenix Wisconsin Madison Wyoming Cheyenne String columnHeads new String State Capital City JTable table new JTable statesAndCapitals columnHeads Since a table does not come with its own scroll bars it is almost always placed in a JScrollPane to make it possible to scroll the table For example add new JScrollPane table BorderLayout CENTER The column headers of a JTable are not actually part of the table they are in a separate component But when you add the table to a JScrollPane the column headers are automatically placed at the top of the pane Using the default settings the user can edit any cell in the table by clicking that cell When editing a cell the arrow keys can be used to move from one cell to another The user can change the order of the columns by dragging a column header to a new position The user can also change the width of the columns by dragging the line that separates neighboring column headers You can try all this in StatesAndCapitalsTableDemo java Allowing the user to edit all entries in the table is not always appropriate certainly it s not appropriate in the states and capitals example A JTable uses an object of type TableModel to store information about the contents of the table The model object is also responsible for deciding whether or not the user should be able to edit any given cell in the table TableModel includes the method public boolean isCellEditable int rowNum columnNum where rowNum and columnNum are the position of a cell in the grid of rows and columns that make up the table When the controller wants to know whether a certain cell is editable it calls this method in the table model If the return value is true the user is allowed to edit the cell The default model that is used when the table is created from an array of objects allows editing of all cells For this model the return value of isCellEditable is true in all cases To make some cells non editable you have to provide a different model for the table One way to do this is to create a subclass of DefaultTableModel and override the isCellEditable method DefaultTableModel and some other classes that are discussed in this section are defined in the package javax swing table Here is how this might have been done in the states and capitals program to make all cells non editable TableModel model new DefaultTableModel statesAndCapitals columnHeads public boolean isCellEditable int row int col return false JTable table new JTable model Here an anonymous subclass of DefaultTableModel is created in which the isCellEditable method returns false in all cases and the model object that is created from that class is passed as a parameter to the JTable constructor The DefaultTableModel class defines many methods that can be used to modify the table including for example setValueAt item rowNum colNum to change the item in a given cell removeRow rowNum to delete a row and addRow itemArray to add a new row at the end of the table that contains items from the array itemArray Note that if the item in a given cell is set to null then that cell will be empty Remember again that when you modify the model the view is automatically updated to reflect the changes In addition to the isCellEditable method the table model method that you are most likely to want to override is getColumnClass which is defined as public Class getColumnClass columnNum The purpose of this method is to specify what kind of values are allowed in the specified column The return value from this method is of type Class The is there for technical reasons having to do with generic programming See Section 10 5 but don t worry about understanding it here Although class objects have crept into this book in a few places in the discussion of ClassLoaders in Subsection 13 1 3 for example this is the first time we have directly encountered the class named Class An object of type Class represents a class A Class object is usually obtained from the name of the class using expressions of the form Double class or JTable class If you want a three column table in which the column types are String Double and Boolean you can use a table model in which getColumnClass is defined as public Class getColumnClass columnNum if columnNum 0 return String class else if columnNum 1 return Double class else return Boolean class The table will call this method and use the return value to decide how to display and edit items in the table For example if a column is specified to hold Boolean values the cells in that column will be displayed and edited as check boxes For numeric types the table will not accept illegal input when the user types in the value It is possible to change the way that a table edits or displays items See the methods setDefaultEditor and setDefaultRenderer in the JTable class As an alternative to using a subclass of DefaultTableModel a custom table model can also be defined using a subclass of AbstractTableModel Whereas DefaultTableModel provides a lot of predefined functionality AbstractTableModel provides very little However using AbstractTableModel gives you the freedom to represent the table data any way you want The sample program ScatterPlotTableDemo java uses a subclass of AbstractTableModel to define the model for a JTable In this program the table has three columns The first column holds a row number and is not editable The other columns hold values of type Double these two columns represent the x and y coordinates of points in the plane The points themselves are graphed in a scatter plot next to the table Initially the program fills in the first six points with random values Here is a picture of the program with the x coordinate in row 5 selected for editing Note by the way that in this program the scatter plot can be considered to be a view of the table model in the same way that the table itself is The scatter plot registers itself as a listener with the model so that it will receive notification whenever the model changes When that happens the scatter plot redraws itself to reflect the new state of the model It is an important property of the MVC pattern that several views can share the same model offering alternative presentations of the same data The views don t have to know about each other or communicate with each other except by sharing the model Although I didn t do it in this program it would even be possible to add a controller to the scatter plot view This could let the user add a point by clicking the mouse on the scatter plot or drag a point to change its coordinates The controller would update the table model based on the user actions Since the scatter plot and table share the same model the values displayed in the table would automatically change to match Here is the definition of the class that defines the model in the scatter plot program All the methods in this class must be defined in any subclass of AbstractTableModel except for setValueAt which only has to be defined if the table is modifiable This class defines the TableModel that is used for the JTable in this program The table has three columns Column 0 simply holds the row number of each row Column 1 holds the x coordinates of the points for the scatter plot and Column 2 holds the y coordinates The table has 25 rows No support is provided for adding more rows private class CoordInputTableModel extends AbstractTableModel private Double xCoord new Double 25 Data for Column 1 private Double yCoord new Double 25 Data for Column 2 Initially all the values in the array are null which means that all the cells are empty public int getColumnCount Tells caller how many columns there are return 3 public int getRowCount Tells caller how many rows there are return xCoord length public Object getValueAt int row int col Get value from cell if col 0 return row 1 Column 0 holds the row number else if col 1 return xCoord row Column 1 holds the x coordinates else return yCoord row Column 2 holds the y coordinates public Class getColumnClass int col Get data type of column if col 0 return Integer class else return Double class public String getColumnName int col Returns a name for column header if col 0 return Num else if col 1 return X else return Y public boolean isCellEditable int row int col Can user edit cell return col 0 public void setValueAt Object obj int row int col This method is called by the system if the value of the cell needs to be changed because the user has edited the cell It can also be called to change the value programmatically In this case only columns 1 and 2 can be modified and the data type for obj must be Double The method fireTableCellUpdated has to be called to send an event to registered listeners to notify them of the modification to the table model if col 1 xCoord row Double obj else if col 2 yCoord row Double obj fireTableCellUpdated row col end nested class CoordInputTableModel In addition to defining a custom table model I customized the appearance of the table in several ways Because this involves changes to the view most of the changes are made by calling methods in the JTable object For example since the default height of the cells was too small for my taste I called table setRowHeight 25 to increase the height To make lines appear between the rows and columns I found that I had to call both table setShowGrid true and table setGridColor Color BLACK Some of the customization has to be done to other objects For example to prevent the user from changing the order of the columns by dragging the column headers I had to use table getTableHeader setReorderingAllowed false Tables are quite complex and I have only discussed a part of the table API here Nevertheless I hope that you have learned enough to start using them and to learn more about them on your own 13 4 4 Documents and Editors As a final example of complex components we look briefly at JTextComponent and its subclasses A JTextComponent displays text that can optionally be edited by the user Two subclasses JTextField and JTextArea were introduced in Subsection 6 5 4 But the real complexity comes in another subclass JEditorPane that supports display and editing of styled text This allows features such as boldface and italic A JEditorPane can even work with basic HTML documents It is almost absurdly easy to write a simple web browser program using a JEditorPane although the program that you get can only handle basic web pages and does a pretty bad job on many modern web pages This is done in the sample program SimpleWebBrowser java In this program the user enters the URL of a web page and the program tries to load and display the web page at that location A JEditorPane can handle pages with content type text plain text html and text rtf The content type text rtf represents styled or rich text format text URLs and content types were covered in Subsection 11 4 1 If editPane is of type JEditorPane and url is of type URL then the statement editPane setPage url is sufficient to load the page and display it Since this can generate an exception the following method is used in SimpleWebBrowser java to display a page private void loadURL URL url try editPane setPage url catch Exception e editPane setContentType text plain Set pane to display plain text editPane setText Sorry the requested document was not found n or cannot be displayed n nError e An HTML document can include links to other pages When the user clicks on a link the web browser should go to the linked page A JEditorPane does not do this automatically but it does generate an event of type HyperLinkEvent when the user clicks a link provided that the edit pane has been set to be non editable by the user A program can register a listener for such events and respond by loading the new page There are a lot of web pages that a JEditorPane won t be able to display correctly but it can be very useful in cases where you have control over the pages that will be displayed A nice application is to distribute HTML format help and information files with a program The files can be stored as resource files in the jar file of the program and a URL for a resource file can be obtained in the usual way using the getResource method of a ClassLoader See Subsection 13 1 3 It turns out by the way that SimpleWebBrowser java is a little too simple A modified version SimpleWebBrowserWithThread java improves on the original by using a thread to load a page and by checking the content type of a page before trying to load it It actually does work as a simple web browser Try it The model for a JTextComponent is an object of type Document If you want to be notified of changes in the model you can add a listener to the model using textComponent getDocument addDocumentListener listener where textComponent is of type JTextComponent and listener is of type DocumentListener The Document class also has methods that make it easy to read a document from a file and write a document to a file I won t discuss all the things you can do with text components here For one more peek at their capabilities see the sample program SimpleRTFEdit java a very minimal editor for files that contain styled text of type text rtf 13 4 5 Custom Components Java s standard component classes are usually all you need to construct a user interface At some point however you might need a component that Java doesn t provide In that case you can write your own component class building on one of the components that Java does provide We ve already done this actually every time we ve written a subclass of the JPanel class to use as a drawing surface A JPanel is a blank slate By defining a subclass you can make it show any picture you like and you can program it to respond in any way to mouse and keyboard events Sometimes if you are lucky you don t need such freedom and you can build on one of Java s more sophisticated component classes For example suppose I have a need for a stopwatch component When the user clicks on the stopwatch I want it to start timing When the user clicks again I want it to display the elapsed time since the first click The

    Original URL path: http://math.hws.edu/javanotes/c13/s4.html (2016-02-07)
    Open archived version from archive

  • Javanotes 7.0, Section 13.5 -- Finishing Touches
    to the image the class uses a two dimensional array to store the iteration count for each pixel in the image If the range of xy values changes or if the size of the window changes all the counts must be recomputed Since the computation can take quite a while it would not be acceptable to block the user interface while the computation is being performed The solution is to do the computation in separate worker threads as discussed in Chapter 12 The program uses one worker thread for each available processor When the computation begins the image is filled with gray Every so often about twice a second the data that has been computed by the computation threads is gathered and applied to the off screen canvas and the part of the canvas that has been modified is copied to the screen A Timer is used to control this process each time the timer fires the image is updated with any new data that has been computed by the threads The user can continue to use the menus and even the mouse while the image is being computed The file MandelbrotPanel java defines the main panel of the Mandelbrot Viewer window MandelbrotPanel is another subclass of JPanel A MandelbrotPanel is mostly filled with a MandelbrotDisplay It also adds a JLabel beneath the display The JLabel is used as a status bar that shows some information that might be interesting to the user The MandelbrotPanel also defines the program s mouse listener In addition to handling zooming the mouse listener puts the x and y coordinates of the current mouse location in the status bar as the user moves or drags the mouse Also when the mouse exits the drawing area the text in the status bar is set to read Idle This is the first time that we have seen an actual use for mouseMoved and mouseExited events See Subsection 6 3 2 and Subsection 6 3 4 The menu bar for the program is defined in Menus java Commands in the File and Control menu are defined as Actions See Subsection 13 3 1 Note that among the actions are file manipulation commands that use techniques from Subsection 11 2 3 Subsection 11 5 2 and Subsection 13 1 5 The MaxIterations Palette and PaletteLength menus each contain a group of JRadioButtonMenuItems See Subsection 13 3 3 I have tried several approaches for handling such groups and none of them have satisfied me completely In this program I have defined a nested class inside Menus to represent each group For example the PaletteManager class contains the menu items in the Palette menu as instance variables It registers an action listener with each item and it defines a few utility routines for operating on the menu The classes for the three menus are very similar and should probably have been defined as subclasses of some more general class There is an Examples menu that contains settings for several sample views of pieces of the Mandelbrot set The MandelbrotPanel that is being used in the program is a parameter to the Menus constructor Many of the menu commands operate on this panel or on the MandelbrotDisplay that it contains In order to carry out these commands the Menus object needs a reference to the MandelbrotPanel As for the MandelbrotDisplay the panel has a method getDisplay that returns a reference to the display that it contains So as long as the menu bar has a reference to the panel it can obtain a reference to the display In previous examples everything was written as one large class file so all the objects were directly available to all the code When a program is made up of multiple interacting files getting access to the necessary objects can be more of a problem MandelbrotPanel MandelbrotDisplay and Menus are the main classes that make up the Mandelbrot Viewer program MandelbrotFrame java defines a simple subclass of JFrame that shows a MandelbrotPanel and its menu bar And Main java contains the main routine that actually runs the program There are a few other classes that I will discuss below This brief discussion of the design of the Mandelbrot Viewer has shown that it uses a wide variety of techniques that were covered earlier in this book In the rest of this section we ll look at a few new features of Java that were used in the program 13 5 3 Internationalization Internationalization refers to writing a program that is easy to adapt for running in different parts of the world Internationalization is often referred to as I18n where 18 is the number of letters between the I and the final n in Internationalization The process of adapting the program to a particular location is called localization and the locations are called locales Locales differ in many ways including the type of currency used and the format used for numbers and dates but the most obvious difference is language Here I will discuss how to write a program so that it can be easily translated into other languages The key idea is that strings that will be presented to the user should not be coded into the program source code If they were then a translator would have to search through the entire source code replacing every string with its translation Then the program would have to be recompiled In a properly internationalized program all the strings are stored together in one or more files that are separate from the source code where they can easily be found and translated And since the source code doesn t have to be modified to do the translation no recompilation is necessary To implement this idea the strings are stored in one or more properties files A properties file is just a list of key value pairs For translation purposes the values are strings that will be presented to the user these are the strings that have to be translated The keys are also strings but they don t have to be translated because they will never be presented to the user Since they won t have to be modified the key strings can be used in the program source code Each key uniquely identifies one of the value strings The program can use the key string to look up the corresponding value string from the properties file The program only needs to know the key string the user will only see the value string When the properties file is translated the user of the program will see different value strings The format of a properties file is very simple The key value pairs take the form key string value string There are no spaces in the key string or before the equals sign Periods are often used to divide words in the key string The value string can contain spaces or any other characters If the line ends with a backslash the value string is continued on the next line in this case spaces at the beginning of that line are ignored One unfortunate detail is that a properties file can contain only plain ASCII characters The ASCII character set only supports the English alphabet Nevertheless a value string can include arbitrary UNICODE characters Non ASCII characters just have to be specially encoded The JDK comes with a program native2ascii that can convert files that use non ASCII characters into a form that is suitable for use as a properties file Suppose that the program wants to present a string to the user as the name of a menu command for example The properties file would contain a key value pair such as menu saveimage Save PNG Image where Save PNG Image is the string that will appear in the menu The program would use the key string menu saveimage to look up the corresponding value string and would then use the value string as the text of the menu item In Java the look up process is supported by the ResourceBundle class which knows how to retrieve and use properties files Sometimes a string that is presented to the user contains substrings that are not known until the time when the program is running A typical example is the name of a file Suppose for example that the program wants to tell the user Sorry the file filename cannot be loaded where filename is the name of a file that was selected by the user at run time To handle cases like this value strings in properties files can include placeholders that will be replaced by strings to be determined by the program at run time The placeholders take the form 0 1 2 For the file error example the properties file might contain error cantLoad Sorry the file 0 cannot be loaded The program would fetch the value string for the key error cantLoad It would then substitute the actual file name for the placeholder 0 Note that when the string is translated the word order might be completely different By using a placeholder for the file name you can be sure that the file name will be put in the correct grammatical position for the language that is being used Placeholder substitution is not handled by the ResourceBundle class but Java has another class MessageFormat that makes such substitutions easy For the Mandelbrot Viewer program the properties file is strings properties Any properties file should have a name that ends in properties Any string that you see when you run the program comes from this file For handling value string lookup I wrote I18n java The I18n class has a static method public static tr String key Object args that handles the whole process Here key is the key string that will be looked up in strings properties Additional parameters if any will be substituted for placeholders in the value string Recall that the formal parameter declaration Object means that there can be any number of actual parameters after key see Subsection 7 1 2 Typical uses would include String saveImageCommandText I18n tr menu saveimage String errMess I18n tr error cantLoad selectedFile getName You will see function calls like this throughout the Mandelbrot Viewer source code The I18n class is written in a general way so that it can be used in any program As long as you provide a properties file as a resource the only things you need to do are change the resource file name in I18n java and put the class in your own package It is actually possible to provide several alternative properties files in the same program For example you might include French and Japanese versions of the properties file along with an English version If the English properties file is named strings properties then the names for the French and Japanese versions should be strings fr properties and strings ja properties Every language has a two letter code such as fr and ja that is used in constructing properties file names for that language The program asks for the properties file using the simple name strings If the program is being run on a Java system in which the preferred language is French the program will try to load strings fr properties if that fails it will look for strings properties This means that the program will use the French properties files in a French locale it will use the Japanese properties file in a Japanese locale and in any other locale it will use the default properties file 13 5 4 Events Events Events We have worked extensively with mouse events key events and action events but these are only a few of the event types that are used in Java The Mandelbrot Viewer program makes use of several other types of events It also serves as an example of the benefits of event oriented programming Let s start from the following fact The MandelbrotDisplay class knows nothing about any of the other classes that make up the program with the single exception of one call to the internationalization method I18n tr Yet other classes are aware of things that are going on in the MandelbrotDisplay class For example when the size of the display is changed the new size is reported in the status bar that is part of the MandelbrotPanel class In the Menus class certain menus are disabled when the display begins the computation of an image and are re enabled when the computation completes The display doesn t call methods in the MandelbrotPanel or Menus classes so how do these classes get their information about what is going on in the display The answer of course is events The MandelbrotDisplay object emits events of various types when various things happen The MandelbrotPanel and Menus objects set up listeners that hear those events and respond to them The point is that because events are used for communication the MandelbrotDisplay class is not strongly coupled to the other classes In fact it can be used in other programs without any modification and without access to the other classes The alternative to using events would be to have the display object call methods such as displaySizeChanged or computationStarted in the MandelbrotPanel and MandelbrotFrame objects to tell them what is going on in the display This would be strong coupling Any programmer who wanted to use MandelbrotDisplay would also have to use the other two classes or would have to modify the display class so that it no longer refers to the other classes Of course not everything can be done with events and not all strong coupling is bad The MandelbrotPanel class refers directly to the MandelbrotDisplay class and cannot be used without it but since the whole purpose of a MandelbrotPanel is to hold a MandelbrotDisplay the coupling is not a problem The Mandelbrot Viewer program responds to mouse events on the display These events are generated by the display object but the display class itself doesn t care about mouse events and doesn t do anything in response to them Mouse events are handled by a listener in the MandelbrotPanel which responds to them by zooming the display and by showing mouse coordinates in the status bar The status bar also shows the new size of the display whenever that size is changed To handle this events of type ComponentEvent are used When the size of a component is changed a ComponentEvent is generated In the Mandelbrot Viewer program a ComponentListener in the MandelbrotPanel class listens for size change events in the display When one occurs the listener responds by showing the new size in the status bar the display knows nothing about the status bar that shows the display s size Component events are also used internally in the MandelbrotDisplay class in an interesting way When the user dynamically changes the size of the display its size can change several times each second Normally a change of display size would trigger the creation of a new off screen canvas and the start of a new asynchronous computation of the image However doing this is a big deal not something I want to do several times in a second If you try resizing the program s window you ll notice that the image doesn t change size dynamically as the window size changes The same image and off screen canvas are used as long as the size is changing Only about one third of a second after the size has stopped changing will a new resized image be produced Here is how this works The display sets up a ComponentListener to listen for resize events on itself When a resize occurs the listener starts a Timer that has a delay of 1 3 second See Subsection 6 4 1 While this timer is running the paintComponent method does not resize the image instead it reuses the image that already exists If the timer fires 1 3 second later the image will be resized at that time However if another resize event occurs while the first timer is running then the first timer will be stopped before it has a chance to fire and a new timer will be started with a delay of 1 3 second The result is that the image does not get resized until 1 3 second after the size of the window stops changing The Mandelbrot Viewer program also uses events of type WindowEvent which are generated by a window when it opens or closes among other things Window events are used by Main java to trigger an action that has to be taken when the program is ending this will be discussed below Perhaps the most interesting use of events in the Mandelbrot Viewer program is to enable and disable menu commands based on the status of the display For this events of type PropertyChangeEvent are used This event class is part of a bean framework that Java uses for some advanced work with objects and class PropertyChangeEvent and related classes are defined in the package java beans The idea is that bean objects are defined by their properties which are just aspects of the state of the bean When a bean property changes the bean can emit a PropertyChangeEvent to notify other objects of the change Properties for which property change events are emitted are known technically as bound properties A bound property has a name that identifies that particular property among all the properties of the bean When a property change event is generated the event object includes the name of the property that has changed the previous value of the property and the new value of the property The MandelbrotDisplay class has a bound property whose name is given by the constant MandelbrotDisplay STATUS PROPERTY A display emits a property change event when its status changes The possible values of the status property are given

    Original URL path: http://math.hws.edu/javanotes/c13/s5.html (2016-02-07)
    Open archived version from archive

  • Javanotes 7.0, Section 11.1 -- Streams, Readers, and Writers
    return value must be type cast to type char to obtain the character that was read In practice you will ordinarily use higher level I O operations provided by sub classes of Reader and Writer as discussed below 11 1 2 PrintWriter One of the neat things about Java s I O package is that it lets you add capabilities to a stream by wrapping it in another stream object that provides those capabilities The wrapper object is also a stream so you can read from or write to it but you can do so using fancier operations than those available for basic streams For example PrintWriter is a subclass of Writer that provides convenient methods for outputting human readable character representations of all of Java s basic data types If you have an object belonging to the Writer class or any of its subclasses and you would like to use PrintWriter methods to output data to that Writer all you have to do is wrap the Writer in a PrintWriter object You do this by constructing a new PrintWriter object using the Writer as input to the constructor For example if charSink is of type Writer then you could say PrintWriter printableCharSink new PrintWriter charSink In fact the parameter to the constructor can also be an OutputStream or a File and the constructor will build a PrintWriter that can write to that output destination Files are covered in the next section When you output data to the PrintWriter printableCharSink using the high level output methods in PrintWriter that data will go to exactly the same place as data written directly to charSink You ve just provided a better interface to the same output destination For example this allows you to use PrintWriter methods to send data to a file or over a network connection For the record if out is a variable of type PrintWriter then the following methods are defined out print x prints the value of x represented in the form of a string of characters to the output stream x can be an expression of any type including both primitive types and object types An object is converted to string form using its toString method A null value is represented by the string null out println outputs an end of line to the output stream out println x outputs the value of x followed by an end of line this is equivalent to out print x followed by out println out printf formatString x1 x2 does formatted output of x1 x2 to the output stream The first parameter is a string that specifies the format of the output There can be any number of additional parameters of any type but the types of the parameters must match the formatting directives in the format string Formatted output for the standard output stream System out was introduced in Subsection 2 4 1 and out printf has the same functionality out flush ensures that characters that have been written with the above methods are actually sent to the output destination In some cases notably when writing to a file or to the network it might be necessary to call this method to force the output to actually appear at the destination Note that none of these methods will ever throw an IOException Instead the PrintWriter class includes the method public boolean checkError which will return true if any error has been encountered while writing to the stream The PrintWriter class catches any IOExceptions internally and sets the value of an internal error flag if one occurs The checkError method can be used to check the error flag This allows you to use PrintWriter methods without worrying about catching exceptions On the other hand to write a fully robust program you should call checkError to test for possible errors whenever you use a PrintWriter 11 1 3 Data Streams When you use a PrintWriter to output data to a stream the data is converted into the sequence of characters that represents the data in human readable form Suppose you want to output the data in byte oriented machine formatted form The java io package includes a byte stream class DataOutputStream that can be used for writing data values to streams in internal binary number format DataOutputStream bears the same relationship to OutputStream that PrintWriter bears to Writer That is whereas OutputStream only has methods for outputting bytes DataOutputStream has methods writeDouble double x for outputting values of type double writeInt int x for outputting values of type int and so on Furthermore you can wrap any OutputStream in a DataOutputStream so that you can use the higher level output methods on it For example if byteSink is of type OutputStream you could say DataOutputStream dataSink new DataOutputStream byteSink to wrap byteSink in a DataOutputStream For input of machine readable data such as that created by writing to a DataOutputStream java io provides the class DataInputStream You can wrap any InputStream in a DataInputStream object to provide it with the ability to read data of various types from the byte stream The methods in the DataInputStream for reading binary data are called readDouble readInt and so on Data written by a DataOutputStream is guaranteed to be in a format that can be read by a DataInputStream This is true even if the data stream is created on one type of computer and read on another type of computer The cross platform compatibility of binary data is a major aspect of Java s platform independence In some circumstances you might need to read character data from an InputStream or write character data to an OutputStream This is not a problem since characters like all data are ultimately represented as binary numbers However for character data it is convenient to use Reader and Writer instead of InputStream and OutputStream To make this possible you can wrap a byte stream in a character stream If byteSource is a variable of type InputStream and byteSink is of type OutputStream then the statements Reader charSource new InputStreamReader byteSource Writer charSink new OutputStreamWriter byteSink create character streams that can be used to read character data from and write character data to the byte streams In particular the standard input stream System in which is of type InputStream for historical reasons can be wrapped in a Reader to make it easier to read character data from standard input Reader charIn new InputStreamReader System in As another application the input and output streams that are associated with a network connection are byte streams rather than character streams but the byte streams can be wrapped in character streams to make it easy to send and receive character data over the network We will encounter network I O in Section 11 4 There are various ways for characters to be encoded as binary data A particular encoding is known as a charset or character set Charsets have standardized names such as UTF 16 UTF 8 and ISO 8859 1 In UTF 16 characters are encoded as 16 bit UNICODE values this is the character set that is used internally by Java UTF 8 is a way of encoding UNICODE characters using 8 bits for common ASCII characters and longer codes for other characters ISO 8859 1 also known as Latin 1 is an 8 bit encoding that includes ASCII characters as well as certain accented characters that are used in several European languages Readers and Writers use the default charset for the computer on which they are running unless you specify a different one This can be done for example in a constructor such as Writer charSink new OutputStreamWriter byteSink ISO 8859 1 Certainly the existence of a variety of charset encodings has made text processing more complicated unfortunate for us English speakers but essential for people who use non Western character sets Ordinarily you don t have to worry about this but it s a good idea to be aware that different charsets exist in case you run into textual data encoded in a non default way 11 1 4 Reading Text Much I O is done in the form of human readable characters In view of this it is surprising that Java does not provide a standard character input class that can read character data in a manner that is reasonably symmetrical with the character output capabilities of PrintWriter The Scanner class introduced briefly in Subsection 2 4 6 and covered in more detail below comes pretty close There is one basic case that is easily handled by the standard class BufferedReader which has a method public String readLine throws IOException that reads one line of text from its input source If the end of the stream has been reached the return value is null When a line of text is read the end of line marker is read from the input stream but it is not part of the string that is returned Different input streams use different characters as end of line markers but the readLine method can deal with all the common cases Traditionally Unix computers including Linux and Mac OS X use a line feed character n to mark an end of line classic Macintosh used a carriage return character r and Windows uses the two character sequence r n In general modern computers can deal correctly with all of these possibilities Line by line processing is very common Any Reader can be wrapped in a BufferedReader to make it easy to read full lines of text If reader is of type Reader then a BufferedReader wrapper can be created for reader with BufferedReader in new BufferedReader reader This can be combined with the InputStreamReader class that was mentioned above to read lines of text from an InputStream For example we can apply this to System in BufferedReader in BufferedReader for reading from standard input in new BufferedReader new InputStreamReader System in try String line in readLine while line null processOneLineOfInput line line in readLine catch IOException e This code segment reads and processes lines from standard input until an end of stream is encountered An end of stream is possible even for interactive input For example on at least some computers typing a Control D generates an end of stream on the standard input stream The try catch statement is necessary because the readLine method can throw an exception of type IOException which requires mandatory exception handling an alternative to try catch would be to declare that the method that contains the code throws IOException Also remember that BufferedReader InputStreamReader and IOException must be imported from the package java io Note that the main purpose of BufferedReader is not simply to make it easier to read lines of text Some I O devices work most efficiently if data is read or written in large chunks instead of as individual bytes or characters A BuferedReader reads a chunk of data and stores it in internal memory The internal memory is known as a buffer When you read from the BufferedReader it will take data from the buffer if possible and it will only go back to its input source for more data when the buffer is emptied There is also a BufferedWriter class and there are buffered stream classes for byte streams as well Previously in this book we have used the non standard class TextIO for input both from users and from files The advantage of TextIO is that it makes it fairly easy to read data values of any of the primitive types Disadvantages include the fact that TextIO can only read from one input source at a time and that it does not follow the same pattern as Java s built in input output classes I have written a class named TextReader to fix some of these disadvantages while providing input capabilities similar to those of TextIO Like TextIO TextReader is a non standard class so you have to be careful to make it available to any program that uses it The source code for the class can be found in the file TextReader java Just as for many of Java s stream classes an object of type TextReader can be used as a wrapper for an existing input stream which becomes the source of the characters that will be read by the TextReader Unlike the standard classes however a TextReader is not itself a stream and cannot be wrapped inside other stream classes The constructors public TextReader Reader characterSource and public TextReader InputStream byteSource create objects that can be used to read character data from the given Reader or InputStream using the convenient input methods of the TextReader class In TextIO the input methods were static members of the class The input methods in the TextReader class are instance methods The instance methods in a TextReader object read from the data source that was specified in the object s constructor This makes it possible for several TextReader objects to exist at the same time reading from different streams those objects can then be used to read data from several files or other input sources at the same time A TextReader object has essentially the same set of input methods as the TextIO class One big difference is how errors are handled When a TextReader encounters an error in the input it throws an exception of type IOException This follows the standard pattern that is used by Java s standard input streams IOExceptions require mandatory exception handling so TextReader methods are generally called inside try catch statements If an IOException is thrown by the input stream that is wrapped inside a TextReader that IOException is simply passed along However other types of errors can also occur One such possible error is an attempt to read data from the input stream when there is no more data left in the stream A TextReader throws an exception of type TextReader EndOfStreamException when this happens The exception class in this case is a nested class in the TextReader class it is a subclass of IOException so a try catch statement that handles IOExceptions will also handle end of stream exceptions However having a class to represent end of stream errors makes it possible to detect such errors and provide special handling for them Another type of error occurs when a TextReader tries to read a data value of a certain type and the next item in the input stream is not of the correct type In this case the TextReader throws an exception of type TextReader BadDataException which is another subclass of IOException For reference here is a list of some of the more useful instance methods in the TextReader class All of these methods can throw exceptions of type IOException public char peek looks ahead at the next character in the input stream and returns that character The character is not removed from the stream If the next character is an end of line the return value is n It is legal to call this method even if there is no more data left in the stream in that case the return value is the constant TextReader EOF EOF stands for End Of File a term that is more commonly used than End Of Stream even though not all streams are files public boolean eoln and public boolean eof convenience methods for testing whether the next thing in the file is an end of line or an end of file Note that these methods do not skip whitespace If eof is false you know that there is still at least one character to be read but there might not be any more non blank characters in the stream public void skipBlanks and public void skipWhiteSpace skip past whitespace characters in the input stream skipWhiteSpace skips all whitespace characters including end of line while skipBlanks only skips spaces and tabs public String getln reads characters up to the next end of line or end of stream and returns those characters in a string The end of line marker is read but is not part of the returned string This will throw an exception if there are no more characters in the stream public char getAnyChar reads and returns the next character from the stream The character can be a whitespace character such as a blank or end of line If this method is called after all the characters in the stream have been read an exception is thrown public int getInt public double getDouble public char getChar etc skip any whitespace characters in the stream including end of lines then read and return a value of the specified type Extra characters on the line are not discarded and are still available to be read by subsequent input methods There is a method for each primitive type An exception occurs if it s not possible to read a data value of the requested type public int getlnInt public double getlnDouble public char getlnChar etc skip any whitespace characters in the stream including end of lines then read a value of the specified type which will be the return value of the method Any remaining characters on the line are then discarded including the end of line marker There is a method for each primitive type An exception occurs if it s not possible to read a data value of the requested type public void close Closes the input stream This should be done when finished reading from the stream TextReader implements the AutoCloseable interface and so can be used as a resource in a try catch statement as discussed at the end of Subsection 8 3 2 11 1 5 The Scanner Class Since its introduction Java has been notable for its lack of built in support for basic input and for its reliance on fairly advanced techniques for the support that it does offer This is my opinion at least The Scanner class was introduced

    Original URL path: http://math.hws.edu/javanotes/c11/s1.html (2016-02-07)
    Open archived version from archive

  • Javanotes 7.0 Table of Contents
    3 6 The switch Statement Section 3 7 Introduction to Exceptions and try catch Section 3 8 Introduction to Arrays Section 3 9 Introduction to GUI Programming Programming Exercises Quiz Chapter 4 Programming in the Large I Subroutines Section 4 1 Black Boxes Section 4 2 Static Subroutines and Static Variables Section 4 3 Parameters Section 4 4 Return Values Section 4 5 APIs Packages and Javadoc Section 4 6 More on Program Design Section 4 7 The Truth About Declarations Programming Exercises Quiz Chapter 5 Programming in the Large II Objects and Classes Section 5 1 Objects Instance Methods and Instance Variables Section 5 2 Constructors and Object Initialization Section 5 3 Programming with Objects Section 5 4 Programming Example Card Hand Deck Section 5 5 Inheritance Polymorphism and Abstract Classes Section 5 6 this and super Section 5 7 Interfaces Section 5 8 Nested Classes Programming Exercises Quiz Chapter 6 Introduction to GUI Programming Section 6 1 The Basic GUI Application Section 6 2 Graphics and Painting Section 6 3 Mouse Events Section 6 4 Timers KeyEvents and State Machines Section 6 5 Basic Components Section 6 6 Basic Layout Section 6 7 Menus and Dialogs Programming Exercises Quiz Chapter 7 Arrays and ArrayLists Section 7 1 Array Details Section 7 2 Array Processing Section 7 3 ArrayList Section 7 4 Searching and Sorting Section 7 5 Two dimensional Arrays Programming Exercises Quiz Chapter 8 Correctness Robustness Efficiency Section 8 1 Introduction to Correctness and Robustness Section 8 2 Writing Correct Programs Section 8 3 Exceptions and try catch Section 8 4 Assertions and Annotations Section 8 5 Analysis of Algorithms Programming Exercises Quiz Chapter 9 Linked Data Structures and Recursion Section 9 1 Recursion Section 9 2 Linked Data Structures Section 9 3 Stacks Queues and ADTs

    Original URL path: http://math.hws.edu/javanotes/contents.html (2016-02-07)
    Open archived version from archive