Put a NASA Photo into the Background of a Text Area





Put a NASA Photo into the Background of a Text Area

This hack will repurpose an existing web page, one of NASA's photo sites, by pulling their "Astronomy Picture of the Day" into the background of a text area.

You've already learned how to draw a watermark image in the background of a text area [Hack #6] using a ScrollPaneWatermark. This hack will pull a photo down from the Web and reuse that class to put the photo in the background. The photo itself comes from NASA's "Astronomy Picture of the Day" page: http://antwrp.gsfc.nasa.gov/apod/. The URL to the image changes each day, but the page itself does not. To pull the image down you will load the page, find the image URL, then load the image itself and put it into the ScrollPaneWatermark. Depending on the day, it may look something like Figure.

Text area with a background image


The code in Figure defines a class called BackgroundLoader, which implements Runnable so it can be placed on its own thread. The constructor takes as an argument the ScrollPaneWatermark, which the loader will put the image into. The run() method contains a loop that will run every two hours, loading the page, finding the SRC URL, then loading the image into the watermark.

A thread to load a background image
    public class BackgroundLoader implements Runnable {
	    private ScrollPaneWatermark watermark;
		public BackgroundLoader(ScrollPaneWatermark watermark) {
		    this.watermark = watermark;
		}	

		public void run() {
			while(true) {
			try { 
				String base_url = "http://antwrp.gsfc.nasa.gov/apod/"; 
				URL url = new URL(base_url);
				Reader input = new InputStreamReader(url.openStream());
				char buf[] = new char[1024];
				StringBuffer page_buffer = new StringBuffer();
				while(true) {

				int n = input.read(buf); 
				if(n < 0) { break; } 
				page_buffer.append(buf,0,n);
			}
			// Locate the Image URL (see next section)
			} catch (Exception ex) {
				System.out.println("exception: " + ex);
				ex.printStackTrace();

			} 
		} 
	} 
  }

First, you open the web page and load it into a page_buffer by looping through an InputStreamReader, copying the page data into a string buffer.

The Reader will take care of encoding issues so you don't need to worry about reading HTTP headers or converting to Unicode.


Page in hand, now you need to find the URL for the image itself. If you load the page into a web browser and view the page source, you will see that there is only a single IMG tag in the entire page. This makes the image very easy to find:

	Pattern pattern = Pattern.compile("<IMG SRC=\"(.*)\"");
	Matcher matcher = pattern.matcher(page_buffer);
	matcher.find();
	String img_url = base_url + matcher.group(1);
	
	watermark.setBackgroundTexture(new URL(img_url));
	watermark.repaint();

	Thread.currentThread().sleep(1000*60*60*2); 

First, you must create a Pattern object with a regex (regular expression) that matches the URL. You will notice in the previous code that there are parentheses around the .*. This is called a grouping. The matcher will store anything that matches the parentheses in a series of groups that you can query later. This lets you define exactly which part of the pattern you want to pull out. After creating a Matcher and calling find(), you can pull out the image URL with the line matcher.group(1), prepending it with the base URL for the page.

With the final image URL ready, just set the background texture for the watermark, refresh the screen, and then sleep for two hours. The calculation in the code (1000*60*60*2) evaluates to the number of milliseconds in a two-hour block of time. The page only changes once a day, but this way the change will be picked up sooner if the program is running overnight.

With all of the parts assembled, you can now create a main method, shown in Figure, that builds a simple text editor with the ScrollPaneWatermark to show the space image in the background.

Testing the space image background
	public static void main(String[] args) throws IOException { 
		JFrame frame = new JFrame("Blocking Window"); 
		JTextArea jta = new JTextArea(10,40); 
		jta.setForeground(Color.white);
		ScrollPaneWatermark viewport = new ScrollPaneWatermark();
		viewport.setView(jta);
		viewport.setOpaque(false);

		JScrollPane scroll = new JScrollPane();
		scroll.setViewport(viewport);

		Container comp = frame.getContentPane();
		comp.add("Center",scroll);

		frame.pack();
		frame.show();
		new Thread(new BackgroundLoader(viewport)).start(); }

The last line of the main( ) method starts a new thread to manage the background image.

Because the code is completely encapsulated in the BackgroundLoader class, you could add space images to a component that uses a scroll pane, not just a JTextArea.



     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows