public void actionPerformed(ActionEvent e) {
   if (e.getSource() == exitItem) {
     kbc.stopLoop();
     setVisible(false);
     dispose();
   } else if (e.getSource() == saveItem) {
     saveImage();
   } else if (e.getSource() == sleepItem1) {
     setDelay(1);
   } else if (e.getSource() == sleepItem2) {
     setDelay(2);
   } else if (e.getSource() == sleepItem5) {
     setDelay(5);
   } else if (e.getSource() == sleepItem10) {
     setDelay(10);
   } else if (e.getSource() instanceof JCheckBoxMenuItem) {
     JCheckBoxMenuItem jmi = (JCheckBoxMenuItem) e.getSource();
     String stat = jmi.getText();
     if (jmi.isSelected()) {
       kbc.addStatistic(stat);
     } else {
       kbc.removeStatistic(stat);
     }
   }
 }
 /**
  * Saves the current chart as an image in png format. The user can select the filename, and is
  * asked to confirm the overwrite of an existing file.
  */
 public void saveImage() {
   JFileChooser fc = new JFileChooser();
   if (fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
     File f = fc.getSelectedFile();
     if (f.exists()) {
       int ok =
           JOptionPane.showConfirmDialog(
               this,
               KstatResources.getString("SAVEAS.OVERWRITE.TEXT") + " " + f.toString(),
               KstatResources.getString("SAVEAS.CONFIRM.TEXT"),
               JOptionPane.YES_NO_OPTION);
       if (ok != JOptionPane.YES_OPTION) {
         return;
       }
     }
     BufferedImage bi = kbc.getChart().createBufferedImage(500, 300);
     try {
       ImageIO.write(bi, "png", f);
       /*
        * According to the API docs this should throw an IOException
        * on error, but this doesn't seem to be the case. As a result
        * it's necessary to catch exceptions more generally. Even this
        * doesn't work properly, but at least we manage to convey the
        * message to the user that the write failed, even if the
        * error itself isn't handled.
        */
     } catch (Exception ioe) {
       JOptionPane.showMessageDialog(
           this,
           ioe.toString(),
           KstatResources.getString("SAVEAS.ERROR.TEXT"),
           JOptionPane.ERROR_MESSAGE);
     }
   }
 }
  /**
   * Initialize the Frame.
   *
   * @param title the window title
   * @param statsMenu an optional menu listing available statistics
   */
  protected void init(String title, JMenu statsMenu) {
    setTitle(title);

    setContentPane(new ChartPanel(kbc.getChart()));

    addWindowListener(new winExit());

    JMenuBar jm = new JMenuBar();
    jm.add(fileMenu());
    if (!(jkstat instanceof SequencedJKstat)) {
      jm.add(sleepMenu());
    }
    if (statsMenu != null) {
      jm.add(statsMenu);
    }
    setJMenuBar(jm);

    pack();
    setVisible(true);
  }
 /**
  * Set the update delay of the chart.
  *
  * @param delay the desired update delay, in seconds
  */
 protected void setDelay(int delay) {
   kbc.setDelay(delay);
 }