Java程序辅导

C C++ Java Python Processing编程在线培训 程序编写 软件开发 视频讲解

客服在线QQ:2653320439 微信:ittutor Email:itutor@qq.com
wx: cjtutor
QQ: 2653320439

This exercise is intended to help you get used to building graphical user interfaces (GUIs)for Java programs. Some explanations first, then the coding exercises:

Finally, there are a couple of that relate toassignment tasks. There is an additional exercise that involves creating a variant of one of these demonstrations.

There are two types of graphical Java program - Applets, and applications. Applets were the feature used to sell Java initially; they are(smallish) programs for which the class files can be downloaded from a WWW host and run ina web browser. Applets never achieved the predicted level of usage; alternativetechnologies were found more appropriate for use on the browser (e.g. "Flash" foranimated graphics, Javascripting for dynamic HTML). Mostly GUIs are developed forstand-alone Java applications.

There aren't actually major differences between Applets and GUI-applications. Bothuse "event-driven" program architectures wherein the user's interactions (mouse-clicksand keystrokes) are packaged as "event objects" that are delivered to call-back functionsthat the programmer has registered to receive these events. Both are built with the samecollection of standardized user interface objects - text fields that can be used to entershort text strings, action buttons, checkboxes, scrolling panes with scroller controls, andgraphic areas for drawing application specific data. Both use the same graphics objects thatsupport functions for drawing text and filling in colored regions. Both use the samecolor model.

The real difference is that an Applet gains access to a subpart of a window that belongsto the browser in which it runs, an application has to negotiate with the operating systemto open a window. These differences result in the use of different base classesfor the graphical parts of the program. The developer of anApplet will create an application specific subclass of one of the Sun supplied "applet base classes";the developer will add all the text fields, checkboxes, panels and buttons as contents of thiscustomized applet. The applet's GUI interface appears when the browser displays the HTMLpage that references it. The developer of an application will create an instance of one of Sun'ssupplied "frame classes" and then add all the text fields etc as the contents of this "frame". When the interface has been built, the application will explicitly show the new frame and itscontents.

Applets are often popular as assignments in Java courses, but they are problematic inreal use. First, your browser has to contain a JVM (Java interpreter) that has up to date versionsof standard packages like java.lang and java.util. In practice, most browsers have old versions (e.g.Java 1.1 circa 1998) and programs written to current Java APIs (1.4 etc) simply will not run. Javaapplets only run reliably if the user of the browser has installed a Sun plugin with a current JVMand basic set of packages. Even if you do have a valid Java interpreter in your browser, youcan experience performance problems resulting from the need to download individual class file and"jar" (java archive) files with packages.

These exercises include applets and applications. The applets should be run with the appletviewertool (you can try available browsers, but the applets will most likely only work with appletviewer).

There are several libraries (packages) of graphical classes for Java. Sun has two - AWT and Swing.IBM supplies another package with its Eclipse development system. Netscape invented another librarythat you may still encounter. There are others.

The applets and applications that you will develop will use AWT or Swing (which itself makes somevery limited use of AWT). The different packages all have some standard components - so you will find classButton (AWT) and JButton (Swing), TextField (AWT) and JTextField (Swing), Panel (AWT) and JPanel (Swing).Swing has a larger selection of classes than AWT; for example, AWT has a simple class for displayand editing of block text in a single font, but Swing also has classes for formatted text in multiplefonts and classes for display of HTML text.

The different packages take quite different approaches to graphics rendering. The AWT package reliesa lot on C-code in the supporting Java runtime engine. An AWT class such as Button does not actuallyhandle the display of an action button control; instead, this work is done by system specific codein the C runtime. This C code is different for a Solaris system, for a Macintosh, and for a Windows system;the result is that the button renders as an X-windows button, a Macintosh style button, or Windows button.Similarly, the AWT run-time code for event-handling links into that supplied by the operating system, so thata button press starts as an XButton event or a Windows button event as generated by the OS.In contrast, Swing minimizes its reliance on the underlying platform; basically, the Swing system simplyasks the platform for a graphic area for which it will take total responsibility. Swing draws itsown buttons, textfields etc (using user specified preferences to determine style); and Swing picks upgeneric key and mouse events and handles all their translation. Most of the Swing code is Java. Theresult is that Swing built interfaces often look better, but the code runs slower.

The exercises will use both Swing and AWT.

By the time Java was invented, there were already extensive class libraries (in C++ and "Object Pascal")that could be used to build GUI interfaces for applications on Macintosh and Windows systems. Theseearlier class libraries had many of the same classes as you find in the Java packages - classes forbuttons, scrollpanes, scrollbars, checkboxes, etc, etc. The developer of a graphical interface wouldstart with "frame" or "window" class, and place labels, buttons, textfields etc at specific coordinatelocations.

The use of specific coordinates caused problems for Java's "write once, run anywhere" policy. Theproblems relate to the fact that things like buttons are different sizes on different platforms - a GUImight look fine on a Mac, but transfer to Windows and the various fields overlap. The Java designers decided to follow a different approach - one pioneered for the C-libraries used with X-windows on Unixsystems. In this approach, it is not the programmer who decides where components like buttons shouldappear - instead this becomes the responsibility of the runtime system.

In the Java version, one has "containers", "simple components", and "layout managers". Containersare graphical components that can contain other graphical components. One always has a top-level containersuch as the Applet itself, or a Frame. There are others. A "Panel" is a container that can be put intoa top-level Applet or Frame and can be used to hold subordinate components (other panels or simplecomponents like buttons, textfields, or checkboxes). Each "container" has an associated "layout manager"(either explicitly defined by the programmer or obtained by default from the Java graphic system). Itis this layout manager that determines the arrangement of subordinate components.

There are several layout managers defined (Swing and AWT share many of the same layout manager classes,Swing has a few extra layout managers). Some,like FlowLayout, are simple but produce unattractive interfaces. Others, like GridBagLayout, are fiendishly complex, but give the programmer a great deal of control and enable the construction ofcomplex interfaces. (A few people cheat, setting the layout manager to null and usingexplicit coordinates when creating an interface; such cheating is frowned on by Java purists andassignment markers.)

In CSCI213, you are expected to build some of your GUI interfaces programmatically. You create your GUI objects; you create containers and layout managers; you assign GUI objects to containersand provide specifications to the layout manager that help it place the components. It is tiresome boring code; but you need to work through it to understand how GUIs are created andhow they work. Once you have built some GUIs "from the ground up", and you understandthe basic concepts, then you can rely on GUI builders to do much of the coding for you.

Application specific display classes are also necessary. The AWT package contains a "Canvas"class for this purpose - you create a subclass of Canvas and link it to your data. Whenthe windows system wants data drawn, it invokes the "paint" method of your Canvas subclass.Your code then renders some pictorial representation of your data. For some reason, Swingdoes not have a corresponding class - so instead one typically creates an applicationspecific subclass of JPanel and links this to the data.

When you need to render data, you will first obtain a reference to a "Graphics" object(you can get this from your Canvas or JPanel class). The Graphics class defines operationslike drawString, fillRect, and frameOval. You use these to draw an image of your data.

The Color system is simple - you define Color objects by specifying their red, green,and blue intensity values. (Java is American, so colour is consistently spelt as color). There are a few constant color object defined by the Color class - e.g. Color.RED; youcan invent others by specifying the r, g, b values (each in range 0...255). If you havea decent graphics card, the colors will display properly (some of the Sun workstationsin the Java lab may still have old graphics cards that have restricted color displays).You set foreground and background colors for a Graphics object prior to invoking an operation like drawString or fillRect (remember to set the colors back to whateverthey were originally, the Graphics object is shared, and if you don't reset colorsthen you may end up with oddly colored buttons, scrollbars etc).


  1. Run demonstration GUI application

    Compile, run, and try to understand a simple GUI application.

    The code for the application is shown below.The code defines an application class and some additional classes; allthe classes are defined in a single file. The code canbe cut-and-pasted into a file (EventDemo1.java); this file can be compiled andrun using the command line compiler javaand then run using java. Rather than run at thecommand line, you shouldadapt this code for execution in the NetBeans environment (you simplycreate separate NetBeans files for each class and "cut&paste" the example code.

    The "EventDemo1" application illustrates, in a limited way, a basic GUI-style program that has some data thatare to be displayed, with some controls that change the rendering of the data.

    The data in this case are a set of rectangles. They are displayed bysimply drawing the rectangles in a Canvas. The controls can be used toshift the coordinates of these rectangles. The data will be redisplayed aftereach shift. The controls consist of a set of action buttons - one eachfor moving the rectangles "north", "east", "south", or "west".

    The main (public) class is EventDemo1. The mainline creates a "data object"and a "display object". The other classes (all defined in the one file) areDataObject, MyCanvas, and Display.

    The DataObject class has data members for an origin for a coordinate system,a vector used as a collection class for rectangle objects, and a link to itsCanvas. The DataObject class processes the events coming from the actionbutton controls; each such event results in a shift of the coordinateorigin. When the rectangles have been shifted, any existing display isout of date; so, the "repaint" operation is invoked on the associated Canvasobject. (Repaint doesn't actually cause the painting to be done immediately, insteada paint event is scheduled at the convenience of the AWT library code.) Since theDataObject class is handling the action events from the controls, it has beendefined as an ActionListener. The DataObject class also defines a paint operation;it is here that one finds the code that draws the rectangles with appropriatepositions. (In this example, the DataObject is both "Model" and "Control".)

    The Canvas class defines a visual component that can be placed in container (suchas an Applet or a Frame) and occupies space. It is for display of applicationspecific data. It obtains a link to its data when it is constructed. It getstold to perform a paint operation when the window is first opened and after anysubsequent repaint invocations. Its paint operation simply defers the actual work to the related data object.

    The Display class builds the complete GUI - a frame that contains othercomponent that will be arranged using a "BorderLayout". The main area isfor the MyCanvas. The "East" area is for a panel containing action buttons.(The GUI classes are defined. In this example, you do not build them using the NetBeans GUI editor.You simply add the class definitions to a NetBeans project.)

    import java.awt.*;import java.awt.event.*;import java.util.*;class DataObject implements ActionListener {	public DataObject() {		myCollection = new Vector<Rectangle>();		Rectangle r1;		r1 = new Rectangle(10, 20, 40, 40);		myCollection.addElement(r1);		r1 = new Rectangle(110,80, 60, 30);		myCollection.addElement(r1);		r1 = new Rectangle(220, 180, 10, 85);		myCollection.addElement(r1);	}	public void LinkToCanvas(Canvas c) { theCanvas = c; }	public void paint(Graphics g)	{		for(Rectangle r : myCollection) {			int x;			int y;			x = xOrigin + r.x;			y = yOrigin + r.y;			g.drawRect(x, y, r.width, r.height);		}	}	public void actionPerformed(ActionEvent e)	{		String s = e.getActionCommand();		if(s.equals("North")) { yOrigin -= 5; theCanvas.repaint(); }		else		if(s.equals("East")) { xOrigin += 5; theCanvas.repaint(); }		else		if(s.equals("South")) { yOrigin += 5; theCanvas.repaint(); }		else		if(s.equals("West")) { xOrigin -= 5; theCanvas.repaint(); }	}	private Vector<Rectangle> myCollection;	private int xOrigin;	private int yOrigin;	private Canvas theCanvas;}class MyCanvas extends Canvas {	public MyCanvas(DataObject d) { myData = d; setSize(400, 400); }	public void paint(Graphics g) { myData.paint(g); }	private DataObject myData;}class Display implements WindowListener {	public void windowClosing(WindowEvent e) { System.exit(0); }	public void windowClosed(WindowEvent e) { }	public void windowIconified(WindowEvent e) { }	public void windowOpened(WindowEvent e) { }	public void windowDeiconified(WindowEvent e) { }	public void windowActivated(WindowEvent e) { }	public void windowDeactivated(WindowEvent e) { }		public Display(DataObject d) 	{		theFrame = new Frame();		theFrame.setLayout(new FlowLayout());		theCanvas = new MyCanvas(d);		d.LinkToCanvas(theCanvas);		theFrame.add(theCanvas);		Button b;		b = new Button("North");		b.addActionListener(d);		theFrame.add(b);		b = new Button("East");		b.addActionListener(d);		theFrame.add(b);		b = new Button("South");		b.addActionListener(d);		theFrame.add(b);		b = new Button("West");		b.addActionListener(d);		theFrame.add(b);		theFrame.pack();		theFrame.addWindowListener(this);	}	public void show() { theFrame.setVisible(true); }	private Frame theFrame;	private MyCanvas theCanvas;}public class EventDemo1 {	public static void main(String args[])	{		DataObject aData;		Display aDisplay;		aData = new DataObject();		aDisplay = new Display(aData);		aDisplay.show();	}}

    In this example, the Display class owns an instance of the java.awt.Frame class (anequally good design would have the Display class defined as a subclass of the standardFrame class). The constructor of the Display class

    • creates the Frame object;
    • sets a Layout manager;
    • creates a MyCanvas object linked to the already existing data object (and setsthe reverse link from data object to canvas object);
    • adds the MyCanvas to the frame;
    • creates in turn each of the action buttons; the data object registers itselfas the thing ("call back object") responsible for handling any events generated bya mouseclick on each button;
    • makes itself responsible for handling WindowEvents.

    The display object is responsible for WindowEvents such as activation, deactivation, closing etc.So, it must implement the WindowListener interface. In this application, most window events(e.g. activation) are unimportant - so there are just empty methods defined (as WindowListeneris an interface, it is necessary to provide some definition for each method that it declares). The only operationthat matters is the window closing event - this signifies that the application should exit.

    There is another way in which these Window events could be handled. It would involvecreation of a WindowAdapter object. You will find this approach illustrated in textbookssuch as the Horstmann and Cornell Core Java reference. Code using a WindowAdapter is shorter -but a lot more obscure! You can try using Adapter classes in your exercises and assignments,but you are advised to stick to the simpler Listener style until you have more experiencewith Java.

    Compile the program, make sure it runs in NetBeans.

  2. Try creating a Swing graphics version of EventDemo1

    Change the code of the EventDemo1 program to use classes from the Swing library; at the same time,improve the layout by placing the action buttons inside an extra "Box" component (a Swing containerthat, coupled with a BoxLayout manager, can arrange components in neat vertical columns).

    You will need to change the code to use a JFrame instead of a Frame, and usea specialized JPanel subclass instead of a specialized Canvas subclass.

    The JFrame class has some limited functionality for handling Window events, so you willno longer need to have anything that implements WindowListener. You simply use a methodin JFrame that specifies what should be done when the close-box is clicked on a window(by default, the window is just hidden - you will need to change that behaviour toget the application to exit). You cannot add components directly to the JFrame objectitself - ask the JFrame to return a reference to its content pane and add subordinatecomponents to this.

    Your main hassles will be with the JPanel that you will have to substitute forAWT's Canvas class. Swing expects a JPanel to work out its size from the dimensionsof subordinate components - but here there are none, as simply requiring a componentin which one can draw application data. Since there are no subordinate components, Swingdecides the JPanel's size is zero (even if you invoke setSize()) and you won't see anything drawn.

    You can however set a "preferred size" for a JPanel and Swing will honor this setting. (You willfind some messy interfaces in the graphics classes. Some functions require Dimension objects, others require x- andy- coordinate values. It is very inconsistent. Things like Component and Containerwere among the first Java classes defined and there were inconsistencies - too much codenow depends on the existing interfaces so Sun can't clean them up and make anything better.)Although a JPanel with a preferred size will sometimes work, there are problems ifcomponents are re-sized (try replacing the inheritted Dimension getMinimumSize()method with one that returns the minimum size that you are prepared to use for your picture). There really isn't a good Swing equivalent to AWT Canvas(and don't try mixing Swing and AWT - that leads to some weird visual glitches).

    The other thing you will notice is that the drawing is incorrect. You will need toadd code that clears any existing data from the display before redrawing your data.

  3. Hand crafted Applet version

    The Applet version of the same example consists of the Java code and anassociated HTML page that has an <applet> tag.
    The DataObject and MyCanvas classes remain the same. The principal class is nowa subclass of Applet. It constructs the GUI components - since it is an Applet(and therefor a GUI container class), it adds these components to itself. Thereis no code for dealing with window events (because there is no separate windowand the browser will handle window events for the window in which the entirepage is displayed).
    public class EventDemo1Applet extends Applet {	public  void init()	{		DataObject aData = new DataObject();		this.setLayout(new FlowLayout());		MyCanvas aCanvas = new MyCanvas(aData);		aData.LinkToCanvas(aCanvas);		this.add(aCanvas);		Button b;		b = new Button("North");		b.addActionListener(aData);		this.add(b);		b = new Button("East");		b.addActionListener(aData);		this.add(b);		b = new Button("South");		b.addActionListener(aData);		this.add(b);		b = new Button("West");		b.addActionListener(aData);		this.add(b);	}}

    NetBeans will create a HTML page and run the Applet in appletviewer.A HTML page that uses this applet is:

    <html><head><title>Applet demo</title></head><body><h1>An applet</h1><p>HTML text will appear in a browserbut not when the page is displayed with appletviewer.</p><applet code="EventDemo1Applet.class"	width="500" height="500"></applet></body></html>

    Try building a "distribution" version of the Applet (in a Javaarchive .jar file) and running it with a browser.

    .

    In NetBeans the Applet should appear something like the following:

  4. JApplet

    Try to create a Swing Applet (JApplet) using the NetBeans GUI editor.

    This task is similar to that illustrated in the lecture notes exceptthat you will work with Swing classes rather than AWT classes.

    You should arrange that the DataObject monitors the buttons - not theJApplet itself.

    I found the GUI editor rather picky on this, it kept adding buttons toincorrect panels if I was off by a pixel. In the end, I created a JApplet;set its layout to BorderLayout; added a JPanel to "East" area; added the JButtonsto this panel, and only then changed the layout of the panel to BoxLayout. TheJButtons have "post create" code that adds the data object as an action listener.The main area of the JApplet is given to a "MyJPanel" (subclass of JPanel).;it needs special "create code" to instantiate it and link it to the data object.

    The generated code (open up initComponents to see it) involved some non-standardclasses. These are classes that the GUI editor uses to help it lay out GUIsthat it builds. If you want to deploy a JApplet built in this way, you haveto get a .jar file with the library containing these non-standardGUI classes.

  5. Mouse listening

    The following code illustrates a different kind of user interaction. TheColourPaletteTest program is a "mouse tracker" - every time the user moves themouse over the window an event is sent to the program. In this example, theprogram uses the mouse coordinates to identify the colour tile containing thepointer and then displays the colour name.

    The program is using ~100 standard colours and many standard shades of grey.These colours were standardized long ago (late 1980s) for X-window displays.Developers are generally encouraged to stick to this standard colour palette.

    The main program is:

    import java.awt.*;import java.awt.event.*;class MyCanvas extends Canvas implements MouseMotionListener {	public void mouseDragged(MouseEvent e) { }     	public void mouseMoved(MouseEvent e) {		int x = e.getX();		int y = e.getY();		int width =  getSize().width / 16;		int height = getSize().height / 16;		x /= width;		y /= height;		int which = 16*y + x;		if(which<ColourTable.colourcount) fName.setText(ColourTable.names[which]);		else fName.setText("xxxxxxxxxxxxxxxxxxxxxxxxxxxx");		}	public MyCanvas(Label l) 	{ fName = l; setSize(512,512); addMouseMotionListener(this);}	public void paint(Graphics g) {		int width = getSize().width / 16;		int height = getSize().height / 16;		int x = 0; 		int y = 0;		int col = 0;		for(int i=0; i < ColourTable.colourcount; i++) {			g.setColor(ColourTable.spectrum[i]);			g.fillRect(x,y, width, height);			g.setColor(Color.black);			g.drawRect(x,y, width, height);			x+=width; 			col++;			if(col==16) { x = 0; y+= height; col = 0; }			}		}	Label fName;}class GUI extends Frame implements WindowListener {	public void windowClosing(WindowEvent e) { System.exit(0); }	public void windowClosed(WindowEvent e) { }	public void windowIconified(WindowEvent e) { }	public void windowOpened(WindowEvent e) { }	public void windowDeiconified(WindowEvent e) { }	public void windowActivated(WindowEvent e) { }	public void windowDeactivated(WindowEvent e) { }		public GUI() {		super("Color Palette");		Panel p = new Panel();		p.add(new Label("color name "));		Label l = new Label("xxxxxxxxxxxxxxxxxxxxxxxxxxxx");		p.add(l);		add(p, "South");		fCanvas = new MyCanvas(l);		add(fCanvas, "Center");		pack();		addWindowListener(this);	}	private MyCanvas fCanvas;}public class ColourPaletteTest {	public static void main(String argv[]) {		GUI g = new GUI();		g.show();	}}
    The program structure is similar to the first version of the EventDemo programand will have to be reorganized to suit NetBeans (separate files for classesetc). Themain program constructs a GUI interface object and displays it. In this casethe GUI class is defined as a subclass of the generic Frame class. Its gets aBorderLayout by default. It has a label in the bottom field and a different MyCanvas object occupying most of the display area.

    Here the MyCanvas class handles the mouse events and deals with the datadisplay. "MouseDragged" events occur when the mouse is moved with a buttonheld down. "MouseMotion" events occur when the mouse is simply moved.Every mouse motion event returned to the listener contains mouse coordinates.

    The program relies on a static class - ColourTable:

    import java.awt.*;public class ColourTable {	static public Color[] spectrum = new Color[256];	static public String[] names = new String[256];	static public int colourcount;        static {		int i = 0;		spectrum[i] = new Color(255,250,250);  names[i] = new String("snow"); i++;		spectrum[i] = new Color(248,248,255);  names[i] = new String("ghost white"); i++;		spectrum[i] = new Color(245,245,245);  names[i] = new String("white smoke"); i++;		spectrum[i] = new Color(220,220,220);  names[i] = new String("gainsboro"); i++;		...		spectrum[i] = new Color(144,238,144);  names[i] = new String("light green"); i++;		colourcount = i;	}}

    The standard colours do have romanticised names like "white smoke". (The class uses astatic initializer block - probably the first one that you have seen. Remind yourselfas to the purpose of this construct.)

    A full listing of the class is available.

  6. Colour chooser

    Create a little Swing application that allows you to view any chosen color.(Actually, there is a Swing colour chooser class - after you have built this application, try using that class).

    The program should use a "pseudo-Canvas" class that extends JPanel and a "GUI" class that extends JFrame.The mainline program will create and show an instance of the GUI class.

    The GUI class will use a BorderLayout. The central area is used to display an instance of the"pseudo-Canvas" JPanel class. The "South" area holds a JButton; the GUI class itself acts asthe listener for this JButton. The "North" area should hold a JPanel within which there areJLabel and JTextField fields for red, green, and blue values.

    When the "Show Color" button is activated, the GUI object should handle the action event.Read the strings from the textfields for the red, green, and blue values. If data areerroneous (either cannot be converted to an integer, or integer value lies outside thepermitted range) use a JOptionPane to show an error message (look up JOptionPane - thedocumentation includes examples). If the data are valid, create a new Color objectand pass it to the "pseudo-canvas" JPanel object. Get the pseudo-canvas redrawn.

    The pseudo-canvas class fills its entire area with a chosen color. Initially, thisshould be Color.WHITE. It will be changed if valid data are entered via the GUI class.


Tabbed Pane (Swing)

The application for this demonstrationis supplied as a NetBeans project (in /share/cs-pub/csci213/Lab3).The project includes source code and a data file.The GUI interface classes were composed as code, they were not built usingthe GUI editor (the related exercise does require use of the GUI editor).

One common style of interface uses a "tabbed pane". The same main window is used for displaysof different data and controls. A set of "tabs" allows the user to select the particulardisplay form required.

This example has three tab-panes - "info", "messages", and "table".The program exists merely to illustrate tabbed panes (and a "table model" fora Swing JTable display) so it doesn't really do anything. The "info" pane hasan input field (used for a file name) and an action button. The "messages" paneis used to display any error messages. The "table" pane shows a tabular listingof data; the table is set to allow a single row to be selected, an action button causes a selected row to be printed.

The table supposedly shows suburbs and their postcodes. The necessary dataare read from a file, with format such as the fragment listed here:

Pyrmont:2009Mortdale:2223Kogarah:2217Gordon:2072St. Ives:2075Glebe:2037Lilyfield:2040Manly:2095Cremorne:2090

When the action button in the "info" pane is pressed, a file name is readfrom the textfield. The program then attempts to read data from the fileconstructing a vector of "AddressRecord" objects.

public class AddressRecord {	// Data fields intentionally public	public String suburb;	public String postcode;		public AddressRecord(String sub, String pc){		suburb = sub;		postcode = pc;	}}

The main program simply builds the interface:

public class TabPaneDemo {	public static void main(String[] args) {		try {					JFrame aFrame = new JFrame("Tab pane demo");			// Avoid using a window listener - built in functions in JFrame			// suffice			aFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );						ATabbedPaneThing displayComponent = new ATabbedPaneThing();				aFrame.getContentPane().add(displayComponent);			aFrame.setSize(new Dimension(500,500));			aFrame.show();	   }	   catch(Exception e) {		System.out.println("Failed because : " + e) ;	   }	}}

The program is run by the thread created in Java's graphic runtime system.

The "control and view" parts of the program are handled by a set of four classes- ATabbedPaneThing, InfoPanel, TablePanel, and MessagesPanel. The ATabbedPaneThingis the component that creates the tabbedpane structure, and its subordinate panels.It also handles actual input of data from a file and most of the work of switchingamong the panels - so it is really the principal control component. The MessagesPanelexists purely to view error messages. The InfoPanel and TablePanel have action buttonsand other input elements (a textfield and a table with selectable rows); these panelshandle their own inputs.

public class ATabbedPaneThing extends JPanel {	private JTabbedPane 		tabbedPane;	private MessagesPanel		mp;	private TablePanel		tp;	private	InfoPanel		ip;	public ATabbedPaneThing() {		// This JPanel subclass holds a "tabbed pane" that occupies		// entire panel (GridLayout(1,1) forces this).		// The tabbed pane displays itself as a set of "tabs"		// across top of panel; the rest of the panel is for the		// tab components.  Each tabcomponent is itself a specialized		// subclass of JPanel - InfoPanel, MessagesPanel or TablePanel;		tabbedPane = new JTabbedPane();		ip = new InfoPanel(this);		tabbedPane.addTab("Info", ip);	// index 0 - panel for text entry		mp = new MessagesPanel();		tabbedPane.addTab("Messages", mp); // index 1 - messages		tp = new TablePanel();		tabbedPane.addTab("Tabular data", tp); // index 2 - table		tabbedPane.setEnabledAt(2, false); // table not ready until have data		setLayout(new GridLayout(1, 1));		add(tabbedPane);			try {			tabbedPane.setSelectedComponent(ip);			}		catch(Exception e){}	}		public void switchToTable() {		try {			tabbedPane.setSelectedComponent(tp);			}		catch(Exception e){}	}		public void switchToMessages() {		try {			tabbedPane.setSelectedComponent(mp);			}		catch(Exception e){}	}		public MessagesPanel getMP() { 		return mp;	}		public TablePanel getTP() {		return tp;	}	public void tryLoadFile(String name)	{		try {			Vector<AddressRecord> newData = new Vector<AddressRecord>();			BufferedReader input = new BufferedReader(				new FileReader(name));			for(;;) {				String line = input.readLine();				if(line == null) break;				String[] parts = line.split(":");				AddressRecord arec = new AddressRecord(parts[0], parts[1]);				newData.add(arec);				tp.updateDataSet(newData);				tabbedPane.setEnabledAt(2, true); // can now tab to pane, though auto switch anyway				switchToTable();			}					}		catch(IOException ioe) {			tabbedPane.setEnabledAt(2, false); // table not ready until have valid data						mp.setMsgString("Unable to load file "				+ name +				" because " +				ioe.getMessage());			switchToMessages();		}	}}

The messages panel simply owns some text data that are displayed in a chosenfont. Mutator methods exist to change the text.

public class MessagesPanel extends JPanel{	public MessagesPanel() {		super();		Font myFont = new Font("Lucida Bright Demibold", Font.PLAIN, 18);		setLayout(new GridLayout(1,1));		txta = new JTextArea();		txta.setFont(myFont);		JScrollPane sp = new JScrollPane(txta);		add(sp);	}		public void setMsgString(String astr) { txta.setText(astr); }	public void appendMsgString(String astr)	{		txta.append(astr);	}		public void clear() { txta.setText(""); }		private JTextArea txta;    }

The Info panel has a text field and an action button. The Info panelhandles the action event from its action button by reading the textfieldand passing a request to the main control object to read a file.A GridBayLayout is used to center the textfield and actionbutton controlsin a resizable area - the code to setup the GridBagLayout constraints makesthis class fairly lengthy! (Each component added to thecontainer panel has to have "constraints" defining its positioning;these constraints define the grid squares that it occupies - here itis a grid 3 wide, 5 high. As well as defining the grid squares, theconstraints include information about how components are to be scaled if the window is resized, and how a component is actuallypositioned within its grid squares.)This is the kind of GUI coding that onewants to avoid - a place where the GUI builder becomes really useful.

public class InfoPanel extends JPanel implements ActionListener {	private ATabbedPaneThing	myGUI;	private JTextField	myTextField;	private JButton		myDoITButton;	public InfoPanel(ATabbedPaneThing atabpanegui) { 		myGUI=atabpanegui;		myTextField = new JTextField(8);		myDoITButton = new JButton("Do it");		GridBagLayout gbl = new GridBagLayout();		GridBagConstraints gbc = new GridBagConstraints();		setLayout(gbl);		// Layout has leftmost and rightmost columns as		// expandable blank areas, holding JPanels		JPanel leftPanel = new JPanel();		gbc.weightx = 100;		gbc.weighty = 100;		gbc.gridx = 0;		gbc.gridy = 0;		gbc.gridheight = 5;		gbc.gridwidth = 1;		gbc.anchor = GridBagConstraints.CENTER;		gbc.fill = GridBagConstraints.BOTH;		add(leftPanel, gbc);						JPanel topPanel = new JPanel();		gbc.weightx = 0;		gbc.weighty = 50;		gbc.gridx = 1;		gbc.gridy = 0;		gbc.gridheight = 1;		gbc.gridwidth = 1;		gbc.anchor = GridBagConstraints.CENTER;		gbc.fill = GridBagConstraints.VERTICAL;		add(topPanel, gbc);				JPanel rightPanel = new JPanel();		gbc.weightx = 100;		gbc.weighty = 100;		gbc.gridx = 2;		gbc.gridy = 0;		gbc.gridheight = 5;		gbc.gridwidth = 1;		gbc.anchor = GridBagConstraints.CENTER;		gbc.fill = GridBagConstraints.BOTH;		add(rightPanel, gbc);		JPanel bottomPanel = new JPanel();		gbc.weightx = 0;		gbc.weighty = 50;		gbc.gridx = 1;		gbc.gridy = 4;		gbc.gridheight = 1;		gbc.gridwidth = 1;		gbc.anchor = GridBagConstraints.CENTER;		gbc.fill = GridBagConstraints.VERTICAL;		add(bottomPanel, gbc);				JLabel lbl1 = new JLabel("File name");		gbc.weightx = 0;		gbc.weighty = 0;		gbc.gridx = 1;		gbc.gridy = 1;		gbc.gridheight = 1;		gbc.gridwidth = 1;		gbc.insets = new Insets(2,2,2,2);		gbc.anchor = GridBagConstraints.CENTER;		gbc.fill = GridBagConstraints.NONE;		add(lbl1, gbc);		gbc.weightx = 0;		gbc.weighty = 0;		gbc.gridx = 1;		gbc.gridy = 2;		gbc.gridheight = 1;		gbc.gridwidth = 1;		gbc.insets = new Insets(2,2,2,2);		gbc.anchor = GridBagConstraints.CENTER;		gbc.fill = GridBagConstraints.NONE;		add(myTextField, gbc);		gbc.weightx = 0;		gbc.weighty = 0;		gbc.gridx = 1;		gbc.gridy = 3;		gbc.gridheight = 1;		gbc.gridwidth = 1;		gbc.insets = new Insets(2,2,2,2);		gbc.anchor = GridBagConstraints.CENTER;		gbc.fill = GridBagConstraints.NONE;		add(myDoITButton, gbc);		myDoITButton.addActionListener(this);	}			public void actionPerformed(ActionEvent aev) {		String str = myTextField.getText();		if(str.equals("")) {			MessagesPanel mp = myGUI.getMP();			mp.setMsgString("You must supply a filename");			myGUI.switchToMessages();			return;			}		myGUI.tryLoadFile(str);			}    }

The table panel creates a JTable and sets options so that individual rows in a displayedtable can be selected. This panel also contains, and handles events from an action button.Here, a simple BorderLayout is used to allocate space for a scrollpane with the tableand an action button.

public class TablePanel extends JPanel implements ActionListener {    private JButton             selectButton;    private JScrollPane			sp;    private AddressDataTable	data;    private JTable				theTable;        public TablePanel(){		        data = new AddressDataTable();		theTable = new JTable(data);		theTable.setColumnSelectionAllowed(false);		theTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);		selectButton = new JButton("Print selected record");		selectButton.addActionListener(this);		sp = new JScrollPane(theTable);			setLayout(new BorderLayout());				add(sp, BorderLayout.CENTER);				add(selectButton, BorderLayout.SOUTH);	}	public void actionPerformed(ActionEvent aev) {		int selection = theTable.getSelectedRow();		if(selection<0) return;		data.printRow(selection);	}		public void updateDataSet(Vector<AddressRecord> v) { data.replaceData(v); }    }

The JTable class used to display data is generally useful - but there is a complication.You have to define a "table model" for your data (how else would the JTable code knowhow many columns there were, how many rows, etc etc). The table model also has to be given the data -as a collection of objects of some type (here, it is a Vector containing AddressRecordobjects).

public class AddressDataTable extends AbstractTableModel {	private static final String[]	columnNames = { "Suburb", "Postcode" };		private Vector<AddressRecord> data;	public int getRowCount() {             return data.size(); 	}        	public int getColumnCount() {             return 2; 	}        	public String getColumnName(int i) {             return columnNames[i]; 	}		public AddressDataTable()	{            data = new Vector<AddressRecord>();	}		public Object getValueAt(int row, int col) 	{            AddressRecord ar = data.elementAt(row);            String response = null;            switch(col) {                case 0: response = ar.suburb; break;				case 1: response = ar.postcode; break;            }            return response;	}		public void printRow(int row) {            AddressRecord ar = data.elementAt(row);            System.out.println(ar.suburb + "\t" +			ar.postcode);	}        	public void replaceData(Vector<AddressRecord> newData) { 		data = newData;		fireTableDataChanged(); 	} }

Exercise - variant tabbed pane application

Build a variation of the tabbed pane example. This version is tokeep a collection of records with name, initials, phone#. Obviously,some minor changes are needed to the table-model. The main changesare to be:

  1. A redesigned "InfoPanel" used to enter a file name.
  2. An extra panel - "DataEntryPanel" - that is used to enteradditional data. This is to have input fields for name, initials andphone number and an action button.
    When the action button is activated, the program updates its collectionof records. If there is an existing entry for the given name andinitials, the existing phone number is changed; the program thendisplays an acknowledgement in the messages panel. If the combinationof name and initials is new, an additional record is added to thecollection. Whenever the collection is changed, the file on diskis rewritten to contain the updated information.
  3. It will probably be useful to define a more elaborate datamodel than a simple Vector of records; you will want a class thatcan load data from a file and store data back to that file and whichcan add/update records.

The revised and new panels for the tabbed pane are to be builtusing the NetBeans GUI editor. You create JPanel forms in NetBeans,set a layout, and add components.

You have two choices - the default layout system that NetBeans supportsor use of GridBagLayout. The default layout system depends on non-standardclasses. An application built using these classes has to have an additional.jar file with these classes; this .jar file must be included in any version of the application that is deployed outside ofthe NetBeans IDE. Unfortunately, if you aren't very careful with your layout, even a GridBagLayoutbased approach draws in some of these non-standard classes.The default layout system is definitely easier to use; you can tryworking with GridBagLayout.

This image shows the revised InfoPanel being built with NetBeansand the default layout mechanisms:

Under the NetBeans Help menu, you will find links to tutorials. Oneof these illustrates use of the GUI builder with the default layout.