Sunday, September 26, 2010

Java Swing applet to calculate Fibonacci numbers

I understand this is a common skill builder in Java courses. To write this from scratch, you need to understand Swing input fields, layout management, action listeners, error trapping, and a little math. It also helps if you already think the Fibonacci sequence is cool.

So to help you seekers of assignment solutions, here you go. Study it, though, rather than just copying it wholesale. Maybe I'm not making this as streamlined as I should, or maybe the xor business is too much trouble for the modest speed and memory boost.

First, the working applet:



And the code behind it:

package cea.demos.fibonacci;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

@SuppressWarnings("serial")
// Swing applet to display Fibonacci numbers between a range of integers
public class Fibonacci extends JApplet implements ActionListener {
  // Declare form elements
  JLabel lowLabel, highLabel;
  JTextField lowText, highText;
  JButton button;
  JTextArea output;
  
  public void init() {
    // Set component positions by hand
    setLayout(null);
    
    // Instantiate form elements
    lowLabel = new JLabel("Lower Limit");
    highLabel = new JLabel("Upper Limit");
    lowText = new JTextField();
    highText = new JTextField();
    button = new JButton("Calculate");
    output = new JTextArea();

    // Set their locations
    lowLabel.setBounds(10, 10, 100, 20);
    lowText.setBounds(10, 30, 50, 20);
    highLabel.setBounds(150, 10, 100, 20);
    highText.setBounds(150, 30, 50, 20);
    button.setBounds(275, 20, 100, 20);
    output.setBounds(10, 60, 365, 100);

    // Set the text area to properly word wrap, disable it from user input,
    // and set its text color back to black
    output.setLineWrap(true);
    output.setWrapStyleWord(true);
    output.setEnabled(false);
    output.setDisabledTextColor(Color.BLACK);
    
    // Add them to the applet
    add(lowLabel);
    add(lowText);
    add(highLabel);
    add(highText);
    add(button);
    add(output);
    
    // Add action listeners to the button and the two text fields
    // (in case user just wants to hit enter after typing a number)
    button.addActionListener(this);
    lowText.addActionListener(this);
    highText.addActionListener(this);
  }
  
  // The main Fibonacci calculator
  private void calculate() {
    int low, high;
    // Make sure both text fields are filled in with numbers
    try {
      low = Integer.parseInt(lowText.getText());
      high = Integer.parseInt(highText.getText());
    } catch (NumberFormatException e) {
      output.setText("Both text fields must contain integers");
      return;
    }
    
    // Verify limits are both non-negative, and that "higher" is the larger.
    if (low < 0 || high < 0) {
      output.setText("Neither limit can be negative");
      return;
    }
    if (high <= low) {
      output.setText("Higher limit must be greater than lower limit");
    }
    
    // Init the first two numbers in the sequence, and the first line of output
    int current = 0;
    int next = 1;
    StringBuffer out = new StringBuffer
                ("Fibonacci sequence between " + low + " and " + high + ":\n");
    
    // "started" flag is used to check whether or not to add a comma before
    // printing the current item in the sequence. If started is false, you
    // haven't printed anything yet, so no comma is needed.
    boolean started = false;
    
    // Start calculating the sequence until the high limit is reached...
    while (current <= high) {
      // but don't start printing until the low limit is reached
      if (current >= low) {
        if (started) out.append(", ");
        else started = true;
        out.append(current);
      }
      // Add next to current, then use an xor swap to switch them. This avoids
      // using a third variable and the logic c = a + b, a = b, b = c.
      current += next;
      next ^= current;
      current ^= next;
      next ^= current;
    }
    
    // Finally, print the results in the text area
    output.setText(out.toString());
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    calculate();
  }

}

No comments:

Post a Comment