Activity 15.6.1.
Try the Real Estate App below. Pull down the menu to try different choices.
ranch.txt
and ranch.gif
. The data file will store just the names of the files, one per line, giving it the following format:cape ranch colonial
JTextArea
?SlideShowFrame
solves the problem of downloading and displaying an image file. So, the most challenging part of this program is the task of downloading a Web text file and using its data in the program.JTextArea
. Downloading the image file can be handled in more or less the same way that it was handled in the SlideShowFrame
— by using a special Java method to download and display the image file.InputStream
and OutputStream
classes contained the read()
and write()
methods needed for I/O. The situation is the same for downloading Web files.URL
class contains the openStream()
method, which opens an InputStream
to the resource associated with the URL
. Once the stream has been opened, you can read data from the stream just as if it were coming from a file. The program doesn’t care whether the data are coming from a file on the Internet or a file on the disk. It just reads data from the stream. So, to download a data file from the Internet, regardless of whether it’s a text file, image file, audio file, or whatever, you would use the following general algorithm:InputStream data;
try {
URL url = new URL(fileURL); // Create a URL
data = url.openStream(); // Open a stream to URL
// READ THE FILE INTO MEMORY
data.close(); // Close the stream
} catch (MalformedURLException e) { // Thrown by URL()
System.out.println(e.getMessage());
} catch( IOException e ) {
System.out.println(e.getMessage()); // Thrown by openStream()
}
URL
instance.InputStream
to it.String
. If it’s an image or an audio file, we would read one byte
at a time.BufferedReader
class contains a readLine()
method that returns either a String
storing the line or the value null
when it reaches the end of file. The following method shows how you would read a text file into the program’s JTextArea
, which is named display
:private void readTextIntoDisplay(URL url)
throws IOException {
BufferedReader data
= new BufferedReader(
new InputStreamReader(url.openStream()));
display.setText(""); // Reset the text area
String line = data.readLine();
while (line != null) { // Read each line
display.append(line + "\n");// Add to display
line = data.readLine();
}
data.close();
}// readTextIntoDisplay()
URL.openStream()
method to open the input stream. Note that the method throws IOException , which means that any I/O exceptions that get raised will be handled by the calling method.display
. For our real estate application, the same basic algorithm can be used to read the names of the data files and store them in a menu from which a user makes selections. For example, if we use a JComboBox
menu named homeChoice
, we would simply add each line to it:String line = data.readLine();
while (line != null) {
homeChoice.addItem(line);
line = data.readLine();
}
JTextArea
, and the image can be drawn on a JPanel
.JComboBox
pull-down menu.JTextArea
all have their own region of the application’s window. This suggests a BorderLayout
, which is the default layout for a JFrame
. We can put the JComboBox
menu at the “North” border, and the image and text on the “West” and “East” borders, respectively. Figure 15.6.1 illustrates these various design decisions.RealEstateViewer
RealEstateViewer
, which will also handle the user interface (Figure 15.6.2). As the application’s top-level window, RealEstateViewer
will is subclass of JFrame
. Because its controls will include a JComboBox
, it must implement the itemStateChanged()
method of the ItemListener
interface.JComboBox
, a JTextArea
, and the ImagePanel
. Because it will be downloading images, it will need an Image
variable.RealEstateViewer
is shown in Listing 15.6.3. Note that the main()
method merely creates an instance of the application and shows it. Note also that the currentImage
variable is declared public
. This will let the ImagePanel
have direct access to currentImage
whenever it needs to display a new image.import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import javax.swing.*;
public class RealEstateViewer extends JFrame
implements ItemListener {
public static final int WIDTH=400,HEIGHT=200;
private final String dataFileURL =
"https://raw.githubusercontent.com/ram8647/javajavajava/master/chptr15/real-estate-app-resources/homes.txt";
private final String URLbase =
"https://raw.githubusercontent.com/ram8647/javajavajava/master/chptr15/real-estate-app-resources/";
private JTextArea display = new JTextArea(20,20);
private JComboBox homeChoice = new JComboBox();
private ImagePanel imagePanel = new ImagePanel(this);
public Image currentImage = null;
public RealEstateViewer () { } // Stub Constructor
// ItemListener interface
public void itemStateChanged(ItemEvent evt) { } // Stub
public static void main(String args[]) {
RealEstateViewer viewer = new RealEstateViewer();
viewer.setSize(viewer.WIDTH,viewer.HEIGHT);
viewer.setVisible(true);
viewer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}// main()
}// RealEstateViewer
RealEstateViewer
, Version 1.ImagePanel
Class
ImagePanel
, to handle displaying the image (Figure 15.6.4 and Listing 15.6.5).paintComponent()
method. This method will be called automatically whenever the main window is repainted. Its task is simply to get the current image from its parent frame and display it. Note that a reference to the parent frame is passed to the object in its constructor.import javax.swing.*;
import java.awt.*;
public class ImagePanel extends JPanel {
private RealEstateViewer frame;
public ImagePanel(RealEstateViewer parent) {
frame = parent;
}
public void paintComponent(Graphics g) {
if (frame.currentImage != null)
g.drawImage(frame.currentImage, 0, 0, this);
}
}// ImagePanel
ImagePanel
class.RealEstateViewer
(Listing 15.6.3) outline the main tasks required by the application. Some of these methods are very simple and even trivial to implement. Others should be broken up into subtasks.homeChoice
menu and setting up an appropriate layout that implements the design we developed for the user interface:public RealEstateViewer () {
super("Home Viewer Application");// Set window title
homeChoice.addItemListener( this);
this.getContentPane().add("North",homeChoice);
this.getContentPane().add("East",display);
this.getContentPane().add("Center",imagePanel);
display.setLineWrap(true);
initHomeChoices(); // Set up choice box
showCurrentSelection(); // Display current home
}
JComboBox
by reading its contents from a file stored in the company’s database. Because that task will require several statements, we define it as a separate method, initHomeChoices()
, and defer its development for now. Similarly, the task of displaying the current menu choice has been organized into the showCurrentSelection()
method, whose development we also defer for now.itemStateChanged()
method is called automatically when the user selects a home from the JComboBox
menu. Its task is to download and display information about the current menu selection. To do this, it can simply call the showCurrentSelection()
method:public void itemStateChanged(ItemEvent evt) {
showCurrentSelection();
}
initHomeChoices()
method downloads the text and uses its contents to set up the items in the homeChoice
JComboBox
menu:private void initHomeChoices() {
try {
URL url = new URL(dataFileURL);
BufferedReader data = new BufferedReader(
new InputStreamReader(url.openStream()));
String line = data.readLine();
while (line != null) {
homeChoice.addItem(line);
line = data.readLine();
}
data.close();
} catch (MalformedURLException e) {
System.out.println( "ERROR: " + e.getMessage());
} catch (IOException e) {
System.out.println( "ERROR: " + e.getMessage());
}
}// initHomeChoices()
readLine(data)
, it is added to the JComboBox
menu.showCurrentSelection()
method is responsible for downloading and displaying images and text files whenever the user selects a home to view. Recall that our specification called for using the name of the menu item as a basis for constructing the name of its corresponding text file and image file. Therefore, the basic algorithm we need isshowCurrentSelection()
itself. The showCurrentSelection()
method will create the URLs and then invoke the appropriate methods to download and display the resources:private void showCurrentSelection() {
URL url = null;
// Get user's choice
String choice = homeChoice.getSelectedItem().toString();
try { // Create url and download file
url = new URL(baseURL + choice + ".txt");
readTextIntoDisplay(url);
// Create url and download image
url = new URL(baseURL + choice + ".gif");
currentImage = ImageIO.read(url);
Toolkit.getDefaultToolkit().beep(); // Beep user
repaint();
} catch (MalformedURLException e) {
System.out.println( "ERROR: " + e.getMessage()) ;
} catch (IOException e) {
System.out.println("ERROR: " + e.getMessage()) ;
} // Try/catch block
} // showCurrentSelection()
MalformedURLException
and IOException
in this method. The advantage of this design is that it separates exception handling from the normal algorithm and organizes it into one method. Finally, note how string concatenation is used to build the URL specifications, each of which consists of three parts: the baseURL
, the user’s choice
, and the file extension.readTextIntoDisplay()
method. This private
utility method performs a standard file-reading algorithm using the readLine()
method that we developed earlier. Figure 15.6.6 provides a view of the program’s appearance as it is displaying information to a user. Listing 15.6.7 provides the complete implementation of this program.RealEstate- Viewer
App.import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
public class RealEstateViewer extends JFrame
implements ItemListener {
public static final int WIDTH=400,HEIGHT=200;
private final String dataFileURL =
"https://raw.githubusercontent.com/ram8647/javajavajava/master/chptr15/real-estate-app-resources/homes.txt";
private final String URLbase =
"https://raw.githubusercontent.com/ram8647/javajavajava/master/chptr15/real-estate-app-resources/";
private JTextArea display = new JTextArea(20,20);
private JComboBox homeChoice = new JComboBox();
private ImagePanel imagePanel = new ImagePanel(this); // use the ImagePanel class
public Image currentImage = null;
public RealEstateViewer () { // Constructor
super("Home Viewer Application"); // Set window title
homeChoice.addItemListener( this);
this.getContentPane().add("North",homeChoice);
this.getContentPane().add("East",display);
this.getContentPane().add("Center",imagePanel);
display.setLineWrap(true);
initHomeChoices(); // Set up the choice box
showCurrentSelection(); // Display the current home
} // RealEstateViewer()
private void initHomeChoices() {
try {
URL url = new URL(dataFileURL);
BufferedReader data = new BufferedReader(
new InputStreamReader(url.openStream()));
String line = data.readLine();
while (line != null) {
homeChoice.addItem(line);
line = data.readLine();
} data.close();
} catch (MalformedURLException e) {
System.out.println("ERROR: " + e.getMessage()) ;
} catch (IOException e) {
System.out.println("ERROR: " + e.getMessage()) ;
}
}// initHomeChoices()
private void readTextIntoDisplay(URL url) throws IOException {
BufferedReader data
= new BufferedReader(
new InputStreamReader(url.openStream()));
display.setText(""); // Reset the text area
String line = data.readLine();
while (line != null) { // Read each line
display.append(line + "\n"); // And add it to the display
line = data.readLine();
}
data.close();
}// readTextIntoDisplay()
private void showCurrentSelection() {
URL url = null; // Get user's choice
String choice = homeChoice.getSelectedItem().toString();
try {
url = new URL(baseURL + choice + ".txt") ; // Create URL
readTextIntoDisplay(url); // Download and display text file
url = new URL(baseURL + choice + ".gif"); // Create URL
// Download image
currentImage = ImageIO.read(url);
Toolkit.getDefaultToolkit().beep(); // Alert the user
repaint();
} catch (MalformedURLException e) {
System.out.println( "ERROR: " + e.getMessage()) ;
} catch (IOException e) {
System.out.println("ERROR: " + e.getMessage()) ;
}
}// showCurrentSelection()
public void itemStateChanged(ItemEvent evt) {
showCurrentSelection();
} // itemStateChanged()
public static void main(String args[]) {
RealEstateViewer viewer = new RealEstateViewer();
viewer.setSize(viewer.WIDTH,viewer.HEIGHT);
viewer.setVisible(true);
viewer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}// main()
}// RealEstateViewer
RealEstateViewer
classjavax.imageio.ImageIO.read()
method and other classes from the Java class library illustrate an important principle of object-oriented programming.ImageIO.read()
method. However, one skill or habit that you should try to develop is always to ask yourself the question: “Is there a method that will do what I’m trying to do here?” That question should be the first question on your search through the libraries and reference books.initHomeChoices()
: // instead of the arg. new InputStreamReader(url.openStream()
BufferedReader data = new BufferedReader(new FileReader(filename));
// catch FileNotFoundFoundException
readTextIntoDisplay(String filename)
and use the FileReader above, and use the File class to read in the image file in readTextIntoDisplay()
: // read in local file instead of url
File imageFile = new File(base + choice + ".jpg");
currentImage = ImageIO.read(imageFile);