Java Tutorial/Development/Applet

Материал из Java эксперт
Версия от 15:30, 31 мая 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Access applet parameters

import javax.swing.JApplet;
public class MainClass extends JApplet {
  public void init() {
    System.out.println(getParameter("text"));
  }
}





Add JButton to JApplet

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
public class MainClass extends JApplet {
  JButton button = new JButton("A very minimal applet");
  public void init() {
    System.out.println("parameter=" + getParameter("param"));
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        System.out.println("Button was clicked");
      }
    });
    getContentPane().add(button);
  }
}





An Swing-based applet skeleton

import javax.swing.*; 
 
/* 
This HTML can be used to launch the applet: 
 
<applet code="AppletSkel" width=300 height=100> 
</applet> 
 
*/ 
 
public class AppletSkel extends JApplet { 
  public void init() { 
    // Initialize the applet and construct the GUI. 
  } 
 
  // Called second, after init().  Also called whenever the applet is restarted.  
  public void start() { 
    // Start or resume execution. 
  } 
 
  // Called when the applet is stopped. 
  public void stop() { 
    // Suspend execution. 
  } 
 
  // Called when applet is terminated.  This is 
  // the last method executed. 
  public void destroy() { 
    // Perform shutdown activities. 
  } 
}





Applet

Without setting the security properly, an Applet

  1. Cannot have any access to files on the local computer.
  2. Cannot invoke any other program on the local computer.
  3. Cannot communicate with any computer other than the computer where it is from.

The following methods control the applet lifecycle.

MethodDescriptionvoid init()initialization. This method is called once when the applet starts execution.void start()starts the applet and is called immediately after init(). Also called if the user returns to the current .html page after leaving it.void stop()called when the user moves off the page containing the applet.void destroy()called after the stop() method when the browser is shut down.


A real applet

import javax.swing.JApplet;
public class MainApplet extends JApplet {
  public void init() {
    System.out.println("init");
  }
  public void start() {
    System.out.println("started");
  }
}





A simple Swing-based applet

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
 
/* 
This HTML can be used to launch the applet: 
 
<object code="MyApplet" width=240 height=100> 
</object> 
 
*/ 
 
public class MyApplet extends JApplet { 
  JButton jbtnOne; 
  JButton jbtnTwo; 
 
  JLabel jlab; 
 
  public void init() { 
    try { 
      SwingUtilities.invokeAndWait(new Runnable () { 
        public void run() { 
          guiInit(); // initialize the GUI 
        } 
      }); 
    } catch(Exception exc) { 
      System.out.println("Can"t create because of "+ exc); 
    } 
  } 
 
  // Called second, after init().  Also called 
  // whenever the applet is restarted.  
  public void start() { 
    // Not used by this applet. 
  } 
 
  // Called when the applet is stopped. 
  public void stop() { 
    // Not used by this applet. 
  } 
 
  // Called when applet is terminated.  This is 
  // the last method executed. 
  public void destroy() { 
    // Not used by this applet. 
  } 
 
  // Setup and initialize the GUI.  
  private void guiInit() { 
    // Set the applet to use flow layout. 
    setLayout(new FlowLayout()); 
 
    // Create two buttons and a label. 
    jbtnOne = new JButton("One"); 
    jbtnTwo = new JButton("Two"); 
 
    jlab = new JLabel("Press a button."); 
 
    // Add action listeners for the buttons. 
    jbtnOne.addActionListener(new ActionListener() {      
      public void actionPerformed(ActionEvent le) {  
        jlab.setText("Button One pressed.");  
      }      
    });      
 
    jbtnTwo.addActionListener(new ActionListener() {      
      public void actionPerformed(ActionEvent le) {  
        jlab.setText("Button Two pressed.");  
      }      
    });      
 
    // Add the components to the applet"s content pane. 
    getContentPane().add(jbtnOne); 
    getContentPane().add(jbtnTwo); 
    getContentPane().add(jlab);     
  } 
}





Calling methods of an Applet from JavaScript code

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Label;
public class Main extends Applet {
  private Label  m_mess = new Label("asdf", Label.CENTER);
  public void init() {
    add(BorderLayout.CENTER, m_mess);
  }
  public void setMessage(String message) {
    m_mess.setText("Selection : " + message);
  }
}   

<html>
<HEAD>
<TITLE>
JavaScript to Applet Communication
</TITLE >
<SCRIPT LANGUAGE="JavaScript">
function selectedCity() 
{
    document.SimpleMessageApplet.setMessage("hi");
}
</SCRIPT>
</HEAD>
<BODY >
<b>This is the Applet</b>
<br><br>
<APPLET CODE="MessageApplet.class" NAME="SimpleMessageApplet" WIDTH=350 HEIGHT=100 >
</APPLET >
</BODY >
</html>





Change an applet background color

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
public class Main extends Applet {
  public void init() {
    setBackground(Color.WHITE);
  }
  public void paint(Graphics g) {
    g.setColor(Color.BLACK);
    g.drawString("Applet background example", 0, 50);
  }
}





Display message in browser status bar

import java.applet.Applet;
public class Main extends Applet {
  public void init() {
    this.showStatus("asdf");
  }
  public void start() {
    
  }
  public void stop() {
  }
}





Mini Appletviewer

import java.applet.Applet;
import java.applet.AppletContext;
import java.applet.AppletStub;
import java.applet.AudioClip;
import java.awt.BorderLayout;
import java.awt.Image;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.Iterator;
import javax.swing.JFrame;
public class MinAppletviewer {
  public static void main(String args[]) throws Exception {
    AppSupport theAppSupport = new AppSupport();
    JFrame f = new JFrame();
    URL toload = new URL(args[0]);
    String host = toload.getHost();
    int port = toload.getPort();
    String protocol = toload.getProtocol();
    String path = toload.getFile();
    int join = path.lastIndexOf("/");
    String file = path.substring(join + 1);
    path = path.substring(0, join + 1);
    theAppSupport.setCodeBase(new URL(protocol, host, port, path));
    theAppSupport.setDocumentBase(theAppSupport.getCodeBase());
    URL[] bases = { theAppSupport.getCodeBase() };
    URLClassLoader loader = new URLClassLoader(bases);
    Class theAppletClass = loader.loadClass(file);
    Applet theApplet = (Applet) (theAppletClass.newInstance());
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.add(theApplet, BorderLayout.CENTER);
    theApplet.setStub(theAppSupport);
    f.setSize(200, 200);
    f.setVisible(true);
    theApplet.init();
    theApplet.start();
  }
}
class AppSupport implements AppletStub, AppletContext {
  private URL codeBase;
  private URL documentBase;
  public AppSupport() throws Exception {
    URL url = null;
    String urlpart = System.getProperty("user.dir");
    urlpart = urlpart.replace(File.separatorChar, "/");
    url = new URL("file://" + urlpart + "/");
    codeBase = documentBase = url;
  }
  public void appletResize(int w, int h) {
  }
  public AppletContext getAppletContext() {
    return (AppletContext) this;
  }
  public URL getDocumentBase() {
    return documentBase;
  }
  public void setDocumentBase(URL url) {
    documentBase = url;
  }
  public URL getCodeBase() {
    return codeBase;
  }
  public void setCodeBase(URL url) {
    codeBase = url;
  }
  public String getParameter(String s) {
    return null;
  }
  public boolean isActive() {
    return true;
  }
  public Applet getApplet(String name) {
    return null;
  }
  public Enumeration getApplets() {
    return new Enumeration() {
      public boolean hasMoreElements() {
        return false;
      }
      public Object nextElement() {
        return null;
      }
    };
  }
  public AudioClip getAudioClip(URL url) {
    return Applet.newAudioClip(url);
  }
  public Image getImage(URL url) {
    return Toolkit.getDefaultToolkit().getImage(url);
  }
  public void showDocument(URL url) {
  }
  public void showDocument(URL url, String target) {
  }
  public void showStatus(String status) {
    System.err.println(status);
  }
  public void setStream(String key, InputStream stream) throws IOException {
  }
  public InputStream getStream(String key) {
    return null;
  }
  public Iterator<String> getStreamKeys() {
    return null;
  }
}





Passing Parameters to Java Applet

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Label;
public class Main extends Applet {
  Label m_titleLabel = new Label(getParameter("Title"));
  public void init() {
    setLayout(new BorderLayout());
    add(BorderLayout.NORTH, m_titleLabel);
  }
}

<HTML>
<TITLE>
Writing and Running Java Applet, Demonstration
</TITLE>
<BODY>
<APPLET CODE="ParamApplet.class" WIDTH=600 HEIGHT=275 >
<PARAM NAME=Title VALUE="This is a Title String">
</APPLET>
</BODY>
</HTML>





Read an applet parameters

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
public class Main extends Applet {
  private String name = "";
  public void init() {
    name = getParameter("name");
  }
  public void paint(Graphics g) {
    g.setColor(Color.BLUE);
    g.drawString(name, 0, 0);
  }
} 
 
To enable the web browser to execute the applet create the following html page.
<html>
<head>
  <title>Parameterized Applet</title>
</head>
<body>
    <applet code="Main" height="150" width="350">
        <param name="name" value="abc" />
    </applet>
</body>
</html>





Swing Applet

import javax.swing.*;
public class HTMLLabelApplet extends JApplet {
  public void init() {
  
    JLabel theText = new JLabel(
     "<html>Hello! This is a multiline label with <b>bold</b> "
     + "and <i>italic</i> text. <P> "
     + "It can use paragraphs, horizontal lines, <hr> "
     + "<font color=red>colors</font> "
     + "and most of the other basic features of HTML 3.2</html>");
   
    this.getContentPane().add(theText);
  
  }
}





System properties accessible to applets

PropertyDescriptionfile.separatorFile separator (for example, "/")java.class.versionJava class version numberjava.vendorJava vendor-specific stringjava.vendor.urlJava vendor URLjava.versionJava version numberline.separatorLine separatoros.archOperating system architectureos.nameOperating system namepath.separatorPath separator (for example, ":")


Tic Tac Toe game

File: test.htm
<title>TicTacToe</title>
<hr>
<applet code=TicTacToe.class width=120 height=120>
</applet>

File: TicTacToe.java
/*
 * @(#)TicTacToe.java 1.2 95/10/13 
 *
 * Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
 * without fee is hereby granted. 
 * Please refer to the file http://java.sun.ru/copy_trademarks.html
 * for further important copyright and trademark information and to
 * http://java.sun.ru/licensing.html for further important licensing
 * information for the Java (tm) Technology.
 * 
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 * 
 * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
 * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
 * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
 * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
 * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
 * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
 * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  SUN
 * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
 * HIGH RISK ACTIVITIES.
 */
import java.awt.*;
import java.awt.image.*;
import java.net.*;
import java.applet.*;
/**
 * A TicTacToe applet. A very simple, and mostly brain-dead
 * implementation of your favorite game! 
 *
 * In this game a position is represented by a white and black
 * bitmask. A bit is set if a position is ocupied. There are
 * 9 squares so there are 1<<9 possible positions for each
 * side. An array of 1<<9 booleans is created, it marks
 * all the winning positions.
 *
 * @version   1.2, 13 Oct 1995
 * @author Arthur van Hoff
 * @modified 96/04/23 Jim Hagen : winning sounds
 */
public
class TicTacToe extends Applet {
    /**
     * White"s current position. The computer is white.
     */
    int white;
    /**
     * Black"s current position. The user is black.
     */
    int black;
    /**
     * The squares in order of importance...
     */
    final static int moves[] = {4, 0, 2, 6, 8, 1, 3, 5, 7};
    /**
     * The winning positions.
     */
    static boolean won[] = new boolean[1 << 9];
    static final int DONE = (1 << 9) - 1;
    static final int OK = 0;
    static final int WIN = 1;
    static final int LOSE = 2;
    static final int STALEMATE = 3;
    /**
     * Mark all positions with these bits set as winning.
     */
    static void isWon(int pos) {
  for (int i = 0 ; i < DONE ; i++) {
      if ((i & pos) == pos) {
    won[i] = true;
      }
  }
    }
    /**
     * Initialize all winning positions.
     */
    static {
  isWon((1 << 0) | (1 << 1) | (1 << 2));
  isWon((1 << 3) | (1 << 4) | (1 << 5));
  isWon((1 << 6) | (1 << 7) | (1 << 8));
  isWon((1 << 0) | (1 << 3) | (1 << 6));
  isWon((1 << 1) | (1 << 4) | (1 << 7));
  isWon((1 << 2) | (1 << 5) | (1 << 8));
  isWon((1 << 0) | (1 << 4) | (1 << 8));
  isWon((1 << 2) | (1 << 4) | (1 << 6));
    }
    /**
     * Compute the best move for white.
     * @return the square to take
     */
    int bestMove(int white, int black) {
  int bestmove = -1;
  
      loop:
  for (int i = 0 ; i < 9 ; i++) {
      int mw = moves[i];
      if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) {
    int pw = white | (1 << mw);
    if (won[pw]) {
        // white wins, take it!
        return mw;
    }
    for (int mb = 0 ; mb < 9 ; mb++) {
        if (((pw & (1 << mb)) == 0) && ((black & (1 << mb)) == 0)) {
      int pb = black | (1 << mb);
      if (won[pb]) {
          // black wins, take another
          continue loop;
      }
        }
    }
    // Neither white nor black can win in one move, this will do.
    if (bestmove == -1) {
        bestmove = mw;
    }
      }
  }
  if (bestmove != -1) {
      return bestmove;
  }
  // No move is totally satisfactory, try the first one that is open
  for (int i = 0 ; i < 9 ; i++) {
      int mw = moves[i];
      if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) {
    return mw;
      }
  }
  // No more moves
  return -1;
    }
    /**
     * User move.
     * @return true if legal
     */
    boolean yourMove(int m) {
  if ((m < 0) || (m > 8)) {
      return false;
  }
  if (((black | white) & (1 << m)) != 0) {
      return false;
  }
  black |= 1 << m;
  return true;
    }
    /**
     * Computer move.
     * @return true if legal
     */
    boolean myMove() {
  if ((black | white) == DONE) {
      return false;
  }
  int best = bestMove(white, black);
  white |= 1 << best;
  return true;
    }
    /**
     * Figure what the status of the game is.
     */
    int status() {
  if (won[white]) {
      return WIN;
  }
  if (won[black]) {
      return LOSE;
  }
  if ((black | white) == DONE) {
      return STALEMATE;
  }
  return OK;
    }
    /**
     * Who goes first in the next game?
     */
    boolean first = true;
    /**
     * The image for white.
     */
    Image notImage;
    /**
     * The image for black.
     */
    Image crossImage;
    /**
     * Initialize the applet. Resize and load images.
     */
    public void init() {
  notImage = getImage(getClass().getResource("images/not.gif"));
  crossImage = getImage(getClass().getResource("images/cross.gif"));
    }
    /**
     * Paint it.
     */
    public void paint(Graphics g) {
  Dimension d = getSize();
  g.setColor(Color.black);
  int xoff = d.width / 3;
  int yoff = d.height / 3;
  g.drawLine(xoff, 0, xoff, d.height);
  g.drawLine(2*xoff, 0, 2*xoff, d.height);
  g.drawLine(0, yoff, d.width, yoff);
  g.drawLine(0, 2*yoff, d.width, 2*yoff);
  int i = 0;
  for (int r = 0 ; r < 3 ; r++) {
      for (int c = 0 ; c < 3 ; c++, i++) {
    if ((white & (1 << i)) != 0) {
        g.drawImage(notImage, c*xoff + 1, r*yoff + 1, this);
    } else if ((black & (1 << i)) != 0) {
        g.drawImage(crossImage, c*xoff + 1, r*yoff + 1, this);
    }
      }
  }
    }
    /**
     * The user has clicked in the applet. Figure out where
     * and see if a legal move is possible. If it is a legal
     * move, respond with a legal move (if possible).
     */
    public boolean mouseUp(Event evt, int x, int y) {
  switch (status()) {
    case WIN:
    case LOSE:
    case STALEMATE:
      play(getClass().getResource("audio/return.au"));
      white = black = 0;
      if (first) {
    white |= 1 << (int)(Math.random() * 9);
      }
      first = !first;
      repaint();
      return true;
  }
  // Figure out the row/colum
  Dimension d = getSize();
  int c = (x * 3) / d.width;
  int r = (y * 3) / d.height;
  if (yourMove(c + r * 3)) {
      repaint();
      switch (status()) {
        case WIN:
    play(getClass().getResource("audio/yahoo1.au"));
    break;
        case LOSE:
    play(getClass().getResource("audio/yahoo2.au"));
    break;
        case STALEMATE:
    break;
        default:
    if (myMove()) {
        repaint();
        switch (status()) {
          case WIN:
      play(getClass().getResource("audio/yahoo1.au"));
      break;
          case LOSE:
      play(getClass().getResource("audio/yahoo2.au"));
      break;
          case STALEMATE:
      break;
          default:
      play(getClass().getResource("audio/ding.au"));
        }
    } else {
        play(getClass().getResource("audio/beep.au"));
    }
      }
  } else {
      play(getClass().getResource("audio/beep.au"));
  }
  return true;
    }
    public String getAppletInfo() {
  return "TicTacToe by Arthur van Hoff";
    }
}





WeatherWizard JApplet

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.ruposite;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JApplet;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class WeatherWizard extends JApplet implements ChangeListener {
  WeatherPainter painter;
  public void init() {
    /* Turn off metal"s use of bold fonts */
    UIManager.put("swing.boldMetal", Boolean.FALSE);
  }
  public void start() {
    initComponents();
  }
  public static void main(String[] args) {
    JFrame f = new JFrame("Weather Wizard");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JApplet ap = new WeatherWizard();
    ap.init();
    ap.start();
    f.add("Center", ap);
    f.pack();
    f.setVisible(true);
  }
  private BufferedImage loadImage(String name) {
    String imgFileName = "images/weather-" + name + ".png";
    URL url = WeatherWizard.class.getResource(imgFileName);
    BufferedImage img = null;
    try {
      img = ImageIO.read(url);
    } catch (Exception e) {
    }
    return img;
  }
  public void initComponents() {
    setLayout(new BorderLayout());
    JPanel p = new JPanel();
    p.add(new JLabel("Temperature:"));
    JSlider tempSlider = new JSlider(20, 100, 65);
    tempSlider.setMinorTickSpacing(5);
    tempSlider.setMajorTickSpacing(20);
    tempSlider.setPaintTicks(true);
    tempSlider.setPaintLabels(true);
    tempSlider.addChangeListener(this);
    p.add(tempSlider);
    add("North", p);
    painter = new WeatherPainter();
    painter.sun = loadImage("sun");
    painter.cloud = loadImage("cloud");
    painter.rain = loadImage("rain");
    painter.snow = loadImage("snow");
    painter.setTemperature(65);
    p.add("Center", painter);
  }
  public void stateChanged(ChangeEvent e) {
    JSlider slider = (JSlider) e.getSource();
    painter.setTemperature(slider.getValue());
  }
}
class WeatherPainter extends Component {
  int temperature = 65;
  String[] conditions = { "Snow", "Rain", "Cloud", "Sun" };
  BufferedImage snow = null;
  BufferedImage rain = null;
  BufferedImage cloud = null;
  BufferedImage sun = null;
  Color textColor = Color.yellow;
  String condStr = "";
  String feels = "";
  Composite alpha0 = null, alpha1 = null;
  BufferedImage img0 = null, img1 = null;
  void setTemperature(int temp) {
    temperature = temp;
    repaint();
  }
  public Dimension getPreferredSize() {
    return new Dimension(450, 125);
  }
  void setupText(String s1, String s2) {
    if (temperature <= 32) {
      textColor = Color.blue;
      feels = "Freezing";
    } else if (temperature <= 50) {
      textColor = Color.green;
      feels = "Cold";
    } else if (temperature <= 65) {
      textColor = Color.yellow;
      feels = "Cool";
    } else if (temperature <= 75) {
      textColor = Color.orange;
      feels = "Warm";
    } else {
      textColor = Color.red;
      feels = "Hot";
    }
    condStr = s1;
    if (s2 != null) {
      condStr += "/" + s2;
    }
  }
  void setupImages(BufferedImage i0) {
    alpha0 = null;
    alpha1 = null;
    img0 = i0;
    img1 = null;
  }
  void setupImages(int min, int max, BufferedImage i0, BufferedImage i1) {
    float alpha = (max - temperature) / (float) (max - min);
    alpha0 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
    alpha1 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1 - alpha);
    img0 = i0;
    img1 = i1;
  }
  void setupWeatherReport() {
    if (temperature <= 32) {
      setupImages(snow);
      setupText("Snow", null);
    } else if (temperature <= 40) {
      setupImages(32, 40, snow, rain);
      setupText("Snow", "Rain");
    } else if (temperature <= 50) {
      setupImages(rain);
      setupText("Rain", null);
    } else if (temperature <= 58) {
      setupImages(50, 58, rain, cloud);
      setupText("Rain", "Cloud");
    } else if (temperature <= 65) {
      setupImages(cloud);
      setupText("Cloud", null);
    } else if (temperature <= 75) {
      setupImages(65, 75, cloud, sun);
      setupText("Cloud", "Sun");
    } else {
      setupImages(sun);
      setupText("Sun", null);
    }
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    Dimension size = getSize();
    Composite origComposite;
    setupWeatherReport();
    origComposite = g2.getComposite();
    if (alpha0 != null)
      g2.setComposite(alpha0);
    g2.drawImage(img0, 0, 0, size.width, size.height, 0, 0, img0.getWidth(null), img0
        .getHeight(null), null);
    if (img1 != null) {
      if (alpha1 != null)
        g2.setComposite(alpha1);
      g2.drawImage(img1, 0, 0, size.width, size.height, 0, 0, img1.getWidth(null), img1
          .getHeight(null), null);
    }
    g2.setComposite(origComposite);
    // Freezing, Cold, Cool, Warm, Hot,
    // Blue, Green, Yellow, Orange, Red
    Font font = new Font("Serif", Font.PLAIN, 36);
    g.setFont(font);
    String tempString = feels + " " + temperature + "F";
    FontRenderContext frc = ((Graphics2D) g).getFontRenderContext();
    Rectangle2D boundsTemp = font.getStringBounds(tempString, frc);
    Rectangle2D boundsCond = font.getStringBounds(condStr, frc);
    int wText = Math.max((int) boundsTemp.getWidth(), (int) boundsCond.getWidth());
    int hText = (int) boundsTemp.getHeight() + (int) boundsCond.getHeight();
    int rX = (size.width - wText) / 2;
    int rY = (size.height - hText) / 2;
    g.setColor(Color.LIGHT_GRAY);
    g2.fillRect(rX, rY, wText, hText);
    g.setColor(textColor);
    int xTextTemp = rX - (int) boundsTemp.getX();
    int yTextTemp = rY - (int) boundsTemp.getY();
    g.drawString(tempString, xTextTemp, yTextTemp);
    int xTextCond = rX - (int) boundsCond.getX();
    int yTextCond = rY - (int) boundsCond.getY() + (int) boundsTemp.getHeight();
    g.drawString(condStr, xTextCond, yTextCond);
  }
}