Java Application Tutorial

Java Application Tutorial #5

I left you a little test last time - to add a textarea to our application. No need to change the main TestApp code but the myFrame code will look like this:-

class myFrame extends Frame
{
     private Dimension myDimension;
     private TextArea myTextArea=new TextArea(" ",25,80);

     myFrame(String Title)
     {
	super(Title);
	setLayout(new GridLayout(1,1));
	this.add(myTextArea);
        myDimension = new Dimension(200,200);
	myTextArea.appendText("This is copyright\n2004");

       	// menu's
	MenuBar mb = new MenuBar();
       	Menu m = new Menu("File");
       	m.add(new MenuItem("Exit"));
       	mb.add(m);
       	setMenuBar(mb);
     }

     public Dimension minimumSize()
     {
	return myDimension;
     }

     public Dimension preferredSize()
     {
	return myDimension;
     }

     public boolean handleEvent(Event ev)
     {
     	if (ev.id == Event.WINDOW_DESTROY)
     	{
		this.dispose();
		System.exit(0);
        	return true;
     	}

     	if (ev.id == Event.ACTION_EVENT)
     	{
		if (ev.target instanceof MenuItem)
		{
			if (ev.arg.equals("Exit"))
			{
		   		System.exit(0);
			}
		}
     	}
     	return super.handleEvent(ev);
     }
}

Some of this should look familiar. The TextArea code came from tutorial #1. Menu's were explained in Tutorial #4 and I have simply put them together. One piece of extra code is:-

myTextArea.appendText("This is copyright\n2004");

which simply adds a bit of code to the TextArea with the /n giving a newline or carriage return character so that the 2004 is displayed on the next line. This can be edited but will still be the same when the program is stopped and run again. This is now becoming very much like a text editor with only a small amount of code. It would of course be really nice if we could load and save text files. Even better if we could choose the files using common file dialogs that you will be familiar with already. No problem. Here is some code to do just that. To make it a little easier, I've split it into several parts. Here is the Save code.

class myFrame extends Frame
{
     private Dimension myDimension;
     TextArea myTextArea=new TextArea(" ",25,80);
     String gblFilename;
     String gblDirectory;

     myFrame(String Title)
     {
	super(Title);
	setLayout(new GridLayout(1,1));
	this.add(myTextArea);
      	myDimension = new Dimension(200,200);
	myTextArea.appendText("This is copyright\n2004");

     	// menu's
	MenuBar mb = new MenuBar();
     	Menu m = new Menu("File");
     	m.add(new MenuItem("Save"));
     	m.add(new MenuItem("Exit"));
     	mb.add(m);
     	setMenuBar(mb);
     }

     public Dimension minimumSize()
     {
	return myDimension;
     }

     public Dimension preferredSize()
     {
	return myDimension;
     }

     public boolean handleEvent(Event ev)
     {
     	if (ev.id == Event.WINDOW_DESTROY)
     	{
		this.dispose();
		System.exit(0);
        	return true;
     	}

     	if (ev.id == Event.ACTION_EVENT)
     	{
		if (ev.target instanceof MenuItem)
		{
			if (ev.arg.equals("Exit"))
			{
		   		System.exit(0);
			}


			if (ev.arg.equals("Save"))
			{
		     		FileDialog fd = new FileDialog(this, "Save this File");
				fd.setDirectory(gblDirectory);
                     		fd.setFile("untitled.txt");                   
                     		fd.show();

				if (fd.getFile() != null)
                     		{
					String filename=new String(fd.getDirectory() + fd.getFile());                   
					gblDirectory=fd.getDirectory();
					gblFilename=fd.getFile();
					try 
					{ 
                             			clsSaveFile save = new clsSaveFile(filename, myTextArea);
					}
                				catch (IOException e)
                			{
		             			System.err.println("IOException in Save menu");
		   			}
					setTitle(filename);
				}
			}

		}
	return super.handleEvent(ev);
	}
}


class clsSaveFile
{
     clsSaveFile(String FileName, TextArea myTextArea) throws IOException
     {
	FileOutputStream fos;
      	StringBuffer sb = new StringBuffer();
      	sb.append(myTextArea.getText());
      	int i;

	try 
	{
	     fos = new FileOutputStream(FileName);
             for (i=0; i < sb.length(); i++)
             fos.write(sb.charAt(i));
             fos.close();
	}
      	catch (IOException e)
      	{  
	     System.err.println ("IOException in clsSaveFile");
      	}
     }
}

This has 2 extra sections including a new class to do the saving and some code to handle when someone clicks Save on the menu and raises a dialog box. So an explanation is as follows:-

 		     		FileDialog fd = new FileDialog(this, "Save this File");
				fd.setDirectory(gblDirectory);
                     		fd.setFile("untitled.txt");                   
                     		fd.show();

When the menu is selected to Save, the first line will create a new dialog for us with some text that will appear at the top of the window to help the user understand what the dialog is for. This is a library function which means we don't have to write our own dialog (although you could if you really wanted to). We then set the current directory (or folder in Windows speak) and assign a filename which will be displayed in the dialog. The dialog is then displayed.

					try 
					{ 
                             			clsSaveFile save = new clsSaveFile(filename, myTextArea);
					}
                				catch (IOException e)
                			{
		             			System.err.println("IOException in Save menu");
		   			}
					setTitle(filename);

Don't worry too much about Exception code. The most important part is the line beginning clsSaveFile which is a call to the class further down which we'll come to in a moment. Finally, the filename is written to the top of the main window to replace untitled. Now the new class.

class clsSaveFile
{

Here is the new class created to save files.


     clsSaveFile(String FileName, TextArea myTextArea) throws IOException
     {

The class is given the filename taken from the dialog above and is also told what TextArea to use.

	FileOutputStream fos;
      	StringBuffer sb = new StringBuffer();
      	sb.append(myTextArea.getText());

The FileOutputSteam is another library function and we give it a name in this base fos. We then create a buffer that will contain the text currently held in the TextArea. We then take the text from the TextArea and feed it (or append it) into the buffer.


      	int i;

This strange command is very important so I'll take it slowly. int refers to a whole number (or integer)that doesn't contain a decimal point. So for example, 2.342 is not an int but 2342 is because it doesn't contain the decimal point. i is a name for an area of memory where we can store and integer number. So for example, i could hold the value 2342 in memory for us to use at a later date. Equally, it can be updated or changed to give some kind of countdown if we so wished. It is for this reason that it will be used further down in the for loop. Incidentally, this data storage area is known as a variable because it can vary. A variable that doesn't vary (cannot be changed) is called a constant. It has been placed here (or declared) to show the compiler that we intebd to use this further down in the program. The compiler would generate an error if we didn't decalre it and subsequently tried to use it.


	try 
	{

The code is surrounded by the try/catch exception just in case there is an error.


	     fos = new FileOutputStream(FileName);

A new FileOutputStream (note the case) is used to create a new file using the filename passed to it.


             for (i=0; i < sb.length(); i++)
             fos.write(sb.charAt(i));

This is a for loop. The variable i declared above initially holds the value zero. sb.length contains the length of the string held in the TextArea ignoring the fact that it is on seperate lines but includes any of the carriage return characters so we know where the lines break. At this point, the second command is invoked and a single character is written to the file. Then i is increase to 1 by the i++ which simply means to increase the count by one. Now the loop will stop and allow the writing of the nex character. This continues until all the charaters are writtn to the file. Take a moment to try and digest this as it is quite an important concept to grasp. So how does the loop know which line to invoke? As written, it will only use the line below it and no others. If you wanted to include more lines in the loop then it would need to look like this:-

for (i=0; i < sb.length(); i++)
{
      fos.write(sb.charAt(i));
      // more lines
}

The double slashes show the compiler that it is merely a comment made to aid the reading of code by humans and will be ignored byt the complier.


             fos.close();
	}
      	catch (IOException e)
      	{  
	     System.err.println ("IOException in clsSaveFile");
      	}
     }
}

Finally, once the loop has finished and all the letters have been written to the file, it is closed. The code is surrounded by the try/catch exception just in case there is an error (if it can't write to disk because the disk is full for example). That completes the Save operation. Next time, we'll load a text file into the TextArea for editing. Till then...

Back to Java Tutor

Written by Nick Cheesman. Last updated: 01/04/2004
Please eMail me at:
nickjc@nickjc.co.uk