Java/Swing JFC/Spinner
Содержание
- 1 A date spinner
- 2 A list spinner
- 3 An example of JSpinner with a custom editor
- 4 An implementation of JSpinner with customized content--icons
- 5 A quick test of various spinners
- 6 A spinner of dates
- 7 Create a spinner
- 8 Creating a JSpinner Component: A number spinner:
- 9 Creating an Hour JSpinner Component
- 10 Creating a SpinnerListModel That Loops Through Its Values
- 11 Customizing the Editor in a JSpinner Component: Create a color spinner
- 12 Date spinner
- 13 Demonstrate the Swing Spinner control
- 14 Demonstrating the JSpinner Component
- 15 Disabling Keyboard Editing in a JSpinner Component
- 16 Enhanced Spinner List Formatter
- 17 Enhanced Spinner List Model
- 18 Java Spinner Component
- 19 Limiting the Values in a Number JSpinner Component
- 20 List based spinner
- 21 Listening for Changes to the Value in a JSpinner Component
- 22 Number spinner
- 23 Setting the Margin Space on a JSpinner Component
- 24 Spinner 2
- 25 Use an Icon Editor for use with the JSpinner component
- 26 Use images in tooltips
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);
}
}