Computer Science 210
Data Structures
Fall 2017, Siena College
RatioListApplet BlueJ Project
Click here to download a BlueJ project for RatioListApplet.
RatioListApplet Source Code
The Java source code for RatioListApplet is below. Click on a file name to download it.
// <applet code='RatioListApplet' width='400' height='450'></applet> /* * Example RatioListApplet: a simple Applet to manipulate * a RatioList - a list of Ratio objects * * Jim Teresco, The College of Saint Rose, CSC 523, Summer 2014 */ import java.awt.BorderLayout; import java.awt.Container; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BoxLayout; import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JSeparator; import javax.swing.JTextField; public class RatioListApplet extends JApplet implements ActionListener { // GUI components private JTextField displayNumerator, displayDenominator; private JButton insertButton, sumButton, minButton, maxButton, reduceButton, reduceAllButton, showAllButton; // our RatioList, which is null until the first is inserted private RatioList ratios; public void init() { Container contentPane = getContentPane(); // a bigger font for our display label and text fields Font biggerFont = new Font("Sans-Serif", Font.BOLD, 24); Font biggestFont = new Font("Fixed", Font.PLAIN, 48); // a JPanel for the center that displays the "current" ratio JPanel currentPanel = new JPanel(); JLabel currentLabel = new JLabel("Display value:"); currentLabel.setFont(biggerFont); currentPanel.add(currentLabel); // another JPanel to create the ratio display JPanel ratioPanel = new JPanel(); ratioPanel.setLayout(new BoxLayout(ratioPanel, BoxLayout.PAGE_AXIS)); displayNumerator = new JTextField("0", 5); displayNumerator.setFont(biggestFont); displayNumerator.setHorizontalAlignment(JTextField.CENTER); ratioPanel.add(displayNumerator); ratioPanel.add(new JSeparator()); displayDenominator = new JTextField("1", 5); displayDenominator.setFont(biggestFont); displayDenominator.setHorizontalAlignment(JTextField.CENTER); ratioPanel.add(displayDenominator); currentPanel.add(ratioPanel); contentPane.add(currentPanel, BorderLayout.CENTER); // a JPanel for the buttons across the bottom JPanel buttonPanel = new JPanel(new GridLayout(0, 1)); insertButton = setupButton("Insert Current", buttonPanel); sumButton = setupButton("Set Current to Sum", buttonPanel); minButton = setupButton("Set Current to Min", buttonPanel); maxButton = setupButton("Set Current to Max", buttonPanel); reduceButton = setupButton("Reduce Current to Lowest Terms", buttonPanel); reduceAllButton = setupButton("Reduce All to Lowest Terms", buttonPanel); showAllButton = setupButton("Show All Ratios", buttonPanel); contentPane.add(buttonPanel, BorderLayout.SOUTH); contentPane.validate(); } // a private method to create, insert, and set the listener for our buttons private JButton setupButton(String label, JPanel addTo) { JButton me = new JButton(label); addTo.add(me); me.addActionListener(this); return me; } // a private method to check if the contents of a JTextField represent a valid // integer value private static boolean isValidInt(JTextField f) { String text = f.getText(); try { Integer.parseInt(text); } catch (NumberFormatException e) { return false; } return true; } // helper method to display a given ratio in the display area private void displayRatio(Ratio r) { displayNumerator.setText(""+r.getNumerator()); displayDenominator.setText(""+r.getDenominator()); } // helper method to get a Ratio based on current contents of the text fields, // and returns null (after showing error dialog) if the fields are not valid // to construct a Ratio private Ratio ratioOfDisplay() { // we need to take the value on the display and create a new ratio out of it // we need to verify that the value displayed is valid to use as a ratio // first, check that the text fields have numbers in them boolean numValid = isValidInt(displayNumerator); boolean denValid = isValidInt(displayDenominator); String message = ""; if (!numValid) { message += "Could not parse numerator as an integer value!\n"; } if (!denValid) { message += "Could not parse denominator as an integer value!\n"; } if (!numValid || !denValid) { JOptionPane.showMessageDialog(null, message, "Invalid Entry", JOptionPane.ERROR_MESSAGE); return null; } // we know they're numbers, so let's get them int num = Integer.parseInt(displayNumerator.getText()); int den = Integer.parseInt(displayDenominator.getText()); // make sure we're not dividing by zero if (den == 0) { JOptionPane.showMessageDialog(null, "Denominator cannot be 0", "Invalid Entry", JOptionPane.ERROR_MESSAGE); return null; } // if we get here, things are good, construct and return a Ratio return new Ratio(num, den); } // handle all those button presses public void actionPerformed(ActionEvent e) { if (e.getSource() == insertButton) { // we need to take the value on the display and create a new ratio out of it // and add it to our collection Ratio newOne = ratioOfDisplay(); if (newOne != null) { // things are valid, so let's construct a Ratio and make it the new // first entry in our RatioList ratios = new RatioList(newOne, ratios); } } else if (e.getSource() == showAllButton) { // we just want to print out all of the ratios in our collection // so we'll put them up in a dialog box String message; if (ratios == null) { message = "No ratios in list."; } else { message = ratios.toString(); } JOptionPane.showMessageDialog(null, message); } else if (e.getSource() == sumButton) { // we need to compute the sum and display it if (ratios == null) { displayRatio(new Ratio(0,1)); } else { displayRatio(ratios.getSum()); } } else if (e.getSource() == minButton) { if (ratios == null) { JOptionPane.showMessageDialog(null, "No ratios in list."); } else{ displayRatio(ratios.getMin()); } } else if (e.getSource() == maxButton) { if (ratios == null) { JOptionPane.showMessageDialog(null, "No ratios in list."); } else { displayRatio(ratios.getMax()); } } else if (e.getSource() == reduceButton) { // get the Ratio from the display text fields Ratio displayed = ratioOfDisplay(); if (displayed != null) { displayed.reduce(); displayRatio(displayed); } } else if (e.getSource() == reduceAllButton) { if (ratios == null) { JOptionPane.showMessageDialog(null, "No ratios in list."); } else { ratios.reduceAll(); } } } }
/* * A recursive data structure (list) of Ratio objects with some * useful methods to manage such a list * * Jim Teresco, The College of Saint Rose, CSC 523, Summer 2014 * */ public class RatioList { // our instance variables have room for one Ratio, and // then a list of other ratios -- which is exactly // the structure we are defining -- so we can define this // structure *recursively* private Ratio first; private RatioList rest; // we construct a RatioList from a Ratio and another RatioList, // which would be null when constructing a brand new RatioList // with its first element public RatioList(Ratio first, RatioList rest) { this.first = first; this.rest = rest; } // a method to compute the sum of all ratios // it's recursive public Ratio getSum() { // if there is no rest, the sum is just first if (rest == null) return first; // otherwise, we have to compute the sum of the rest (using // this method) and then add in first, using Ratio's add method return first.add(rest.getSum()); } // to find the minimum ratio, we also use a recursive method. // the minimum is the smaller of first and the minimum of the rest, // which we compute using this method recursively public Ratio getMin() { // the smallest out of a single ratio is that ratio if (rest == null) return first; // otherwise, find the min of the rest and compare to first Ratio minOfRest = rest.getMin(); if (minOfRest.getDecimalValue() < first.getDecimalValue()) { return minOfRest; } else { return first; } } // max is the same idea public Ratio getMax() { // the largest out of a single ratio is that ratio if (rest == null) return first; // otherwise, find the max of the rest and compare to first Ratio maxOfRest = rest.getMax(); if (maxOfRest.getDecimalValue() > first.getDecimalValue()) { return maxOfRest; } else { return first; } } // reduce all Ratios in the list to lowest terms public void reduceAll() { // reduce the one Ratio we have first.reduce(); // and if there are more, reduce recursively if (rest != null) rest.reduceAll(); } // the toString method is recursive! To print this whole RatioList, // we concatenate the result of first's toString with a recursive // call to this toString method. But only do the latter when rest // is not null (we are not at the end of the list) public String toString() { String answer = first.toString(); if (rest != null) { answer += ", " + rest.toString(); } return answer; } }
/* * Example Ratios -- the Ratio class * * This class encapsulates a numerator and denominator and * includes the capability to set the numerator or denominator, * retrieve the numerator or denominator, retrieve the decimal * equivalent of the ratio, and return a "pretty" String * representation of the ratio * * This version includes a non-destructive method to add another * ratio to this and return a new ratio that contains the sum * * Jim Teresco, The College of Saint Rose, CSC 202, Fall 2012 * CSC 523, Summer 2014 * * $Id$ */ public class Ratio { // Instance variables for the two integers, one each for the numerator // and denominator. private int numerator; private int denominator; // our straightforward constructor public Ratio(int num, int den) { numerator = num; denominator = den; } // Mutators for numerator and denominator public void setNumerator(int num) { numerator = num; } public void setDenominator(int den) { denominator = den; } // And some accessors public int getNumerator() { return numerator; } public int getDenominator() { return denominator; } public double getDecimalValue() { return 1.0 * numerator / denominator; } // print our simple string representation public String toString() { return numerator + "/" + denominator; } // a non-destructive add method that adds another ratio to this // one and returns a new one (leaving this and other unchanged) public Ratio add(Ratio other) { return new Ratio(numerator*other.denominator + denominator*other.numerator, denominator*other.denominator); } // a recursive method to compute greatest common divisor using Euclid's method public static int gcd(int a, int b) { if (a == 0) return b; if (a > b) return gcd(b, a); // so below we can assume b>=a return gcd(b%a, a); } // Reduce this ratio to lowest terms. To do so, we find the greatest common // divisor of the numerator and denominator, then divide both // numerator and denominator by that value public void reduce() { int divideBy = gcd(numerator, denominator); numerator /= divideBy; denominator /= divideBy; } }