teaching machines

CS 145 Lecture 34 – Slideshow

December 7, 2016 by . Filed under cs145, fall 2016, lectures.

Dear students,

I’ve said several times that object-oriented design helps us organize our code. We can put code and the data that it regularly processes together into the same chunk. Objects allow for the separation of concerns. Class A can focus on its task, and be very good at it. It can be tested and perfected in isolation. Class B can focus on its task, and be very good at it. If the code for classes A and B were mixed together in class C, the developer’s brain would be pulled in different directions, and its quality would probably suffer.

So, when we model our problems with objects, we should make cohesive entities. Let’s see a particular occasion where the separation of concerns comes up: when writing an application with a graphical user interface. There are two tasks: to present a view to the user, and to model the data that’s being interacted with. As it turns out, view code tends to change a lot—we switch operating systems, windowing libraries, and so on. Model code tends to change less frequently. In addition to separating by concerns, we also like to “separate that which changes from that which doesn’t.”

Today, then, let’s write a slideshow application. We’ll start with the model, which knows nothing about presenting data. Once that’s in place, we’ll implement the view, which reads from the model and presents its data.

Here’s your TODO to complete before we meet again:

See you next class!

Sincerely,

P.S. Here’s the code we wrote together…

Model.java

package lecture1207;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import javax.imageio.ImageIO;

public class Model {
  private BufferedImage[] images;
  private File[] kids;
  private int bookmark;
  
  // ctor?
  public Model(File directory) throws IOException {
    kids = directory.listFiles();
    Arrays.sort(kids);
    images = new BufferedImage[kids.length];
    for (int i = 0; i < kids.length; ++i) {
      images[i] = ImageIO.read(kids[i]);
    }
    bookmark = 0;
  }
  
  public BufferedImage getCurrent() {
    return images[bookmark];
  }
  
  public void next() {
    bookmark = (bookmark + 1) % images.length;
  }
  
  public void previous() {
    bookmark = (bookmark + images.length - 1) % images.length;
  }
}

Slickshow.java

package lecture1207;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Slickshow extends JFrame {
  private Model model;
  private JLabel label;
  
  public Slickshow(Model model) {
    this.model = model;
    
    JButton nextButton = new JButton(">");
    JButton prevButton = new JButton("<");

    add(nextButton, BorderLayout.EAST);
    add(prevButton, BorderLayout.WEST);
    
    class NextListener implements ActionListener {
      public void actionPerformed(ActionEvent e) {
        model.next();
        label.setIcon(new ImageIcon(model.getCurrent()));

      }
    }
    nextButton.addActionListener(new NextListener());
    
    prevButton.addActionListener(e -> {
      model.previous();
      label.setIcon(new ImageIcon(model.getCurrent()));
    });

    label = new JLabel();
    label.setIcon(new ImageIcon(model.getCurrent()));
    add(label, BorderLayout.CENTER);
    
    setSize(800, 600);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setVisible(true);
  }
}

Main.java

package lecture1207;

import java.io.File;
import java.io.IOException;

public class Main {
  public static void main(String[] args) throws IOException {
    Model model = new Model(new File("/Users/johnch/Desktop/doscope"));
//    for (int i = 0; i < 10; ++i) {
//      System.out.println(model.getCurrent());
//      model.previous();
//    }
    Slickshow show = new Slickshow(model);
  }
}