Prototyping a Swing Interface with the Netbeans IDE GUI Editor Netbeans provides an environment for creating Java applications including a module for GUI design. Here we assume that we have some existing code which implements the model portion of the MVC and we wish to prototype an interface for it. See section 5 for a discussion of the MVC and the particular model our example works with. 1. Getting Started 1.1 Make a new directory for this project. Copy the files start.jar and build.xml to your directory. 1.2. Start up Netbeans and make a new project. Within Netbeans make a new project (Project --> Project Manager --> New) and associate your local directory with the project. Select the Filesystems icon in the Explorer window and mount the local directory which contains your files. Click on the little lever to the left of the build file icon as seen in the Explorer (Figure 1). Double-click the unjarstart target. This will uncompress the starting directory for this project. Inside is a src folder which should also be mounted.. Click lever to reveal targets inside. your_project_directory your_project_directory/src Figure 1 Files shown are after decompressing the starting jar file and mounting the src folder as well. 1.3. Create a GUI form. Select the cs484guiex folder in the Explorer. Hold down the right button and select the New option. Pick new JFrame. A dialog box will appear and ask for the class name - use StateImgFrame. The IDE will move to GUI Editing mode and a Form Editor window will appear as well as a Source Editor window with generated Java code which corresponds to the GUI displayed in the Form Editor. Initially all that the GUI consists of is a single JFrame. your_project_directory your_project_directory/src The new class StateImgFrame is created and appears visually in the Form Editor. It has been placed in the src directory. Its Java source code has been generated and is shown in the Source Editor window. Figure 2
2. Adding Components to the Form We will start to build the interface by adding labels and buttons. We also need to take into account the fact that the components that we add to a form will be positioned by a layout manager. Components are placed within other components (Containers). Containers use layout managers to position and size the components inside of them. Our goal is something like this: State statelab At the top of the form editor is a tabbed palette. We will be using the Swing components and Layouts. leftcard rightcard Back Next JLabel JButton JPanel a JPanel backbut nextbut Figure 3 2.1 Add the buttons. Click on the JButton symbol in the palette and then click within the JFrame. A button is added to the frame but is sized to fill the entire frame. The component hierarchy is shown in the upper right. The lower right displays the properties for the selected item - the JButton just created. Components are automatically named by the system but we should rename them sensibly for future reference. To make components fit where we d like them to, we need to control the layouts. It will be easier in this case to create a JPanel that we can place the buttons within. Component Inspector Properties Figure 4 Move your mouse to the upper right and hold down the right button over the JFrame to get a popup menu. Select Add from Palette --> Swing --> JPanel to get a new JPanel within the frame. Draw the JButton so that it appears nested within the JPanel. Create another JButton and place it in the panel. 2.2 Modify Button Properties. Place the mouse over the leftmost JButton. Using the right button popup menu, select Rename and name the button backbut. Move the mouse to the text field in the properties dialog and change its text to Back. Modify the right JButton so it becomes nextbut and has the text Next. Note that the panel holding the JButtons is using a Flowlayout. That panel is with the JFrame which is using a Border- Layout. You can graphically select the panel and slide it to the bottom of the JFrame as shown in Figure 5.
Figure 5 2.3 Add a Label. Click on the Swing JLabel component on the palette and click again within the JFrame. Drag the label until it is positioned at the top as shown in Figure 6. Rename the label to be statelabel and modify its properties as shown. Note that you can change the font of a label too. Clicking on the Test Form button, shows the result so far. Note the size is different than might be expected. Test Form Figure 6 2.4 Add 2 more labels which will display images. Use the label component to create a label to hold an image card on the left and one on the right. Name the labels leftcard and rightcard respectively. To place an image on a label, select the label s icon property.... Select the class path option, and look for an image in the image subdirectory (such as /images/faner.jpg). Set the text for the label to be empty so only a picture is shown. After associating a picture with both the leftcard and rightcard and running the Test Form button you should get something similar to what is shown in Figure 7. Figure 7
3. Adding a MenuBar and its Menus 3.1 Add a MenuBar. The MenuBar is a row of menus that we want to appear at the top of the JFrame. To create it select the JFrame and get the right menu pop-up. Select the Add from Palette --> Swing --> JMenuBar. The MenuBar will be added along with a single menu. See Figure 8. your_project_directory Figure 8 Double-click on the run target to run your interface as an application your_project_directory/src Figure 9 3.2 Create the File Menu. Select the JMenu automatically created when the JMenuBar was created. Change its name to filemenu. Change its text to File. 3.3 Add an Item to a Menu. Select the filemenu and use the right menu pop-up to Add --> JMenuItem. Change the name of the new menuitem to quitmenuitem. Change its text to Quit. Try out your menu with Test Form. 4. Running the Interface code as an Application 4.1 Running from ANT. The Netbeans IDE can utilize a new utility which is becoming standard for development with Java. ANT which acts sort of like the Unix make command, organizes dependencies between tasks and can be used to accomplish things like compiling, running, testing and packaging of code. ANT reads an XML file by default called build.xml. You should have a build file in your project directory. See Figure 9. Double-clicking on the run target will execute that target from within the build.xml file to run your interface code as a java application. Note: this won t work if you haven t given the name StateImgFrame to your interface class. Notice the menu works like a menu but when the Quit option is selected, nothing happens. 4.2 Hooking up the Quit menu item. The GUI editor generates java source code as you graphically edit the GUI. Sections of code rendered in blue are considered protected and are not to be edited by hand. If you double-click the quitmenitem it will take you to the source code and its actionperformed method. Add the code System.exit(); to the actionperformed method. Double-click the run target and try out the menu now. The application should now quit in response to the Quit menu item. Add the text System.exit(0); Figure 10
5. Hooking up the Interface to an Underlying Model In order to separate the internal logic of an application from its interface, the Model View Controller (MVC) paradigm is often used. Application presents the user with a visualization (View) and the means to issue commands (Controller) to the object of interest (Model). See Figure 11. The model object here is very simple. Its StateModel Model Underlying, application object, business logic, data, etc. Q. What state are you in? A. Model is in state X User wants to move to next state. GUI View Presents the model to the user. Controller Allows user to manipulate/query the model Figure 11 StateImgFrame logic merely represents several states that we can move through. The model organizes those states as a sequence beginning at the Start state and ending at the Finish state. Our model also gets to impose the policies about what are legal source and destination states. For instance, from Start we are only allowed to go to State1. We can only go forward or backward a single state at a time. Once the Finish state is reached, we can only move backwards. All such rules should be in the logic of the model. The interface will call model methods to pass along the user s commands and ask the model for its current configuration so it can be displayed accurately. The separation of the model from the View/Controller is especially important. It separates the internal logic from the GUI. This makes the internal logic easier to test and maintain and keeps it independent of the particular interface. A single application may represent the same model in different ways (as diagrams, numbers etc.). The methods for this model and a diagram of its legal state transitions are shown in Figure 12. public StateModel()........... constructor public int getstate()............ returns an integer representing the current state public void backstate()........ moves the model one state backwards. If there is no such allowable state from the current state then the state will remain unchanged. public void nextstate()........... moves the model one state forward. If there is no such allowable state from the current state then the state will remain unchanged. public boolean isbackok()......returns true if able to move one state backwards otherwise false is returned. public boolean isnextok()..... returns true if able to move one state forwards otherwise false is returned. next next next Start State1 State2 Finished Figure 12 back back back
Our application will visualize the 4 different states by displaying a different image pair for each state and a label giving the name of the state. Make sure you have the StateModel.java file in the same directory as your source file for the interface (StateImgFrame.java). Note the model code will not need to be changed. The interface code will be changed to hook up with the model. There is a file codetopaste.txt that has source code that you can copy and paste into the StateImgFrame.java file. It is numbered with the points below. 5.1 Make the Next button (Controller) pass its command onto the model. Double-click the Next button in the Form Editor. You will automatically generate an event handler for it and be taken to the source code editor. Make the handler call model.nextstate(); 5.2 Have the interface create and maintain an instance of the model. Create a StateModel variable, model, within the StateImgFrame class. Make a new constructor that a model can be passed to and modify the default constructor to make use of it. 5.3 Make a method so the interface (View) can ask the model for its current information. The method updategui() is defined near the end of the StateImgFrame.java file. It will be used to set all the GUI components to their up-to-date values based upon the model. 5.4 Add a helper function that updates the labels. The method setlabels() will set the label components based upon the model information. Add its code to the end of the StateImgFrame class. 5.5 A helper to load in image icons is needed. Since the GUI will use pictures on some of the labels, a utility function is defined to load the images into memory. Add the method loadimgicons() to the end of the StateImg- Frame class. 5.6 Declare the image icon variables within the class. Use an import statement just after the package statement at the top of the file(6.1). Then after the protected variables enter the declarations for the ImageIcons(6.2). 5.7 Revise the handler to update the GUI. Go back to the nextbutactionperformed() method and after the model.nextstate() method has been called, call the updategui() method. Run the application to see what happens. Watch carefully. Hitting the Next button does change the state but you can only tell by watching the text label at the top. None of the images show up! 5.8 Load the images at initialization. Make sure that the images are loaded. In the constructor (the one which takes a model as input) add the statement loadimgicons() after the components are initialized. Run the application again. It almost looks right but the initial conditions aren t right. 5.9 Make the application start out by asking the model for information. Add the following statement just after the line added in the previous step: updategui(); The Next button should work correctly now. 5.10 Hook-up the Back button. Apply steps 5.1 and 5.7 to the Back button. Use the code model.backstate(); updategui(); in its handler. 6. Tidy-up Appearances Most applications have a meaningful title for their main window. If you select the JFrame in the form editor you will see that it has properties that can be set. Set its title to something like CS484 GUI Demo. You also may decide whether or not to allow the window to be resized. You can set that properties from the Other Properties listing Check your understanding: Hook-up the Next and Back entries in the Navigate Menu so that they work as the buttons do. (Also make sure that they are enabled and disabled properly). prepared by Dr. Michael Wainer, Feb. 2004.