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".
  • Javanotes 7.0, Section 6.6 -- Basic Layout
    R C where R is the number of rows and C is the number of columns If you want to leave horizontal gaps of H pixels between columns and vertical gaps of V pixels between rows use new GridLayout R C H V instead When you use a GridLayout it s probably good form to add just enough components to fill the grid However this is not required In fact as long as you specify a non zero value for the number of rows then the number of columns is essentially ignored The system will use just as many columns as are necessary to hold all the components that you add to the container If you want to depend on this behavior you should probably specify zero as the number of columns You can also specify the number of rows as zero In that case you must give a non zero number of columns The system will use the specified number of columns with just as many rows as necessary to hold the components that are added to the container Horizontal grids with a single row and vertical grids with a single column are very common For example suppose that button1 button2 and button3 are buttons and that you d like to display them in a horizontal row in a panel If you use a horizontal grid for the panel then the buttons will completely fill that panel and will all be the same size The panel can be created as follows JPanel buttonBar new JPanel buttonBar setLayout new GridLayout 1 3 Note The 3 here is pretty much ignored and you could also say new GridLayout 1 0 To leave gaps between the buttons you could use new GridLayout 1 0 5 5 buttonBar add button1 buttonBar add button2 buttonBar add button3 You might find this button bar to be more attractive than the one that uses the default FlowLayout layout manager 6 6 2 Borders We have seen how to leave gaps between the components in a container but what if you would like to leave a border around the outside of the container This problem is not handled by layout managers Instead borders in Swing are represented by objects A Border object can be added to any JComponent not just to containers Borders can be more than just empty space The class javax swing BorderFactory contains a large number of static methods for creating border objects For example the function BorderFactory createLineBorder Color BLACK returns an object that represents a one pixel wide black line around the outside of a component If comp is a JComponent a border can be added to comp using its setBorder method For example comp setBorder BorderFactory createLineBorder Color BLACK Once a border has been set for a JComponent the border is drawn automatically without any further effort on the part of the programmer The border is drawn along the edges of the component just inside its boundary The layout manager of a JPanel or other container will take the space occupied by the border into account The components that are added to the container will be displayed in the area inside the border I don t recommend using a border on a JPanel that is being used as a drawing surface However if you do this you should take the border into account If you draw in the area occupied by the border that part of your drawing will be covered by the border Here are some of the static methods that can be used to create borders BorderFactory createEmptyBorder top left bottom right leaves an empty border around the edges of a component Nothing is drawn in this space so the background color of the component will appear in the area occupied by the border The parameters are integers that give the width of the border along the top left bottom and right edges of the component This is actually very useful when used on a JPanel that contains other components It puts some space between the components and the edge of the panel It can also be useful on a JLabel which otherwise would not have any space between the text and the edge of the label BorderFactory createLineBorder color thickness draws a line around all four edges of a component The first parameter is of type Color and specifies the color of the line The second parameter is an integer that specifies the thickness of the border in pixels If the second parameter is omitted a line of thickness 1 is drawn BorderFactory createMatteBorder top left bottom right color is similar to createLineBorder except that you can specify individual thicknesses for the top left bottom and right edges of the component BorderFactory createEtchedBorder creates a border that looks like a groove etched around the boundary of the component The effect is achieved using lighter and darker shades of the component s background color and it does not work well with every background color BorderFactory createLoweredBevelBorder gives a component a three dimensional effect that makes it look like it is lowered into the computer screen As with an EtchedBorder this only works well for certain background colors BorderFactory createRaisedBevelBorder similar to a LoweredBevelBorder but the component looks like it is raised above the computer screen BorderFactory createTitledBorder title creates a border with a title The title is a String which is displayed in the upper left corner of the border There are many other methods in the BorderFactory class most of them providing variations of the basic border styles given here The following illustration shows six components with six different border styles The text in each component is the command that created the border for that component The source code for the program that produced this picture can be found in BorderDemo java 6 6 3 SliderAndButtonDemo Now that we have looked at components and layouts it s time to put them together into some complete programs We start with a simple demo that uses a JLabel three JButtons and a couple of JSliders all laid out in a GridLayout The sliders in this program control the foreground and background color of the label and the buttons control its font style Writing this program is a matter of creating the components laying them out and programming listeners to respond to events from the sliders and buttons My program is defined as a subclass of JPanel that implements ChangeListener and ActionListener so that the panel itself can act as the listener for change events from the sliders and action events from the buttons In the constructor the six components are created and configured a GridLayout is installed as the layout manager for the panel and the components are added to the panel Create the display label with properties to match the values of the sliders and the setting of the combo box displayLabel new JLabel Hello World JLabel CENTER displayLabel setOpaque true displayLabel setBackground new Color 100 100 100 displayLabel setForeground Color RED displayLabel setFont new Font Serif Font BOLD 30 displayLabel setBorder BorderFactory createEmptyBorder 0 8 0 8 Create the sliders and set up the panel to listen for ChangeEvents that are generated by the sliders bgColorSlider new JSlider 0 255 100 bgColorSlider addChangeListener this fgColorSlider new JSlider 0 100 0 fgColorSlider addChangeListener this Create four buttons to control the font style and set up the panel to listen for ActionEvents from the buttons JButton plainButton new JButton Plain Font plainButton addActionListener this JButton italicButton new JButton Italic Font italicButton addActionListener this JButton boldButton new JButton Bold Font boldButton addActionListener this Set the layout for the panel and add the four components Use a GridLayout with 3 rows and 2 columns and with 5 pixels between components setLayout new GridLayout 3 2 5 5 add displayLabel add plainButton add bgColorSlider add italicButton add fgColorSlider add boldButton The class also defines the methods required by the ActionListener and ChangeListener interfaces The actionPerformed method is called when the user clicks one of the buttons This method changes the font in the JLabel where the font depends on which button was clicked To determine which button was clicked the method uses evt getActionCommand which returns the text from the button public void actionPerformed ActionEvent evt String cmd evt getActionCommand if cmd equals Plain Font displayLabel setFont new Font Serif Font PLAIN 30 else if cmd equals Italic Font displayLabel setFont new Font Serif Font ITALIC 30 else if cmd equals Bold Font displayLabel setFont new Font Serif Font BOLD 30 And the stateChanged method which is called when the user manipulates one of the sliders uses the value on the slider to compute a new foreground or background color for the label The method checks evt getSource to determine which slider was changed public void stateChanged ChangeEvent evt if evt getSource bgColorSlider int bgVal bgColorSlider getValue displayLabel setBackground new Color bgVal bgVal bgVal NOTE The background color is a shade of gray determined by the setting on the slider else float hue fgColorSlider getValue 100 0f displayLabel setForeground Color getHSBColor hue 1 0f 1 0f Note The foreground color ranges through all the colors of the spectrum Note that the slider variables are global variables in the program because they are referenced in the stateChanged method as well as in the constructor On the other hand the button variables are local variables in the constructor because that is the only place where they are used The complete source code for this example is in the file SliderAndButtonDemo java 6 6 4 A Simple Calculator As our next example we look briefly at an example that uses nested subpanels to build a more complex user interface The program has two JTextFields where the user can enter two numbers four JButtons that the user can click to add subtract multiply or divide the two numbers and a JLabel that displays the result of the operation Here is a picture from the program This example uses a panel with a GridLayout that has four rows and one column In this case the layout is created with the statement setLayout new GridLayout 4 1 3 3 which allows a 3 pixel gap between the rows where the gray background color of the panel is visible The first row of the grid layout actually contains two components a JLabel displaying the text x and a JTextField A grid layout can only have one component in each position In this case the component in the first row is a JPanel a subpanel that is nested inside the main panel This subpanel in turn contains the label and text field This can be programmed as follows xInput new JTextField 0 10 Create a text field sized to hold 10 chars JPanel xPanel new JPanel Create the subpanel xPanel add new JLabel x Add a label to the subpanel xPanel add xInput Add the text field to the subpanel add xPanel Add the subpanel to the main panel The subpanel uses the default FlowLayout layout manager so the label and text field are simply placed next to each other in the subpanel at their preferred size and are centered in the subpanel Similarly the third row of the grid layout is a subpanel that contains four buttons In this case the subpanel uses a GridLayout with one row and four columns so that the buttons are all the same size and completely fill the subpanel One other point of interest in this example is the actionPerformed method that responds when the user clicks one of the buttons This method must retrieve the user s numbers from the text field perform the appropriate arithmetic operation on them depending on which button was clicked and set the text of the JLabel named answer to represent the result However the contents of the text fields can only be retrieved as strings and these strings must be converted into numbers If the conversion fails the label is set to display an error message public void actionPerformed ActionEvent evt double x y The numbers from the input boxes try String xStr xInput getText x Double parseDouble xStr catch NumberFormatException e The string xStr is not a legal number answer setText Illegal data for x xInput requestFocusInWindow return try String yStr yInput getText y Double parseDouble yStr catch NumberFormatException e The string yStr is not a legal number answer setText Illegal data for y yInput requestFocusInWindow return Perform the operation based on the action command from the button The action command is the text displayed on the button Note that division by zero produces an error message String op evt getActionCommand if op equals answer setText x y x y else if op equals answer setText x y x y else if op equals answer setText x y x y else if op equals if y 0 answer setText Can t divide by zero else answer setText x y x y end actionPerformed The complete source code for this example can be found in SimpleCalc java 6 6 5 Using a null Layout As mentioned above it is possible to do without a layout manager altogether For our next example we ll look at a panel that does not use a layout manager If you set the layout manager of a container to be null by calling container setLayout null then you assume complete responsibility for positioning and sizing the components in that container If comp is any component then the statement comp setBounds x y width height puts the top left corner of the component at the point x y measured in the coordinate system of the container that contains the component and it sets the width and height of the component to the specified values You should only set the bounds of a component if the container that contains it has a null layout manager In a container that has a non null layout manager the layout manager is responsible for setting the bounds and you should not interfere with its job Assuming that you have set the layout manager to null you can call the setBounds method any time you like You can even make a component that moves or changes size while the user is watching If you are writing a panel that has a known fixed size then you can set the bounds of each component in the panel s constructor Note that you must also add the components to the panel using the panel s add component instance method otherwise the component will not appear on the screen Our example contains four components two buttons a label and a panel that displays a checkerboard pattern This is just an example of using a null layout it doesn t do anything except that clicking the buttons changes the text of the label We will use this example in Section 7 5 as a starting point for a checkers game The panel in this program is defined by the class NullLayoutDemo which is created as a subclass of JPanel The four components are created and added to the panel in the constructor Then the setBounds method of each component is called to set the size and position of the component public NullLayoutDemo setLayout null I will do the layout myself setBackground new Color 0 120 0 A dark green background setBorder BorderFactory createEtchedBorder setPreferredSize new Dimension 350 240 Create the components and add them to the content pane If you don t add them to a container they won t appear even if you set their bounds board new Checkerboard Checkerboard is a subclass of JPanel defined below as a static nested class inside the main class add board newGameButton new JButton New Game newGameButton addActionListener this add newGameButton resignButton new JButton Resign resignButton addActionListener this add resignButton message new JLabel Click New Game to begin message setForeground new Color 100 255 100 Light green message setFont new Font Serif Font BOLD 14 add message Set the position and size of each component by calling its setBounds method board setBounds 20 20 164 164 newGameButton setBounds 210 60 120 30 resignButton setBounds 210 120 120 30 message setBounds 20 200 330 30 end constructor It s fairly easy in this case to get a reasonable layout It s much more difficult to do your own layout if you want to allow for changes of size In that case you have to respond to changes in the container s size by recomputing the sizes and positions of all the components that it contains If you want to respond to changes in a container s size you can register an appropriate listener with the container Any component generates an event of type ComponentEvent when its size changes and also when it is moved hidden or shown You can register a ComponentListener with the container and respond to resize events by recomputing the sizes and positions of all the components in the container Consult a Java reference for more information about ComponentEvents However my real advice is that if you want to allow for changes in the container s size try to find a layout manager to do the work for you The complete source code for this example is in NullLayoutDemo java 6 6 6 A Little Card Game For a final example let s look at something a little more interesting as a program The example is a simple card game in which you look at a playing card and try to predict whether the next card will be higher or lower in value Aces have the lowest value in this game You ve seen a text oriented version of the same game in Subsection 5 4 3 Section 5 4 also introduced Deck Hand and Card classes that are used by the program In this GUI version of the game you click on a button to make your prediction If you predict

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


  • Javanotes 7.0, Section 6.7 -- Menus and Dialogs
    JMenu method that can be used to add menus to the menu bar The name of the menu then appears in the menu bar For example the MosaicDraw program uses three menus controlMenu colorMenu and toolsMenu We could create a menu bar and add the menus to it with the statements JMenuBar menuBar new JMenuBar menuBar add controlMenu menuBar add colorMenu menuBar add toolsMenu The final step in using menus is to use the menu bar in a window such as a JFrame We have already seen that a frame has a content pane The menu bar is another component of the frame not contained inside the content pane The JFrame class has an instance method setMenuBar JMenuBar that can be used to set the menu bar There can only be one so this is a set method rather than an add method In the MosaicDraw program the menu bar is created by a MosaicDrawController object and can be obtained by calling that object s getMenuBar method The main routine in MosaicDraw java gets the menu bar from the controller and adds it to the window Here is the basic code that is used in somewhat modified form to set up the interface MosaicDrawController controller new MosaicDrawController MosaicPanel content controller getMosaicPanel window setContentPane content Use panel from controller as content pane JMenuBar menuBar controller getMenuBar window setJMenuBar menuBar Use the menu bar from the controller Using menus always follows the same general pattern Create a menu bar Create menus and add them to the menu bar Create menu items and add them to the menus and set up listening to handle action events from the menu items Use the menu bar in a window by calling the window s setJMenuBar method There are other kinds of menu items defined by subclasses of JMenuItem that can be added to menus One of these is JCheckBoxMenuItem which represents menu items that can be in one of two states selected or not selected A JCheckBoxMenuItem has the same functionality and is used in the same way as a JCheckBox see Subsection 6 5 3 Three JCheckBoxMenuItems are used in the Control menu of the MosaicDraw program One is used to turn the random color variation of the squares on and off Another turns a symmetry feature on and off when symmetry is turned on the user s drawing is reflected horizontally and vertically to produce a symmetric pattern And the third checkbox menu item shows and hides the grouting in the mosaic the grouting is the gray lines that are drawn around each of the little squares in the mosaic The menu item that corresponds to the Use Randomness option in the Control menu could be set up with the statements JMenuItem useRandomnessToggle new JCheckBoxMenuItem Use Randomness useRandomnessToggle addActionListener listener Set up a listener useRandomnessToggle setSelected true Randomness is initially turned on controlMenu add useRandomnessToggle Add the menu item to the menu In my program the Use Randomness JCheckBoxMenuItem corresponds to a boolean valued instance variable named useRandomness in the MosaicDrawController class This variable is part of the state of the controller object Its value is tested whenever the user draws one of the squares to decide whether or not to add a random variation to the color of the square When the user selects the Use Randomness command from the menu the state of the JCheckBoxMenuItem is reversed from selected to not selected or from not selected to selected The ActionListener for the menu item checks whether the menu item is selected or not and it changes the value of useRandomness to match Note that selecting the menu command does not have any immediate effect on the picture that is shown in the window It just changes the state of the program so that future drawing operations on the part of the user will have a different effect The Use Symmetry option in the Control menu works in much the same way The Show Grouting option is a little different Selecting the Show Grouting option does have an immediate effect The picture is redrawn with or without the grouting depending on the state of the menu item My program uses a single ActionListener to respond to all of the menu items in all the menus This is not a particularly good design but it is easy to implement for a small program like this one The actionPerformed method of the listener object uses the statement String command evt getActionCommand to get the action command of the source of the event this will be the text of the menu item The listener tests the value of command to determine which menu item was selected by the user If the menu item is a JCheckBoxMenuItem the listener must check the state of the menu item The menu item is the source of the event that is being processed The listener can get its hands on the menu item object by calling evt getSource Since the return value of getSource is of type Object the return value must be type cast to the correct type Here for example is the code that handles the Use Randomness command if command equals Use Randomness Set the value of useRandomness depending on the menu item s state JCheckBoxMenuItem toggle JCheckBoxMenuItem evt getSource useRandomness toggle isSelected The actionPerformed method uses a rather long if then else statement to check all the possible action commands It might be more natural and efficient use a switch statement with command as the selector and all the possible action commands as cases In addition to menu items a menu can contain lines that separate the menu items into groups In the MosaicDraw program the Control menu contains such a separator A JMenu has an instance method addSeparator that can be used to add a separator to the menu For example the separator in the Control menu was created with the statement controlMenu addSeparator A menu can also contain a submenu The name of the submenu appears as an item in the main menu When the user moves the mouse over the submenu name the submenu pops up There is no example of this in the MosaicDraw program It is very easy to do this in Java You can add one JMenu to another JMenu using a statement such as mainMenu add submenu and it becomes a submenu 6 7 2 Dialogs One of the commands in the Color menu of the MosaicDraw program is Custom Color When the user selects this command a new window appears where the user can select a color This window is an example of a dialog or dialog box A dialog is a type of window that is generally used for short single purpose interactions with the user For example a dialog box can be used to display a message to the user to ask the user a question to let the user select a file to be opened or to let the user select a color In Swing a dialog box is represented by an object belonging to the class JDialog or to a subclass The JDialog class is very similar to JFrame and is used in much the same way Like a frame a dialog box is a separate window Unlike a frame however a dialog is not completely independent Every dialog is associated with a frame or another dialog which is called its parent window The dialog box is dependent on its parent For example if the parent is closed the dialog box will also be closed It is possible to create a dialog box without specifying a parent but in that case an invisible frame is created by the system to serve as the parent Dialog boxes can be either modal or modeless When a modal dialog is created its parent frame is blocked That is the user will not be able to interact with the parent until the dialog box is closed Modeless dialog boxes do not block their parents in the same way so they seem a lot more like independent windows In practice modal dialog boxes are easier to use and are much more common than modeless dialogs All the examples we will look at are modal Aside from having a parent a JDialog can be created and used in the same way as a JFrame However I will not give any examples here of using JDialog directly Swing has many convenient methods for creating common types of dialog boxes For example the color choice dialog that appears when the user selects the Custom Color command in the MosaicDraw program belongs to the class JColorChooser which is a subclass of JDialog The JColorChooser class has a static method that makes color choice dialogs very easy to use Color JColorChooser showDialog Component parentComp String title Color initialColor When you call this method a dialog box appears that allows the user to select a color The first parameter specifies the parent of the dialog the parent window of the dialog will be the window if any that contains parentComp this parameter can be null and it can itself be a frame or dialog object The second parameter is a string that appears in the title bar of the dialog box And the third parameter initialColor specifies the color that is selected when the color choice dialog first appears The dialog has a sophisticated interface that allows the user to select a color When the user presses an OK button the dialog box closes and the selected color is returned as the value of the method The user can also click a Cancel button or close the dialog box in some other way in that case null is returned as the value of the method This is a modal dialog and showDialog does not return until the user dismisses the dialog box in some way By using this predefined color chooser dialog you can write one line of code that will let the user select an arbitrary color Swing also has a JFileChooser class that makes it almost as easy to show a dialog box that lets the user select a file to be opened or saved The JOptionPane class includes a variety of methods for making simple dialog boxes that are variations on three basic types a message dialog a confirm dialog and an input dialog The variations allow you to provide a title for the dialog box to specify the icon that appears in the dialog and to add other components to the dialog box I will only cover the most basic forms here A message dialog simply displays a message string to the user The user hopefully reads the message and dismisses the dialog by clicking the OK button A message dialog can be shown by calling the static method void JOptionPane showMessageDialog Component parentComp String message The message can be more than one line long Lines in the message should be separated by newline characters n New lines will not be inserted automatically even if the message is very long For example assuming that the special variable this refers to a Component JOptionPane showMessageDialog this This program is about to crash n Sorry about that An input dialog displays a question or request and lets the user type in a string as a response You can show an input dialog by calling String JOptionPane showInputDialog Component parentComp String question Again parentComp can be null and the question can include newline characters The dialog box will contain an input box an OK button and a Cancel button If the user clicks Cancel or closes the dialog box in some other way then the return value of the method is null If the user clicks OK then the return value is the string that was entered by the user Note that the return value can be an empty string which is not the same as a null value if the user clicks OK without typing anything in the input box If you want to use an input dialog to get a numerical value from the user you will have to convert the return value into a number see Subsection 3 7 2 As an example String name name JOptionPanel showInputDialog null Hi What s your name if name null JOptionPane showMessageDialog null Well I ll call you Grumpy else JOptionPane showMessageDialog null Pleased to meet you name Finally a confirm dialog presents a question and three response buttons Yes No and Cancel A confirm dialog can be shown by calling int JOptionPane showConfirmDialog Component parentComp String question The return value tells you the user s response It is one of the following constants JOptionPane YES OPTION the user clicked the Yes button JOptionPane NO OPTION the user clicked the No button JOptionPane CANCEL OPTION the user clicked the Cancel button JOptionPane CLOSE OPTION the dialog was closed in some other way By the way it is possible to omit the Cancel button from a confirm dialog by calling one of the other methods in the JOptionPane class Just call JOptionPane showConfirmDialog parent question title JOptionPane YES NO OPTION The final parameter is a constant which specifies that only a Yes button and a No button should be used The third parameter is a string that will be displayed as the title of the dialog box window A small demo program SimpleDialogDemo java is available to demonstrate JColorChooser and several JOptionPane dialogs 6 7 3 Fine Points of Frames In previous sections whenever I used a frame I created a JFrame object in a main routine and installed a panel as the content pane of that frame This works fine but a more object oriented approach is to define a subclass of JFrame and to set up the contents of the frame in the constructor of that class This is what I did in the case of the MosaicDraw program MosaicDraw is defined as a subclass of JFrame The definition of this class is very short but it illustrates several new features of frames that I want to discuss public class MosaicDraw extends JFrame public static void main String args JFrame window new MosaicDraw window setDefaultCloseOperation JFrame EXIT ON CLOSE window setVisible true public MosaicDraw super Mosaic Draw MosaicDrawController controller new MosaicDrawController setContentPane controller getMosaicPanel setJMenuBar controller getMenuBar pack Dimension screensize Toolkit getDefaultToolkit getScreenSize setLocation screensize width getWidth 2 screensize height getHeight 2 The constructor in this class begins with the statement super Mosaic Draw which calls the constructor in the superclass JFrame The parameter specifies a title that will appear in the title bar of the window The next three lines of the constructor set up the contents of the window a MosaicDrawController is created and the content pane and menu bar of the window are obtained from the controller The next line is something new If window is a variable of type JFrame or JDialog then the statement window pack will resize the window so that its size matches the preferred size of its contents In this case of course pack is equivalent to this pack that is it refers to the window that is being created by the constructor The pack method is usually the best way to set the size of a window Note that it will only work correctly if every component in the window has a correct preferred size This is only a problem in two cases when a panel is used as a drawing surface and when a panel is used as a container with a null layout manager In both these cases there is no way for the system to determine the correct preferred size automatically and you should set a preferred size by hand For example panel setPreferredSize new Dimension 400 250 The last two lines in the constructor position the window so that it is exactly centered on the screen The line Dimension screensize Toolkit getDefaultToolkit getScreenSize determines the size of the screen The size of the screen is screensize width pixels in the horizontal direction and screensize height pixels in the vertical direction The setLocation method of the frame sets the position of the upper left corner of the frame on the screen The expression screensize width getWidth is the amount of horizontal space left on the screen after subtracting the width of the window This is divided by 2 so that half of the empty space will be to the left of the window leaving the other half of the space to the right of the window Similarly half of the extra vertical space is above the window and half is below Note that the constructor has created the window and set its size and position but that at the end of the constructor the window is not yet visible on the screen More exactly the constructor has created the window object but the visual representation of that object on the screen has not yet been created To show the window on the screen it will be necessary to call its instance method window setVisible true In addition to the constructor the MosaicDraw class includes a main routine This makes it possible to run MosaicDraw as a stand alone application The main routine as a static method has nothing to do with the function of a MosaicDraw object and it could and perhaps should be in a separate class The main routine creates a MosaicDraw and makes it visible on the screen It also calls window setDefaultCloseOperation JFrame EXIT ON CLOSE which means that the program will end when the user closes the window Note that this is not done in the constructor because doing it there would make MosaicDraw less flexible It is possible for example to write a program that lets the user open multiple MosaicDraw windows In that case we don t want to shut down the whole program just because the user has closed one of the

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

  • Javanotes 7.0, Section 11.5 -- A Brief Introduction to XML
    2 Working With the DOM The sample XML file shown above was designed to store information about simple drawings made by the user The drawings are ones that could be made using the sample program SimplePaint2 java from Subsection 7 3 3 We ll look at another version of that program that can save the user s drawing using an XML format for the data file The new version is SimplePaintWithXML java The sample XML document shown earlier in this section was produced by this program I designed the format of that document to represent all the data needed to reconstruct a picture in SimplePaint The document encodes the background color of the picture and a list of curves Each curve element contains the data from one object of type CurveData It is easy enough to write data in a customized XML format although we have to be very careful to follow all the syntax rules Here is how I write the data for a SimplePaint picture to a PrintWriter out This produces an XML file with the same structure as the example shown above out println xml version 1 0 out println simplepaint version 1 0 Color bgColor getBackground out println background red bgColor getRed green bgColor getGreen blue bgColor getBlue for CurveData c curves out println curve out println color red c color getRed green c color getGreen blue c color getBlue out println symmetric c symmetric symmetric for Point pt c points out println point x pt x y pt y out println curve out println simplepaint Reading the data back into the program is another matter To reconstruct the data structure represented by the XML Document it is necessary to parse the document and extract the data from it This could be difficult to do by hand Fortunately Java has a standard API for parsing and processing XML Documents Actually it has two but we will only look at one of them A well formed XML document has a certain structure consisting of elements containing attributes nested elements and textual content It s possible to build a data structure in the computer s memory that corresponds to the structure and content of the document Of course there are many ways to do this but there is one common standard representation known as the Document Object Model or DOM The DOM specifies how to build data structures to represent XML documents and it specifies some standard methods for accessing the data in that structure The data structure is a kind of tree whose structure mirrors the structure of the document The tree is constructed from nodes of various types There are nodes to represent elements attributes and text The tree can also contain several other types of node representing aspects of XML that we can ignore here Attributes and text can be processed without directly manipulating the corresponding nodes so we will be concerned almost entirely with element nodes The sample program XMLDemo java lets you experiment with XML and the DOM It has a text area where you can enter an XML document Initially the input area contains the sample XML document from this section When you click a button named Parse XML Input the program will attempt to read the XML from the input box and build a DOM representation of that document If the input is not well formed XML an error message is displayed If it is legal the program will traverse the DOM representation and display a list of elements attributes and textual content that it encounters The program uses a few techniques that I won t discuss here In Java the DOM representation of an XML document file can be created with just two statements If selectedFile is a variable of type File that represents the XML file then DocumentBuilder docReader DocumentBuilderFactory newInstance newDocumentBuilder xmldoc docReader parse selectedFile will open the file read its contents and build the DOM representation The classes DocumentBuilder and DocumentBuilderFactory are both defined in the package javax xml parsers The method docReader parse does the actual work It will throw an exception if it can t read the file or if the file does not contain a legal XML document If it succeeds then the value returned by docReader parse is an object that represents the entire XML document This is a very complex task It has been coded once and for all into a method that can be used very easily in any Java program We see the benefit of using a standardized syntax The structure of the DOM data structure is defined in the package org w3c dom which contains several data types that represent an XML document as a whole and the individual nodes in a document The org w3c in the name refers to the World Wide Web Consortium W3C which is the standards organization for the Web DOM like XML is a general standard not just a Java standard The data types that we need here are Document Node Element and NodeList They are defined as interfaces rather than classes but that fact is not relevant here We can use methods that are defined in these data types to access the data in the DOM representation of an XML document An object of type Document represents an entire XML document The return value of docReader parse xmldoc in the above example is of type Document We will only need one method from this class If xmldoc is of type Document then xmldoc getDocumentElement returns a value of type Element that represents the root element of the document Recall that this is the top level element that contains all the other elements In the sample XML document from earlier in this section the root element consists of the tag simplepaint version 1 0 the end tag simplepaint and everything in between The elements that are nested inside the root element are represented by their own nodes which are said to be children

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

  • Javanotes 7.0, Section 12.2 -- Programming with Threads
    Math random int temp hue r hue r hue i hue i temp delay 1000 Wait one second before starting the sort quickSort 0 hue length 1 Sort the whole array recursively catch ThreadTerminationException e User clicked Finish for int i 0 i hue length i hue i i restore original array values finally Make sure running is false and button label is correct running false startButton setText Start display repaint The program uses a variable runner of type Runner to represent the thread that does the sorting When the user clicks the Start button the following code is executed to create and start the thread startButton setText Finish runner new Runner running true Set the signal before starting the thread runner start Note that the value of the signal variable running is set to true before starting the thread If running were false when the thread was started the thread might see that value as soon as it starts and interpret it as a signal to stop before doing anything Remember that when runner start is called runner starts running in parallel with the thread that called it Stopping the thread is a little more interesting because the thread might be sleeping when the Finish button is pressed The thread has to wake up before it can act on the signal that it is to terminate To make the thread a little more responsive we can call runner interrupt which will wake the thread if it is sleeping See Subsection 12 1 2 This doesn t have much practical effect in this program but it does make the program respond noticeably more quickly if the user presses Finish immediately after pressing Start while the thread is sleeping for a full second 12 2 3 Threads for Background Computation In order for a GUI program to be responsive that is to respond to events very soon after they are generated it s important that event handling methods in the program finish their work very quickly Remember that events go into a queue as they are generated and the computer cannot respond to an event until after the event handler methods for previous events have done their work This means that while one event handler is being executed other events will have to wait If an event handler takes a while to run the user interface will effectively freeze up during that time This can be very annoying if the delay is more than a fraction of a second Fortunately modern computers can do an awful lot of computation in a fraction of a second However some computations are too big to be done in event handlers The solution in that case is to do the computation in another thread that runs in parallel with the event handling thread This makes it possible for the computer to respond to user events even while the computation is ongoing We say that the computation is done in the background Note that this application of threads is very different from the previous example When a thread is used to drive a simple animation it actually does very little work The thread only has to wake up several times each second do a few computations to update state variables for the next frame of the animation and call repaint to cause the next frame to be displayed There is plenty of time while the thread is sleeping for the computer to redraw the display and handle any other events generated by the user When a thread is used for background computation however we want to keep the computer as busy as possible working on the computation The thread will compete for processor time with the event handling thread if you are not careful event handling repainting in particular can still be delayed Fortunately you can use thread priorities to avoid the problem By setting the computation thread to run at a lower priority than the event handling thread you make sure that events will be processed as quickly as possible while the computation thread will get all the extra processing time Since event handling generally uses very little processing time this means that most of the processing time goes to the background computation but the interface is still very responsive Thread priorities were discussed in Subsection 12 1 2 The sample program BackgroundComputationDemo java is an example of background processing This program creates an image that takes a while to compute The program uses some techniques for working with images that will not be covered until Section 13 1 for now all that you need to know is that it takes some computation to compute the color of each pixel in the image The image itself is a piece of a mathematical object known as the Mandelbrot set We will use the same image in several examples in this chapter and will return to the Mandelbrot set in Section 13 5 In outline BackgroundComputationDemo is similar to the QuicksortThreadDemo discussed above The computation is done in a thread defined by a nested class Runner A volatile boolean variable running is used to control the thread If the value of running is set to false the thread should terminate The sample program has a button that the user clicks to start and to abort the computation The difference is that the thread in this case is meant to run continuously without sleeping To allow the user to see that progress is being made in the computation always a good idea every time the thread computes a row of pixels it copies those pixels to the image that is shown on the screen The user sees the image being built up line by line When the computation thread is created in response to the Start button we need to set it to run at a priority lower than the event handling thread The code that creates the thread is itself running in the event handling thread so

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

  • Javanotes 7.0, Section 12.3 -- Threads and Parallel Processing
    to the image Here is what the program does to start the computation with a few details omitted taskQueue new ConcurrentLinkedQueue Runnable Create the queue int height Number of rows in the image for int row 0 row height row MandelbrotTask task task Create a task to compute one row of the image taskQueue add task Add the task to the queue int threadCount Number of threads in the pool workers new WorkerThread threadCount running true Set the signal before starting the threads threadsCompleted 0 Records how many of the threads have terminated for int i 0 i threadCount i workers i new WorkerThread try workers i setPriority Thread currentThread getPriority 1 catch Exception e workers i start Note that it is important that the tasks be added to the queue before the threads are started The threads see an empty queue as a signal to terminate If the queue is empty when the threads are started they might see an empty queue and terminate immediately after being started without performing any tasks You should try out MultiprocessingDemo2 It computes the same image as MultiprocessingDemo1 but the rows of pixels are not computed in the same order as in that program if there is more than one thread If you look carefully you might see that the rows of pixels are not added to the image in strict order from top to bottom This is because it is possible for one thread to finish row number i 1 while another thread is still working on row i or even earlier rows The effect might be more apparent if you use more threads than you have processors Try it with 20 threads 12 3 3 Producer Consumer and Blocking Queues MultiprocessingDemo2 creates an entirely new thread pool every time it draws an image This seems wasteful Shouldn t it be possible to create one set of threads at the beginning of the program and use them whenever an image needs to be computed After all the idea of a thread pool is that the threads should sit around and wait for tasks to come along and should execute them when they do The problem is that so far we have no way to make a thread wait for a task to come along To do that we will use something called a blocking queue A blocking queue is an implementation of one of the classic patterns in parallel processing the producer consumer pattern This pattern arises when there are one or more producers who produce things and one or more consumers who consume those things All the producers and consumers should be able to work simultaneously hence parallel processing If there are no things ready to be processed a consumer will have to wait until one is produced In many applications producers also have to wait sometimes If things can only be consumed at a rate of say one per minute it doesn t make sense for the producers to produce them indefinitely at a rate of two per minute That would just lead to an unlimited build up of things waiting to be processed Therefore it s often useful to put a limit on the number of things that can be waiting for processing When that limit is reached producers should wait before producing more things We need a way to get the things from the producers to the consumers A queue is an obvious answer Producers place items into the queue as they are produced Consumers remove items from the other end of the queue We are talking parallel processing so we need a synchronized queue but we need more than that When the queue is empty we need a way to have consumers wait until an item appears in the queue If the queue becomes full we need a way to have producers wait until a space opens up in the queue In our application the producers and consumers are threads A thread that is suspended waiting for something to happen is said to be blocked and the type of queue that we need is called a blocking queue In a blocking queue the operation of dequeueing an item from the queue can block if the queue is empty That is if a thread tries to dequeue an item from an empty queue the thread will be suspended until an item becomes available at that time it will wake up retrieve the item and proceed Similarly if the queue has a limited capacity a producer that tries to enqueue an item can block if there is no space in the queue Java has two classes that implement blocking queues LinkedBlockingQueue and ArrayBlockingQueue These are parameterized types to allow you to specify the type of item that the queue can hold Both classes are defined in the package java util concurrent and both implement an interface called BlockingQueue If bqueue is a blocking queue belonging to one of these classes then the following operations are defined bqueue take Removes an item from the queue and returns it If the queue is empty when this method is called the thread that called it will block until an item becomes available This method throws an InterruptedException if the thread is interrupted while it is blocked bqueue put item Adds the item to the queue If the queue has a limited capacity and is full the thread that called it will block until a space opens up in the queue This method throws an InterruptedException if the thread is interrupted while it is blocked bqueue add item Adds the item to the queue if space is available If the queue has a limited capacity and is full an IllegalStateException is thrown This method does not block bqueue clear Removes all items from the queue and discards them Java s blocking queues define many additional methods for example bqueue poll 500 is similar to bqueue take except that it will not block for longer than 500 milliseconds but the four listed here are sufficient for our purposes Note that I have listed two methods for adding items to the queue bqueue put item blocks if there is not space available in the queue and is most appropriate for use with blocking queues that have a limited capacity bqueue add item does not block and is appropriate for use with blocking queues that have an unlimited capacity An ArrayBlockingQueue has a maximum capacity that is specified when it is constructed For example to create a blocking queue that can hold up to 25 objects of type ItemType you could say ArrayBlockingQueue ItemType bqueue new ArrayBlockingQueue ItemType 25 With this declaration bqueue put item will block if bqueue already contains 25 items while bqueue add item will throw an exception in that case Recall that this ensures that tasks are not produced indefinitely at a rate faster than they can be consumed A LinkedBlockingQueue is meant for creating blocking queues with unlimited capacity For example LinkedBlockingQueue ItemType bqueue new LinkedBlockingQueue ItemType creates a queue with no upper limit on the number of items that it can contain In this case bqueue put item will never block and bqueue add item will never throw an IllegalStateException You would use a LinkedBlockingQueue when you want to avoid blocking and you have some other way of ensuring that the queue will not grow to arbitrary size For both types of blocking queue bqueue take will block if the queue is empty The sample program MultiprocessingDemo3 java uses a LinkedBlockingQueue in place of the ConcurrentLinkedQueue in the previous version MultiprocessingDemo2 java In this example the queue holds tasks that is items of type Runnable and the queue is declared as an instance variable named taskQueue LinkedBlockingQueue Runnable taskQueue When the user clicks the Start button and it s time to compute an image all of the tasks that make up the computation are put into this queue This is done by calling taskQueue add task for each task It s important that this can be done without blocking since the tasks are created in the event handling thread and we don t want to block that The queue cannot grow indefinitely because the program only works on one image at a time and there are only a few hundred tasks per image Just as in the previous version of the program worker threads belonging to a thread pool will remove tasks from the queue and carry them out However in this case the threads are created once at the beginning of the program actually the first time the Start button is pressed and the same threads are reused for any number of images When there are no tasks to execute the task queue is empty and the worker threads will block until tasks become available Each worker thread runs in an infinite loop processing tasks forever but it will spend a lot of its time blocked waiting for a task to be added to the queue Here is the inner class that defines the worker threads This class defines the worker threads that make up the thread pool A WorkerThread runs in a loop in which it retrieves a task from the taskQueue and calls the run method in that task Note that if the queue is empty the thread blocks until a task becomes available in the queue The constructor starts the thread so there is no need for the main program to do so The thread will run at a priority that is one less than the priority of the thread that calls the constructor A WorkerThread is designed to run in an infinite loop It will end only when the Java virtual machine exits This assumes that the tasks that are executed don t throw exceptions which is true in this program The constructor sets the thread to run as a daemon thread the Java virtual machine will exit automatically when the only threads are daemon threads In this program this is not necessary since the virtual machine is set to exit when the window is closed In a multi window program however we can t simply end the program when a window is closed private class WorkerThread extends Thread WorkerThread try setPriority Thread currentThread getPriority 1 catch Exception e try setDaemon true catch Exception e start Thread starts as soon as it is constructed public void run while true try Runnable task taskQueue take wait for task if necessary task run catch InterruptedException e We should look more closely at how the thread pool works The worker threads are created and started before there is any task to perform Each thread immediately calls taskQueue take Since the task queue is empty all the worker threads will block as soon as they are started To start the computation of an image the event handling thread will create tasks and add them to the queue As soon as this happens worker threads will wake up and start processing tasks and they will continue doing so until the queue is emptied Note that on a multi processor computer some worker threads can start processing even while the event thread is still adding tasks to the queue When the queue is empty the worker threads will go back to sleep until processing starts on the next image An interesting point in this program is that we want to be able to abort the computation before it finishes but we don t want the worker threads to terminate when that happens When the user clicks the Abort button the program calls taskQueue clear which prevents any more tasks from being assigned to worker threads However some tasks are most likely already being executed when the task queue is cleared Those tasks will complete after the computation in which they are subtasks has supposedly been aborted When those subtasks complete we don t want their output to be applied to the image It s not a big deal in this program but in more general applications we don t want output meant for a previous computation job to be applied to later jobs My solution is to assign a job number to each computation job The job number of the current job is stored in an instance variable named jobNum and each task object has an instance variable that tells which task that job is part of When a job ends either because the job finishes on its own or because the user aborts it the value of jobNum is incremented When a task completes the job number stored in the task object is compared to jobNum If they are equal then the task is part of the current job and its output is applied to the image If they are not equal then the task was part of a previous job and its output is discarded It s important that access to jobNum be properly synchronized Otherwise one thread might check the job number just as another thread is incrementing it and output meant for an old job might sneak through after that job has been aborted In the program all the methods that access or change jobNum are synchronized You can read the source code to see how it works One more point about MultiprocessingDemo3 I have not provided any way to terminate the worker threads in this program They will continue to run until the Java Virtual Machine exits To allow thread termination before that we could use a volatile signaling variable running and set its value to false when we want the worker threads to terminate The run methods for the threads would be replaced by public void run while running try Runnable task taskQueue take task run catch InterruptedException e However if a thread is blocked in taskQueue take it will not see the new value of running until it becomes unblocked To ensure that that happens it is necessary to call worker interrupt for each worker thread worker just after setting runner to false If a worker thread is executing a task when runner is set to false the thread will not terminate until that task has completed If the tasks are reasonably short this is not a problem If tasks can take longer to execute than you are willing to wait for the threads to terminate then each task must also check the value of running periodically and exit when that value becomes false 12 3 4 Wait and Notify To implement a blocking queue we must be able to make a thread block just until some event occurs The thread is waiting for the event to occur Somehow it must be notified when that happens There are two threads involved since the event that will wake one thread is caused by an action taken by another thread such as adding an item to the queue Note that this is not just an issue for blocking queues Whenever one thread produces some sort of result that is needed by another thread that imposes some restriction on the order in which the threads can do their computations If the second thread gets to the point where it needs the result from the first thread it might have to stop and wait for the result to be produced Since the second thread can t continue it might as well go to sleep But then there has to be some way to notify the second thread when the result is ready so that it can wake up and continue its computation Java of course has a way to do this kind of waiting and notifying It has wait and notify methods that are defined as instance methods in class Object and so can be used with any object These methods are used internally in blocking queues They are fairly low level tricky and error prone and you should use higher level control strategies such as blocking queues when possible However it s nice to know about wait and notify in case you ever need to use them directly The reason why wait and notify should be associated with objects is not obvious so don t worry about it at this point It does at least make it possible to direct different notifications to different recipients depending on which object s notify method is called The general idea is that when a thread calls a wait method in some object that thread goes to sleep until the notify method in the same object is called It will have to be called obviously by another thread since the thread that called wait is sleeping A typical pattern is that Thread A calls wait when it needs a result from Thread B but that result is not yet available When Thread B has the result ready it calls notify which will wake Thread A up if it is waiting so that it can use the result It is not an error to call notify when no one is waiting it just has no effect To implement this Thread A will execute code similar to the following where obj is some object if resultIsAvailable false obj wait wait for notification that the result is available useTheResult while Thread B does something like generateTheResult obj notify send out a notification that the result is available Now there is a really nasty race condition in this code The two threads might execute their code in the following order 1 Thread A checks resultIsAvailable and finds that the result is not ready so it decides to execute the obj wait statement but before it does 2 Thread B finishes generating the result and calls obj notify 3 Thread A calls obj wait to wait for notification that the result is ready In Step 3 Thread A is waiting for a notification that will never come because notify has already been called in Step 2

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

  • Index of /javanotes/source/chapter12/netgame/common
    31 07 30 17K DisconnectMessage java 2015 07 31 07 30 895 ForwardedMessage java 2015 07 31 07 30 1 2K Hub java 2015 07 31 07 30 23K ResetSignal java 2015 07 31 07 30 242 StatusMessage java 2015

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

  • Javanotes 7.0, Section 12.5 -- Network Programming Example: A Networked Game Framework
    See the source code for more information I should also note that Client contains the protected instance variable connectedPlayerIDs of type int an array containing the ID numbers of all the clients that are currently connected to the hub The most important public methods that are provided by the Client class are send message transmits a message to the hub The message can be any non null object that implements the Serializable interface getID gets the ID number that was assigned to this client by the hub disconnect closes the client s connection to the hub It is not possible to send messages after disconnecting The send method will throw an IllegalStateException if an attempt is made to do so The Hub and Client classes are meant to define a general framework that can be used as the basis for a variety of networked games and indeed of other distributed programs The low level details of network communication and multithreading are hidden in the private sections of these classes Applications that build on these classes can work in terms of higher level concepts such as players and messages The design of these classes was developed though several iterations based on experience with several actual applications I urge you to look at the source code to see how Hub and Client use threads sockets and streams In the remainder of this section I will discuss three applications built on the netgame framework I will not discuss these applications in great detail You can find the complete source code for all three in the netgame package 12 5 2 A Simple Chat Room Our first example is a chat room a network application where users can connect to a server and can then post messages that will be seen by all current users of the room It is similar to the GUIChat program from Subsection 12 4 2 except that any number of users can participate in a chat While this application is not a game it does show the basic functionality of the netgame framework The chat room application consists of two programs The first ChatRoomServer java is a completely trivial program that simply creates a netgame Hub to listen for connection requests from netgame clients public static void main String args try new Hub PORT catch IOException e System out println Can t create listening socket Shutting down The port number PORT is defined as a constant in the program and is arbitrary as long as both the server and the clients use the same port Note that ChatRoom uses the Hub class itself not a subclass The second part of the chat room application is the program ChatRoomWindow java which is meant to be run by users who want to participate in the chat room A potential user must know the name or IP address of the computer where the hub is running For testing it is possible to run the client program on the same computer as the hub using localhost as the name of the computer where the hub is running When ChatRoomWindow is run it uses a dialog box to ask the user for this information It then opens a window that will serve as the user s interface to the chat room The window has a large transcript area that displays messages that users post to the chat room It also has a text input box where the user can enter messages When the user enters a message that message will be posted to the transcript of every user who is connected to the hub so all users see every message sent by every user Let s look at some of the programming Any netgame application must define a subclass of the abstract Client class For the chat room application clients are defined by a nested class ChatClient inside ChatRoomWindow The program has an instance variable connection of type ChatClient which represents the program s connection to the hub When the user enters a message that message is sent to the hub by calling connection send message When the hub receives the message it packages it into an object of type ForwardedMessage along with the ID number of the client who sent the message The hub sends a copy of that ForwardedMessage to every connected client including the client who sent the message On the client side in each client when the message is received from the hub the messageReceived method of the ChatClient object in that client is called ChatClient overrides this method to make it add the message to the transcript of the ChatClientWindow To summarize Every message entered by any user is sent to the hub which just sends out copies of each message that it receives to every client Each client will see exactly the same stream of messages from the hub A client is also notified when a player connects to or disconnects from the hub and when the connection with the hub is lost ChatClient overrides the methods that are called when these events happen so that they post appropriate messages to the transcript Here s the complete definition of the client class for the chat room application A ChatClient connects to a Hub and is used to send messages to and receive messages from the Hub Messages received from the Hub will be of type ForwardedMessage and will contain the ID number of the sender and the string that was sent by that user private class ChatClient extends Client Opens a connection to the chat room server on a specified computer ChatClient String host throws IOException super host PORT Responds when a message is received from the server It should be a ForwardedMessage representing something that one of the participants in the chat room is saying The message is simply added to the transcript along with the ID number of the sender protected void messageReceived Object message if message instanceof ForwardedMessage no other message types are expected ForwardedMessage

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

  • Index of /javanotes/source/chapter12/netgame/chat
    chat Name Last modified Size Description Parent Directory ChatRoomServer java 2015 07 31 07 30 1 1K ChatRoomWindow java 2015 07 31 07 30 10K Apache 2 4 7 Ubuntu

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