Java/Swing JFC/Spinner — различия между версиями

Материал из Java эксперт
Перейти к: навигация, поиск
 
м (1 версия)
 
(нет различий)

Текущая версия на 06:39, 1 июня 2010

A date spinner

  
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
public class Main {
  public static void main(String[] argv) throws Exception {
    SpinnerDateModel dateModel = new SpinnerDateModel();
    JSpinner spinner = new JSpinner(dateModel);
    Calendar calendar = new GregorianCalendar(2000, Calendar.JANUARY, 1);
    spinner.setValue(calendar.getTime());
  }
}





A list spinner

  
import javax.swing.JSpinner;
import javax.swing.SpinnerListModel;
public class Main {
  public static void main(String[] argv) throws Exception {
    SpinnerListModel listModel = new SpinnerListModel(new String[] { "red","green", "blue" });
    JSpinner spinner = new JSpinner(listModel);
    spinner.setValue("blue");
  }
}





An example of JSpinner with a custom editor

  
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// MonthSpinner.java
//An example of JSpinner with a custom editor that allows the user to spin
//through dates of the mm/yy format.
//
import java.awt.Container;
import java.awt.FlowLayout;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
public class MonthSpinner extends JFrame {
  public MonthSpinner() {
    super("Month Spinner");
    setSize(200, 100);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    Container c = getContentPane();
    c.setLayout(new FlowLayout(FlowLayout.LEFT, 4, 4));
    c.add(new JLabel("Expiration Date:"));
    Date today = new Date();
    // Start the spinner today, but don"t set a min or max date
    // The increment should be a month
    JSpinner s = new JSpinner(new SpinnerDateModel(today, null, null,
        Calendar.MONTH));
    JSpinner.DateEditor de = new JSpinner.DateEditor(s, "MM/yy");
    s.setEditor(de);
    c.add(s);
    setVisible(true);
  }
  public static void main(String args[]) {
    new MonthSpinner();
  }
}





An implementation of JSpinner with customized content--icons

  
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// IconSpinner.java
//An implementation of JSpinner with customized content--icons in this case.
//A standard spinner model is used with a custom editor (IconEditor.java).
//
import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.SpinnerListModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class IconSpinner extends JFrame {
  public IconSpinner() {
    super("JSpinner Icon Test");
    setSize(300, 80);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    Container c = getContentPane();
    c.setLayout(new GridLayout(0, 2));
    Icon nums[] = new Icon[] { new ImageIcon("1.gif"),
        new ImageIcon("2.gif"), new ImageIcon("3.gif"),
        new ImageIcon("4.gif"), new ImageIcon("5.gif"),
        new ImageIcon("6.gif") };
    JSpinner s1 = new JSpinner(new SpinnerListModel(nums));
    s1.setEditor(new IconEditor(s1));
    c.add(new JLabel(" Icon Spinner"));
    c.add(s1);
    setVisible(true);
  }
  public static void main(String args[]) {
    new IconSpinner();
  }
}
class IconEditor extends JLabel implements ChangeListener {
  JSpinner spinner;
  Icon icon;
  public IconEditor(JSpinner s) {
    super((Icon) s.getValue(), CENTER);
    icon = (Icon) s.getValue();
    spinner = s;
    spinner.addChangeListener(this);
  }
  public void stateChanged(ChangeEvent ce) {
    icon = (Icon) spinner.getValue();
    setIcon(icon);
  }
  public JSpinner getSpinner() {
    return spinner;
  }
  public Icon getIcon() {
    return icon;
  }
}





A quick test of various spinners

  
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// SwingSpinnerTest.java
//A quick test of various spinners.
//
import java.awt.Container;
import java.awt.GridLayout;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
import javax.swing.SpinnerListModel;
import javax.swing.SpinnerNumberModel;
public class SwingSpinnerTest extends JFrame {
  public SwingSpinnerTest() {
    super("JSpinner Test");
    setSize(300, 180);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    Container c = getContentPane();
    c.setLayout(new GridLayout(0, 2));
    c.add(new JLabel(" Basic Spinner"));
    c.add(new JSpinner());
    c.add(new JLabel(" Date Spinner"));
    c.add(new JSpinner(new SpinnerDateModel()));
    String weekdays[] = new String[] { "Sunday", "Monday", "Tuesday",
        "Wednesday", "Thursday", "Friday", "Saturday" };
    c.add(new JLabel(" List Spinner"));
    c.add(new JSpinner(new SpinnerListModel(weekdays)));
    c.add(new JLabel(" Number Spinner"));
    c.add(new JSpinner(new SpinnerNumberModel(0, 0, 100, 5)));
    c.add(new JLabel(" Rollover List Spinner"));
    c.add(new JSpinner(new RolloverSpinnerListModel(weekdays)));
    setVisible(true);
  }
  public static void main(String args[]) {
    new SwingSpinnerTest();
  }
}
class RolloverSpinnerListModel extends SpinnerListModel {
  public RolloverSpinnerListModel(Object[] items) {
    super(items);
  }
  public RolloverSpinnerListModel(List items) {
    super(items);
  }
  public Object getNextValue() {
    Object nv = super.getNextValue();
    if (nv != null) {
      return nv;
    }
    return getList().get(0);
  }
  public Object getPreviousValue() {
    Object pv = super.getPreviousValue();
    if (pv != null) {
      return pv;
    }
    List l = getList();
    return l.get(l.size() - 1);
  }
}





A spinner of dates

  
import java.awt.FlowLayout;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
public class Main extends JFrame {
  public Main () {
    setSize(200, 100);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setLayout(new FlowLayout(FlowLayout.LEFT, 4, 4));
    add(new JLabel("Expiration Date:"));
    Date today = new Date();
    JSpinner s = new JSpinner(new SpinnerDateModel(today, null, null, Calendar.MONTH));
    JSpinner.DateEditor de = new JSpinner.DateEditor(s, "MM/yy");
    s.setEditor(de);
    add(s);
    setVisible(true);
  }
  public static void main(String args[]) {
    new Main();
  }
}





Create a spinner

  
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.plaf.basic.BasicArrowButton;
public class Spinner extends JPanel {
  private int orientation = SwingConstants.VERTICAL;
  private BasicArrowButton incrementButton;
  private BasicArrowButton decrementButton;
  public Spinner() {
    createComponents();
  }
  public Spinner(int o) {
    orientation = o;
    createComponents();
  }
  public void setEnabled(boolean enable) {
    incrementButton.setEnabled(enable);
    decrementButton.setEnabled(enable);
  }
  public boolean isEnabled() {
    return (incrementButton.isEnabled() && decrementButton.isEnabled());
  }
  protected void createComponents() {
    if (orientation == SwingConstants.VERTICAL) {
      setLayout(new GridLayout(2, 1));
      incrementButton = new BasicArrowButton(SwingConstants.NORTH);
      decrementButton = new BasicArrowButton(SwingConstants.SOUTH);
      add(incrementButton);
      add(decrementButton);
    } else if (orientation == SwingConstants.HORIZONTAL) {
      setLayout(new GridLayout(1, 2));
      incrementButton = new BasicArrowButton(SwingConstants.EAST);
      decrementButton = new BasicArrowButton(SwingConstants.WEST);
      add(decrementButton);
      add(incrementButton);
    }
  }
  public JButton getIncrementButton() {
    return (incrementButton);
  }
  public JButton getDecrementButton() {
    return (decrementButton);
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    JPanel panel = (JPanel) frame.getContentPane();
    panel.setLayout(new BorderLayout());
    JTextField field = new JTextField(20);
    Spinner spinner = new Spinner();
    panel.add(field, "Center");
    panel.add(spinner, "East");
    Dimension dim = frame.getToolkit().getScreenSize();
    frame.setLocation(dim.width / 2 - frame.getWidth() / 2, dim.height / 2
        - frame.getHeight() / 2);
    frame.pack();
    frame.show();
  }
}





Creating a JSpinner Component: A number spinner:

  
import javax.swing.JSpinner;
public class Main {
  public static void main(String[] argv) throws Exception {
    // Create a number spinner
    JSpinner spinner = new JSpinner();
    // Set its value
    spinner.setValue(new Integer(100));
  }
}





Creating an Hour JSpinner Component

  
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.swing.JFormattedTextField;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
import javax.swing.text.DateFormatter;
import javax.swing.text.DefaultFormatterFactory;
public class Main {
  public static void main(String[] argv) throws Exception {
    Calendar calendar = new GregorianCalendar();
    calendar.set(Calendar.HOUR_OF_DAY, 13); // 1pm
    SpinnerDateModel dateModel = new SpinnerDateModel(calendar.getTime(), null,
        null, Calendar.HOUR_OF_DAY);
    JSpinner spinner = new JSpinner(dateModel);
    JFormattedTextField tf = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField();
    DefaultFormatterFactory factory = (DefaultFormatterFactory) tf.getFormatterFactory();
    DateFormatter formatter = (DateFormatter) factory.getDefaultFormatter();
    // Change the date format to only show the hours
    formatter.setFormat(new SimpleDateFormat("hh:00 a"));
    //formatter.setFormat(new SimpleDateFormat("HH:00 a"));
  }
}





Creating a SpinnerListModel That Loops Through Its Values

  
import java.util.List;
import javax.swing.JSpinner;
import javax.swing.SpinnerListModel;
public class Main {
  public static void main(String[] argv) throws Exception {
    SpinnerCircularListModel listModel = new SpinnerCircularListModel(
        new String[] { "red", "green", "blue" });
    JSpinner spinner = new JSpinner(listModel);
  }
}
class SpinnerCircularListModel extends SpinnerListModel {
  public SpinnerCircularListModel(Object[] items) {
    super(items);
  }
  public Object getNextValue() {
    List list = getList();
    int index = list.indexOf(getValue());
    index = (index >= list.size() - 1) ? 0 : index + 1;
    return list.get(index);
  }
  public Object getPreviousValue() {
    List list = getList();
    int index = list.indexOf(getValue());
    index = (index <= 0) ? list.size() - 1 : index - 1;
    return list.get(index);
  }
}





Customizing the Editor in a JSpinner Component: Create a color spinner

  
import java.awt.Color;
import java.awt.Dimension;
import java.lang.reflect.Field;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerListModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main {
  public static void main(String[] argv) throws Exception {
    ColorSpinner spinner = new ColorSpinner(new String[] { "red", "green","blue" });
   spinner.setValue("blue");
  }
}
class ColorSpinner extends JSpinner {
  public ColorSpinner(String[] colorNames) {
    super();
    setModel(new SpinnerListModel(colorNames));
    setEditor(new Editor(this));
  }
  public class Editor extends JPanel implements ChangeListener {
    int preferredWidth = 30;
    int preferredHeight = 16;
    Editor(JSpinner spinner) {
      spinner.addChangeListener(this);
      setPreferredSize(new Dimension(preferredWidth, preferredHeight));
      setColor((String) spinner.getValue());
    }
    public void stateChanged(ChangeEvent evt) {
      JSpinner spinner = (JSpinner) evt.getSource();
      String value = (String) spinner.getValue();
      setColor(value);
    }
    public void setColor(String colorName) {
      try {
        Field field = Class.forName("java.awt.Color").getField(colorName);
        Color color = (Color) field.get(null);
        setBackground(color);
      } catch (Exception e) {
      }
    }
  }
}





Date spinner

  
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
import javax.swing.SpinnerListModel;
import javax.swing.SpinnerNumberModel;
public class Main extends JFrame {
  public Main() {
    JSpinner m_dateSpinner;
    SpinnerDateModel m_dateSpinnerModel;
    Calendar rightNow = Calendar.getInstance();
    Date current = rightNow.getTime();
    rightNow.set(Calendar.HOUR_OF_DAY, -24);
    Date start = rightNow.getTime();
    rightNow.set(Calendar.HOUR_OF_DAY, 48);
    Date end = rightNow.getTime();
    int step = Calendar.HOUR_OF_DAY;
    m_dateSpinnerModel = new SpinnerDateModel(current, start, end, step);
    m_dateSpinner = new JSpinner(m_dateSpinnerModel);
    add(m_dateSpinner);
  }
  public static void main(String argv[]) {
    Main spinnerFrame = new Main();
    spinnerFrame.setSize(350, 200);
    spinnerFrame.setVisible(true);
  }
}





Demonstrate the Swing Spinner control

  
import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.*;
/**
 * Demonstrate the Swing "Spinner" control.
 * @author ian
 */
public class SpinnerDemo {
  public static void main(String[] args) {
    JFrame jf = new JFrame("It Spins");
    Container cp = jf.getContentPane();
    cp.setLayout(new GridLayout(0,1));
    // Create a JSpinner using one of the pre-defined SpinnerModels
    JSpinner dates = new JSpinner(new SpinnerDateModel());
    cp.add(dates);
    // Create a JSPinner using a SpinnerListModel. 
    String[] data = { "One", "Two", "Three" };
    JSpinner js = new JSpinner(new SpinnerListModel(data));
    cp.add(js);
    jf.setSize(100, 80);
    jf.setVisible(true);
  }
}





Demonstrating the JSpinner Component

  
import java.awt.BorderLayout;
import java.awt.Container;
import java.util.Calendar;
import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
import javax.swing.SpinnerListModel;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
public class SpinnerTest {
  public static void main(String args[]) {
    JFrame frame = new JFrame("Spinning");
    Container contentPane = frame.getContentPane();
    String months[] = { "January", "February", "March", "April", "May",
        "June", "July", "August", "September", "October", "November",
        "December" };
    SpinnerModel model = new SpinnerListModel(months);
    JSpinner spinner = new JSpinner(model);
    contentPane.add(spinner, BorderLayout.NORTH);
    SpinnerDateModel model2 = new SpinnerDateModel();
    model2.setCalendarField(Calendar.WEEK_OF_MONTH);
    JSpinner spinner2 = new JSpinner(model2);
    JSpinner.DateEditor editor2 = new JSpinner.DateEditor(spinner2,
        "MMMMM dd, yyyy");
    spinner2.setEditor(editor2);
    frame.getContentPane().add(spinner2, BorderLayout.CENTER);
    SpinnerNumberModel model3 = new SpinnerNumberModel(50, 0, 100, 5);
    JSpinner spinner3 = new JSpinner(model3);
    frame.getContentPane().add(spinner3, BorderLayout.SOUTH);
    frame.setSize(200, 100);
    frame.show();
  }
}





Disabling Keyboard Editing in a JSpinner Component

  
import java.awt.Color;
import javax.swing.JFormattedTextField;
import javax.swing.JSpinner;
public class Main {
  public static void main(String[] argv) throws Exception {
    JSpinner spinner = new JSpinner();
    // Disable keyboard edits in the spinner
    JFormattedTextField tf = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField();
    tf.setEditable(false);
    tf.setBackground(Color.white);
    // The value of the spinner can still be programmatically changed
    spinner.setValue(new Integer(100));
  }
}





Enhanced Spinner List Formatter

  

import java.text.ParseException;
import java.util.Arrays;
import java.util.List;
import javax.swing.JFormattedTextField;
import javax.swing.SpinnerListModel;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
/**
 * Copyright 2007 Brandon Goodin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * ListFormatter provides completion while text is being input
 * into the JFormattedTextField.rupletion is only done if the
 * user is inserting text at the end of the document.rupletion
 * is done by way of the SpinnerListModel method findNextMatch.
 * This is largely a copy of the SpinnerListFormatter found in
 * JDK 1.5 sources. A new version was written because the JDK
 * version was not extensible and did not allow for the ability
 * to ehance the stringToValue.
 *
 * The stringToValue was enhanced to iterate through the model
 * list and compare the String values of the list objects and
 * the string value passed to the formatter. The first equal
 * will return. So, if multiple objects have the same toString
 * value, only the first will be returned.
 */
public class EnhancedSpinnerListFormatter extends
    JFormattedTextField.AbstractFormatter {
  private DocumentFilter filter;
  private EnhancedSpinnerListModel model;

  public EnhancedSpinnerListFormatter(EnhancedSpinnerListModel model) {
    this.model = model;
  }
  public String valueToString(Object value) throws ParseException {
    if (value == null) {
      return "";
    }
    return value.toString();
  }
  public Object stringToValue(String string) throws ParseException {
    for (Object item : model.getList()) {
      if (item.toString().equals(string)) return item;
    }
    return null;
  }
  protected DocumentFilter getDocumentFilter() {
    if (filter == null) {
      filter = new Filter();
    }
    return filter;
  }

  private class Filter extends DocumentFilter {
    public void replace(FilterBypass fb, int offset, int length,
              String string, AttributeSet attrs) throws
        BadLocationException {
      if (string != null && (offset + length) ==
          fb.getDocument().getLength()) {
        Object next = model.findNextMatch(
            fb.getDocument().getText(0, offset) +
                string);
        String value = (next != null) ? next.toString() : null;
        if (value != null) {
          fb.remove(0, offset + length);
          fb.insertString(0, value, null);
          getFormattedTextField().select(offset +
              string.length(),
              value.length());
          return;
        }
      }
      super.replace(fb, offset, length, string, attrs);
    }
    public void insertString(FilterBypass fb, int offset,
                 String string, AttributeSet attr)
        throws BadLocationException {
      replace(fb, offset, 0, string, attr);
    }
  }
}


/**
 * Copyright 2007 Brandon Goodin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * This is a pretty much a direct copy of the SpinnerListModel from JDK 1.5 sources.
 * It was copied out in order to expose methods that needed to be publicly available
 * in order to allow for completion to work properly with a list of complex objects
 * that present their human readable value from a toString(). The findNextMatch
 * method was exposed as public.
 */
class EnhancedSpinnerListModel extends SpinnerListModel {
  private List list;
    private int index;

    /**
     * Constructs a <code>SpinnerModel</code> whose sequence of
     * values is defined by the specified <code>List</code>.
     * The initial value (<i>current element</i>)
     * of the model will be <code>values.get(0)</code>.
     * If <code>values</code> is <code>null</code> or has zero
     * size, an <code>IllegalArugmentException</code> is thrown.
     *
     * @param values the sequence this model represents
     * @throws IllegalArugmentException if <code>values</code> is
     *                                  <code>null</code> or zero size
     */
    @SuppressWarnings({"JavadocReference"})
    public EnhancedSpinnerListModel(List<?> values) {
      if (values == null || values.size() == 0) {
        throw new IllegalArgumentException("SpinnerListModel(List) expects non-null non-empty List");
      }
      this.list = values;
      this.index = 0;
    }

    /**
     * Constructs a <code>SpinnerModel</code> whose sequence of values
     * is defined by the specified array.  The initial value of the model
     * will be <code>values[0]</code>.  If <code>values</code> is
     * <code>null</code> or has zero length, an
     * <code>IllegalArugmentException</code> is thrown.
     *
     * @param values the sequence this model represents
     * @throws IllegalArugmentException if <code>values</code> is
     *                                  <code>null</code> or zero length
     */
    @SuppressWarnings({"JavadocReference"})
    public EnhancedSpinnerListModel(Object[] values) {
      if (values == null || values.length == 0) {
        throw new IllegalArgumentException("SpinnerListModel(Object[]) expects non-null non-empty Object[]");
      }
      this.list = Arrays.asList(values);
      this.index = 0;
    }

    /**
     * Constructs an effectively empty <code>SpinnerListModel</code>.
     * The model"s list will contain a single
     * <code>"empty"</code> string element.
     */
    public EnhancedSpinnerListModel() {
      this(new Object[]{"empty"});
    }

    /**
     * Returns the <code>List</code> that defines the sequence for this model.
     *
     * @return the value of the <code>list</code> property
     * @see #setList
     */
    public List<?> getList() {
      return list;
    }

    /**
     * Changes the list that defines this sequence and resets the index
     * of the models <code>value</code> to zero.  Note that <code>list</code>
     * is not copied, the model just stores a reference to it.
     * <p/>
     * This method fires a <code>ChangeEvent</code> if <code>list</code> is
     * not equal to the current list.
     *
     * @param list the sequence that this model represents
     * @throws IllegalArgumentException if <code>list</code> is
     *                                  <code>null</code> or zero length
     * @see #getList
     */
    public void setList(List<?> list) {
      if ((list == null) || (list.size() == 0)) {
        throw new IllegalArgumentException("invalid list");
      }
      if (!list.equals(this.list)) {
        this.list = list;
        index = 0;
        fireStateChanged();
      }
    }

    /**
     * Returns the current element of the sequence.
     *
     * @return the <code>value</code> property
     * @see javax.swing.SpinnerModel#getValue
     * @see #setValue
     */
    public Object getValue() {
      return list.get(index);
    }

    /**
     * Changes the current element of the sequence and notifies
     * <code>ChangeListeners</code>.  If the specified
     * value is not equal to an element of the underlying sequence
     * then an <code>IllegalArgumentException</code> is thrown.
     * In the following example the <code>setValue</code> call
     * would cause an exception to be thrown:
     * <pre>
     * String[] values = {"one", "two", "free", "four"};
     * SpinnerModel model = new SpinnerListModel(values);
     * model.setValue("TWO");
     * </pre>
     *
     * @param elt the sequence element that will be model"s current value
     * @throws IllegalArgumentException if the specified value isn"t allowed
     * @see javax.swing.SpinnerModel#setValue
     * @see #getValue
     */
    public void setValue(Object elt) {
      int index = list.indexOf(elt);
      if (index == -1) {
        throw new IllegalArgumentException("invalid sequence element");
      } else if (index != this.index) {
        this.index = index;
        fireStateChanged();
      }
    }

    /**
     * Returns the next legal value of the underlying sequence or
     * <code>null</code> if value is already the last element.
     *
     * @return the next legal value of the underlying sequence or
     *         <code>null</code> if value is already the last element
     * @see javax.swing.SpinnerModel#getNextValue
     * @see #getPreviousValue
     */
    public Object getNextValue() {
      return (index >= (list.size() - 1)) ? null : list.get(index + 1);
    }

    /**
     * Returns the previous element of the underlying sequence or
     * <code>null</code> if value is already the first element.
     *
     * @return the previous element of the underlying sequence or
     *         <code>null</code> if value is already the first element
     * @see javax.swing.SpinnerModel#getPreviousValue
     * @see #getNextValue
     */
    public Object getPreviousValue() {
      return (index <= 0) ? null : list.get(index - 1);
    }

    /**
     * Returns the next object that starts with <code>substring</code>.
     *
     * @param substring the string to be matched
     * @return the match
     */
    public Object findNextMatch(String substring) {
      int max = list.size();
      if (max == 0) {
        return null;
      }
      int counter = index;
      do {
        Object value = list.get(counter);
        String string = value.toString();
        if (string != null && string.startsWith(substring)) {
          return value;
        }
        counter = (counter + 1) % max;
      } while (counter != index);
      return null;
    }
}





Enhanced Spinner List Model

  
import java.util.Arrays;
import java.util.List;
import javax.swing.SpinnerListModel;

/**
 * Copyright 2007 Brandon Goodin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * This is a pretty much a direct copy of the SpinnerListModel from JDK 1.5 sources.
 * It was copied out in order to expose methods that needed to be publicly available
 * in order to allow for completion to work properly with a list of complex objects
 * that present their human readable value from a toString(). The findNextMatch
 * method was exposed as public.
 */
public class EnhancedSpinnerListModel extends SpinnerListModel {
  private List list;
    private int index;

    /**
     * Constructs a <code>SpinnerModel</code> whose sequence of
     * values is defined by the specified <code>List</code>.
     * The initial value (<i>current element</i>)
     * of the model will be <code>values.get(0)</code>.
     * If <code>values</code> is <code>null</code> or has zero
     * size, an <code>IllegalArugmentException</code> is thrown.
     *
     * @param values the sequence this model represents
     * @throws IllegalArugmentException if <code>values</code> is
     *                                  <code>null</code> or zero size
     */
    @SuppressWarnings({"JavadocReference"})
    public EnhancedSpinnerListModel(List<?> values) {
      if (values == null || values.size() == 0) {
        throw new IllegalArgumentException("SpinnerListModel(List) expects non-null non-empty List");
      }
      this.list = values;
      this.index = 0;
    }

    /**
     * Constructs a <code>SpinnerModel</code> whose sequence of values
     * is defined by the specified array.  The initial value of the model
     * will be <code>values[0]</code>.  If <code>values</code> is
     * <code>null</code> or has zero length, an
     * <code>IllegalArugmentException</code> is thrown.
     *
     * @param values the sequence this model represents
     * @throws IllegalArugmentException if <code>values</code> is
     *                                  <code>null</code> or zero length
     */
    @SuppressWarnings({"JavadocReference"})
    public EnhancedSpinnerListModel(Object[] values) {
      if (values == null || values.length == 0) {
        throw new IllegalArgumentException("SpinnerListModel(Object[]) expects non-null non-empty Object[]");
      }
      this.list = Arrays.asList(values);
      this.index = 0;
    }

    /**
     * Constructs an effectively empty <code>SpinnerListModel</code>.
     * The model"s list will contain a single
     * <code>"empty"</code> string element.
     */
    public EnhancedSpinnerListModel() {
      this(new Object[]{"empty"});
    }

    /**
     * Returns the <code>List</code> that defines the sequence for this model.
     *
     * @return the value of the <code>list</code> property
     * @see #setList
     */
    public List<?> getList() {
      return list;
    }

    /**
     * Changes the list that defines this sequence and resets the index
     * of the models <code>value</code> to zero.  Note that <code>list</code>
     * is not copied, the model just stores a reference to it.
     * <p/>
     * This method fires a <code>ChangeEvent</code> if <code>list</code> is
     * not equal to the current list.
     *
     * @param list the sequence that this model represents
     * @throws IllegalArgumentException if <code>list</code> is
     *                                  <code>null</code> or zero length
     * @see #getList
     */
    public void setList(List<?> list) {
      if ((list == null) || (list.size() == 0)) {
        throw new IllegalArgumentException("invalid list");
      }
      if (!list.equals(this.list)) {
        this.list = list;
        index = 0;
        fireStateChanged();
      }
    }

    /**
     * Returns the current element of the sequence.
     *
     * @return the <code>value</code> property
     * @see javax.swing.SpinnerModel#getValue
     * @see #setValue
     */
    public Object getValue() {
      return list.get(index);
    }

    /**
     * Changes the current element of the sequence and notifies
     * <code>ChangeListeners</code>.  If the specified
     * value is not equal to an element of the underlying sequence
     * then an <code>IllegalArgumentException</code> is thrown.
     * In the following example the <code>setValue</code> call
     * would cause an exception to be thrown:
     * <pre>
     * String[] values = {"one", "two", "free", "four"};
     * SpinnerModel model = new SpinnerListModel(values);
     * model.setValue("TWO");
     * </pre>
     *
     * @param elt the sequence element that will be model"s current value
     * @throws IllegalArgumentException if the specified value isn"t allowed
     * @see javax.swing.SpinnerModel#setValue
     * @see #getValue
     */
    public void setValue(Object elt) {
      int index = list.indexOf(elt);
      if (index == -1) {
        throw new IllegalArgumentException("invalid sequence element");
      } else if (index != this.index) {
        this.index = index;
        fireStateChanged();
      }
    }

    /**
     * Returns the next legal value of the underlying sequence or
     * <code>null</code> if value is already the last element.
     *
     * @return the next legal value of the underlying sequence or
     *         <code>null</code> if value is already the last element
     * @see javax.swing.SpinnerModel#getNextValue
     * @see #getPreviousValue
     */
    public Object getNextValue() {
      return (index >= (list.size() - 1)) ? null : list.get(index + 1);
    }

    /**
     * Returns the previous element of the underlying sequence or
     * <code>null</code> if value is already the first element.
     *
     * @return the previous element of the underlying sequence or
     *         <code>null</code> if value is already the first element
     * @see javax.swing.SpinnerModel#getPreviousValue
     * @see #getNextValue
     */
    public Object getPreviousValue() {
      return (index <= 0) ? null : list.get(index - 1);
    }

    /**
     * Returns the next object that starts with <code>substring</code>.
     *
     * @param substring the string to be matched
     * @return the match
     */
    public Object findNextMatch(String substring) {
      int max = list.size();
      if (max == 0) {
        return null;
      }
      int counter = index;
      do {
        Object value = list.get(counter);
        String string = value.toString();
        if (string != null && string.startsWith(substring)) {
          return value;
        }
        counter = (counter + 1) % max;
      } while (counter != index);
      return null;
    }
}





Java Spinner Component

Limiting the Values in a Number JSpinner Component

  
import javax.swing.JSpinner;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
public class Main {
  public static void main(String[] argv) throws Exception {
    // Create a number spinner that only handles values in the range [0,100]
    int min = 0;
    int max = 100;
    int step = 5;
    int initValue = 50;
    SpinnerModel model = new SpinnerNumberModel(initValue, min, max, step);
    JSpinner spinner = new JSpinner(model);
  }
}





List based spinner

  
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerListModel;
public class Main extends JFrame {
  public Main() {
    JSpinner m_listSpinner;
    SpinnerListModel m_listSpinnerModel;
    List<String> sequence = new ArrayList<String>();
    sequence.add(new String("I - First"));
    sequence.add(new String("II - Second"));
    sequence.add(new String("III - Third"));
    sequence.add(new String("IV - Fourth"));
    sequence.add(new String("V - Fifth"));
    sequence.add(new String("VI - Sixth"));
    m_listSpinnerModel = new SpinnerListModel(sequence);
    m_listSpinner = new JSpinner(m_listSpinnerModel);
    add(m_listSpinner);
  }
  public static void main(String argv[]) {
    Main spinnerFrame = new Main();
    spinnerFrame.setSize(350, 200);
    spinnerFrame.setVisible(true);
  }
}





Listening for Changes to the Value in a JSpinner Component

  
import javax.swing.JSpinner;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main {
  public static void main(String[] argv) throws Exception {
    JSpinner spinner = new JSpinner();
    spinner.addChangeListener(new SpinnerListener());
    spinner.setValue(new Integer(100));
  }
}
class SpinnerListener implements ChangeListener {
  public void stateChanged(ChangeEvent evt) {
    JSpinner spinner = (JSpinner) evt.getSource();
    // Get the new value
    Object value = spinner.getValue();
  }
}





Number spinner

  
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
import javax.swing.SpinnerListModel;
import javax.swing.SpinnerNumberModel;
public class Main extends JFrame {
  public Main() {
    JSpinner m_numberSpinner;
    SpinnerNumberModel m_numberSpinnerModel;
    Double current = new Double(5.50);
    Double min = new Double(0.00);
    Double max = new Double(10.00);
    Double step = new Double(0.25);
    m_numberSpinnerModel = new SpinnerNumberModel(current, min, max, step);
    m_numberSpinner = new JSpinner(m_numberSpinnerModel);
    add(m_numberSpinner);
  }
  public static void main(String argv[]) {
    Main spinnerFrame = new Main();
    spinnerFrame.setSize(350, 200);
    spinnerFrame.setVisible(true);
  }
}





Setting the Margin Space on a JSpinner Component

  
import java.awt.Insets;
import javax.swing.JFormattedTextField;
import javax.swing.JSpinner;
public class Main {
  public static void main(String[] argv) throws Exception {
    JSpinner spinner = new JSpinner();
    // Get the text field
    JFormattedTextField tf = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField();
    // Set the margin (add two spaces to the left and right side of the value)
    int top = 0;
    int left = 2;
    int bottom = 0;
    int right = 2;
    Insets insets = new Insets(top, left, bottom, right);
    tf.setMargin(insets);
  }
}





Spinner 2

  
/*
Swing, Second Edition
by Matthew Robinson, Pavel Vorobiev
*/
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.plaf.basic.BasicArrowButton;
public class Spinner extends JPanel {
  private int m_orientation = SwingConstants.VERTICAL;
  private BasicArrowButton m_incrementButton;
  private BasicArrowButton m_decrementButton;
  public Spinner() {
    createComponents();
  }
  public Spinner(int orientation) {
    m_orientation = orientation;
    createComponents();
  }
  public void setEnabled(boolean enable) {
    m_incrementButton.setEnabled(enable);
    m_decrementButton.setEnabled(enable);
  }
  public boolean isEnabled() {
    return (m_incrementButton.isEnabled() && m_decrementButton.isEnabled());
  }
  protected void createComponents() {
    if (m_orientation == SwingConstants.VERTICAL) {
      setLayout(new GridLayout(2, 1));
      m_incrementButton = new BasicArrowButton(SwingConstants.NORTH);
      m_decrementButton = new BasicArrowButton(SwingConstants.SOUTH);
      add(m_incrementButton);
      add(m_decrementButton);
    } else if (m_orientation == SwingConstants.HORIZONTAL) {
      setLayout(new GridLayout(1, 2));
      m_incrementButton = new BasicArrowButton(SwingConstants.EAST);
      m_decrementButton = new BasicArrowButton(SwingConstants.WEST);
      add(m_decrementButton);
      add(m_incrementButton);
    }
  }
  public JButton getIncrementButton() {
    return (m_incrementButton);
  }
  public JButton getDecrementButton() {
    return (m_decrementButton);
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    JPanel panel = (JPanel) frame.getContentPane();
    panel.setLayout(new BorderLayout());
    JTextField field = new JTextField(20);
    Spinner spinner = new Spinner();
    panel.add(field, "Center");
    panel.add(spinner, "East");
    Dimension dim = frame.getToolkit().getScreenSize();
    frame.setLocation(dim.width / 2 - frame.getWidth() / 2, dim.height / 2
        - frame.getHeight() / 2);
    frame.pack();
    frame.show();
  }
}





Use an Icon Editor for use with the JSpinner component

  
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
class IconEditor extends JLabel implements ChangeListener {
  JSpinner spinner;
  Icon icon;
  public IconEditor(JSpinner s) {
    super((Icon)s.getValue(), CENTER);
    icon = (Icon)s.getValue();
    spinner = s;
    spinner.addChangeListener(this);
  }
  public void stateChanged(ChangeEvent ce) {
    icon = (Icon)spinner.getValue();
    setIcon(icon);
  }
  public JSpinner getSpinner() { return spinner; }
  public Icon getIcon() { return icon; }
}





Use images in tooltips

  
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Main {
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    JLabel label = new JLabel("Label with image in Tooltip!");
    label.setToolTipText("<html><img src=\"" + Main.class.getResource("tooltip.gif")
        + "\"> Tooltip ");
    label.setHorizontalAlignment(JLabel.CENTER);
    frame.setContentPane(label);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setBounds(100, 100, 200, 100);
    frame.setVisible(true);
  }
}