Getting Started


You will build a simple Swing application that presents a lists of courses to the end user. It will also allow the user to add new courses.


As you learn Swing, you might start with spike solutionsbits of code that demonstrate how Swing should work. Once you get these spikes working, you will go back and figure out how to test the Swing code. This chapter sometimes presents its material in this fashion: I will demonstrate how to code something in Swing, then supply code that shows how to test it.

Most applications, whether they use Swing or not, initiate with a frame. A frame is a top-level window with a title bar and border by default. The frame is largely drawn by and under the control of your operating system. Within Java, the Swing frame class is javax.swing.JFrame. Building an initial application in Java is as simple as constructing a JFrame, setting its size, and making it visible.

Create the class Sis (short for Student Information System).

 package sis.ui; import javax.swing.*; public class Sis {    static final int WIDTH = 350;    static final int HEIGHT = 500;    public static void main(String[] args) {       new Sis().show();    }    public void show() {       JFrame frame = new JFrame();       frame.setSize(WIDTH, HEIGHT);       frame.setVisible(true);    } } 

The definition for Sis includes a main method to allow you to execute the application from the command line. About the only things you ever want to do in a main method are to construct a new instance and call a single method on it. You may first need to call a method to parse the command-line arguments. If your main method is more involved, you need to refactor. Resist adding any real logic to mainmain is usually not comprehensively tested.

Compile and execute Sis. You should see a simple frame window (see Figure 1). Experiment with this window and note that you can do things such as size it, minimize it, or close it like any other windowed application. You may also want to experiment with the setSize and setVisible messages to see how they impact the frame. Try omitting either or both message sends.

Figure 1. A Frame Window


The only problem is that when you close this window, the Java process does not terminate. Behind the scenes, Swing creates user threads. Exiting the main method does not result in the termination of these user threads. See the section Shutting Down in Lesson 13 for a discussion of user threads and daemon threads.

You can tell the JFrame to terminate the Java process by telling it to exit on close:

 package sis.ui; import javax.swing.*; public class Sis {    static final int WIDTH = 300;    static final int HEIGHT = 200;    public static void main(String[] args) {       new Sis().show();    }    void show() {       JFrame frame = new JFrame();       frame.setSize(WIDTH, HEIGHT);       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       frame.setVisible(true);    } } 

Now that you understand what it takes to build a frame, you can toss this code away and write a couple of tests. You will want to refer to the Java API documentation to see what kinds of queries you can send to a JFrame object. The tests show that you can inspect each piece of information you use to initialize the frame. You can also query whether or not the frame is visible.

 package sis.ui; import junit.framework.*; import javax.swing.*; public class SisTest extends TestCase {    private Sis sis;    private JFrame frame;    protected void setUp() {       sis = new Sis();       frame = sis.getFrame();    }    public void testCreate() {       final double tolerance = 0.05;       assertEquals(Sis.HEIGHT, frame.getSize().getHeight(), tolerance);       assertEquals(Sis.WIDTH, frame.getSize().getWidth(), tolerance);       assertEquals(JFrame.EXIT_ON_CLOSE,                    frame.getDefaultCloseOperation());    }    public void testShow() {       sis.show();       assertTrue(frame.isVisible());    } } 

The code that meets this test ends up slightly different than the spike code:

 package sis.ui; import javax.swing.*; public class Sis {    static final int WIDTH = 300;    static final int HEIGHT = 200;    private JFrame frame = new JFrame();    public static void main(String[] args) {       new Sis().show();    }    Sis() {       frame.setSize(WIDTH, HEIGHT);       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    }    void show() {       frame.setVisible(true);    }    JFrame getFrame() {       return frame;    } } 

When you run the test, you will see the frame window display on screen, because the test instantiates Sis. Resist embedding such tests that pop up windows. It is very distracting and will slow down your tests considerably. You will learn techniques later that eliminate the need to render the user interface while running tests. For now, a test or two that pops up windows might be considered acceptable.

The frame window does not disappear even after the test completes. This is a bigger distraction that you can fix. In your test's tearDown method, tell the application to close:

 public class SisTest extends TestCase {    ...    protected void tearDown() {       sis.close();    }    ... } 

Close the application by having it dispose of the frame window:

 package sis.ui; import javax.swing.*; public class Sis {    ...    private JFrame frame = new JFrame();    ...    void close() {       frame.dispose();    } } 

View First or Model First?

When developing a user interface, the question often arises of which to approach first: building the model or building the view? There is no right answer. It depends on your comfort level and ultimately on the approach you derive the most success from.

In the core 15 lessons of Agile Java, you learned to build Java classes in the absence of a user interface or place in a larger system. In reality, you will find that context often changes your design. Application needs may significantly impact the public interface of model classes.

I've been most successful when I've designed a system "application first." Each time I've built model classes in isolation, I've been forced to alter their behavior considerably when attempting to drop them into an application.

Even though I center the development of a system around its application classes, I do so with the view and its needs clearly in mind. And in reality, I rarely develop any of a system "first." I've found it far more effective to bounce around between the various layers, using tests and their results as my guide.




Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net