Subscribe to Martyr2's Programming Underground        RSS Feed
-----

Inheriting From A Control in Java

Icon 5 Comments
I am sure we all love Java Swing. It is not quite as thrilling as the swings we use to play on at the park, but it sure makes our Java applications come alive with a nice rich GUI. We are familiar with the JButton to make buttons, JTextFields to make textboxes and perhaps you have even ventured into using JTables. But maybe some of these controls have not gone far enough for you. Maybe you want to crack the whip on these controls and give them some extra super powers so they can go out and fight crime on the streets of DIC. We will grant the JTextArea control the power of file handling right here on the Programming Underground!

<Willy Wonka Chocolate River Boat theme music that could scare the bejeezes out of you>

For our little example we are going to have two class files. One is going to be our new class called "myTextBox" which is going to extend from a JTextArea control, but given a few extra functions to handle reading from and saving to a file. The second class is going to be simply a driver program (the main program which will use and test our new class).

What would a control like this be useful for? Well, have you ever thought of making a text editor that was tabbed so you could open multiple text documents at once? Maybe you have had experience with a program like TextPad or Notepad++. Instead of having to keep track of an array of files and which files are associated with which JTextArea controls used for editing them, using a class like this we can directly tie the file to the textarea editing it. Then it is just a matter of calling our method "Open" on the textarea to load a file into the control and calling "Save" on the textarea control to save its contents back to file. Very very handy.

Our control for all intents and purposes is an actual JTextArea control. It is a child of that control type. It just has a few added methods and a read only property. It will have the Open() method, to open a file and load its contents into the control, and a Save() method to take what is in the control and write it to its corresponding file. The property called getFileName() will simply provide the name of the file associated with that textarea control. Nice little property that you could use in a loop to know all the currently loaded files by iterating through the textarea controls you have open.

Here is what our control looks like....

import javax.swing.*;
import java.io.*;

// Our class extends the functionality of JTextArea
public class myTextBox extends JTextArea {
	private String aFileName;
	
	// Constructor (default parameterless)
	public myTextBox() {
		super();
		aFileName = "";
		setLineWrap(true);
	}
	
	// Constructor (parameterized)
	public myTextBox(String fileName) {
		super();
		if (fileName != null) {
			// File name was specified, so try and open it.
			Open(fileName);
		}
		setLineWrap(true);
	}
	
	// Opens a specified file name. This can be called from a constructor or from a direct call to the method "Open" on our control.
	public void Open(String fileName) {
		if (fileName != "") {
			
			aFileName = fileName;
			
			File f = new File(aFileName);
			
			// Does this file actually exist before we attempt to read it?
			if (f.exists()) {
				// Try catch in case we have an error opening or reading the file.
				try {
					BufferedReader buffRead = new BufferedReader(new FileReader(f));
					
					String line = "";
					
					// Clear the textbox before reading in a  new file.
					this.setText("");
					
					// Line by line we read from the text file and append that string to the textbox.
					while ((line = buffRead.readLine()) != null) {
						this.append(line);
					}
					buffRead.close();
				}
				catch (IOException ex) {
					JOptionPane.showMessageDialog(null,"Error reading file!", "File IO Error", JOptionPane.ERROR_MESSAGE);
				}
			}
			else { 
				JOptionPane.showMessageDialog(null, "File does not exist!", "File Not Found", JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	
	// Save what is in this control to the file specified in aFileName (saving it back to the file we opened).
	public void Save() {
		if (aFileName != null) {
			// Make sure we try catch here in case we have an error opening or saving the file.
			try {
				BufferedWriter buffWrite = new BufferedWriter(new FileWriter(aFileName));
				
				// Get what text is in the control and write it to the file. Then close it and tell the user the save is complete.
				buffWrite.write(this.getText());
				buffWrite.close();
				JOptionPane.showMessageDialog(null, "Save complete!", "Save Complete", JOptionPane.INFORMATION_MESSAGE);
			}
			catch (Exception ex) {
				JOptionPane.showMessageDialog(null, "Error saving file!", "File Save Error", JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	
	// Returns the file currently associated with this control.
	public String getFileName() {
		return aFileName;
	}
}



As always the code is well commented to help you step through the process. We start off by extending our new class from an existing JTextArea control. This is a class that has an "is a" relationship with JTextArea. Our textbox IS A type of JTextArea. Next we have two constructors. One is the default parameterless constructor. This constructor does nothing but call the constructor of the JTextArea parent, as well as setting our only member variable aFileName to an empty string.

The other constructor is the one we expect to use most of the time. It takes in a file name, tests to see if it exists, attempts to open it and read its contents into the control. We do this by opening the file using a BufferedReader, looping through its lines and appending each line to the control. When we are done we close the file. We also use this section of code to set our member variable aFileName to the name of the file specified. The file open method is also made public. This is in the event that the user wants to change the file this control is editing, it can simply call the open method again.

To augment this we have also provided a Save() method which will take whatever is in the control, open up the file specified in the aFileName variable and write its contents back to the file. It does this with a BufferedWriter class and writes whatever content is in the control to the file. For the programmer using our class, all they need to do is call the save method on the control instance itself. We demonstrate both the open and save functionality using a simple driver program below...

import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.event.*;

public class testMyTextBox extends JFrame implements ActionListener {
	// Here is a private reference to our new control
	private myTextBox mbox;
	
	// Constructor for this class
	public testMyTextBox() {
		setLayout(new BorderLayout());
		
		// Create an instance of our new control, giving it a file to open and load into it.
		mbox = new myTextBox("c:\\filetest.txt");
		
		// Create a button to activate a save of the contents.
		JButton button = new JButton("Save");
		button.addActionListener(this);
		
		// Add the controls to our JFrame
		add(mbox,BorderLayout.CENTER);
		add(button,BorderLayout.SOUTH);
	}
	
	// Our program starts here. We create our application, set its title size and show it when it is fully loaded.
	// Notice that by creating an instance of our app, the testMyTextBox() constructor is going to fire first
	// Which will load our new control and button onto the form prior to showing the JFrame.
	public static void main(String args[]) {
		testMyTextBox app = new testMyTextBox();
		app.setDefaultCloseOperation(EXIT_ON_CLOSE);
		app.setTitle("My New TextBox");
		app.setSize(300,300);
		app.setVisible(true);
	}
	
	// This is the beauty of our new control. When the user clicks the save button, all we have to do is call our method "Save"
	// on our new control and it will take care of the saving.
	public void actionPerformed(ActionEvent e) {
		mbox.Save();
	}
}



Nothing too fancy about this driver program. This program simply creates a JFrame which we set its title, size, default close operation and adds an instance of our new control to the center of the screen (using a border layout). In addition it adds a simple save button to the bottom. I am sure with a few tweaks you could turn this driver into something that could hold a satellite hostage for.... 1 MILLIONNNNN DOLLARSSSS! I mean... 100 BILLIONNNNN DOLLARSSSS!

The real magic is that we attach an actionListener to the button which will listen for a button click and trigger the save. When that click is received, all we have to do is call "Save" on any myTextBox objects we want to save. Each myTextBox can save to their individual files and all is great. This is encapsulation at its best! The programmer does not have to know a thing about what the control is doing under the hood, just that it can open and save files to and from the control.

If we wanted to get access to the file associated with the myTextBox control, we could have called the mbox.getFileName() method and it would return the file name and path specified in the initial Open() method call. Simple as that.

So look through the code and read the inline comments and I am sure it will make sense to you. Feel free to use this code any way you like and it is in the public domain... like all the code here on the Programming Underground is. Just please, don't use it to attack some small village in Tibet. They really have enough things to worry about than being fried from a satellite laser shot from space using this program. Enjoy and thanks for reading! :)

If you want more blog entries like this, check out the official blog over on The Coders Lexicon. There you will find more code, more guides and more resources for programmers of all skill levels!

5 Comments On This Entry

Page 1 of 1

tivrfoa Icon

16 April 2009 - 12:04 PM
I'm still reading, but I encountered myTextBox!! I don't know in what languange you are used to program but follow the convencions!

MyTextBox

=D
0

KYA Icon

16 April 2009 - 12:51 PM

tivrfoa, on 16 Apr, 2009 - 12:04 PM, said:

I'm still reading, but I encountered myTextBox!! I don't know in what languange you are used to program but follow the convencions!

MyTextBox

=D


I am partial to uppercase class names as well. I've seen them done both ways all over the place though.
0

tivrfoa Icon

16 April 2009 - 06:04 PM
Hi again :D

Nice post! Methods starting with uppercase :blink:

two things:
first: setLayout(new BorderLayout()) is unnecessary, because BorderLayout is the default layout of JFrames.

second: there's a little error in the code. You are not adding new lines!
Change to this:
while ((line = buffRead.readLine()) != null) {
this.append(line + "\n");
}
0

Martyr2 Icon

16 April 2009 - 07:45 PM
First of all, the goal of my blog has always been to bring code, and explanations, to the masses. Those masses tend to be learners and newbies. Given this, I often put in subtle changes here and there to make things easier to explain the topic at hand. Here I use some capitals on MY functions to help differentiate them from Java's functions. Makes it a little easier sometimes to tell the difference and reduce the confusion.

As for the layout manager, when you have a chance to future proof your project, why not? I think we had this little conversation before, never rely on a default unless you absolutely have to. One day Java could change that default and it will break all your apps. If you can throw in a line to help prevent a future change to a default, why not?

As for leaving out the new lines, I guess I could have put those in. But the idea here was to explain the principle of inheriting from a Java Swing control and often I leave out as much as possible to keep things nice and simple. I wouldn't consider this an error as much as a simple omission to simplify the idea.

Besides, the ultimate goal here is readability. So who cares if it is "Save" or "save" as long as the actual word "save" explains what it does and does it well. That and of course you are not going overboard with "sAvE". Never do I bash people for their case as long as they stick to it throughout the program and it is not erratic.

;)
0

tivrfoa Icon

16 April 2009 - 08:52 PM

Martyr2, on 16 Apr, 2009 - 06:45 PM, said:

First of all, the goal of my blog has always been to bring code, and explanations, to the masses. Those masses tend to be learners and newbies. Given this, I often put in subtle changes here and there to make things easier to explain the topic at hand. Here I use some capitals on MY functions to help differentiate them from Java's functions. Makes it a little easier sometimes to tell the difference and reduce the confusion.

interesting methodology :]

Martyr2, on 16 Apr, 2009 - 06:45 PM, said:

As for the layout manager, when you have a chance to future proof your project, why not? I think we had this little conversation before, never rely on a default unless you absolutely have to. One day Java could change that default and it will break all your apps. If you can throw in a line to help prevent a future change to a default, why not?

it would be very fun if the sun engineers make this change, and then all applications that were build don't work anymore. hey, but why they don't do this? BACKWARD COMPATIBILITY!!! hummmmm

Martyr2, on 16 Apr, 2009 - 06:45 PM, said:

As for leaving out the new lines, I guess I could have put those in. But the idea here was to explain the principle of inheriting from a Java Swing control and often I leave out as much as possible to keep things nice and simple. I wouldn't consider this an error as much as a simple omission to simplify the idea.

yeah ... a user open a file and see a data that doesn't represent the real data, i.e., wrong data ...

Martyr2, on 16 Apr, 2009 - 06:45 PM, said:

Besides, the ultimate goal here is readability. So who cares if it is "Save" or "save" as long as the actual word "save" explains what it does and does it well. That and of course you are not going overboard with "sAvE". Never do I bash people for their case as long as they stick to it throughout the program and it is not erratic.

;)

All my comments are for all learners and newbies (including me) become a better professional. Besides ... convention increase readability.
0
Page 1 of 1

September 2014

S M T W T F S
 1 2 3456
78910111213
14151617181920
21222324252627
282930