2013-05-29 42 views
0

我试图实现以下。JSpinner与自定义渲染器

我想使用为其数据使用数字的JSpinner,但我想让它呈现如下:“6/10”,即“value/maximum”,默认JSpinner只显示“value ”。当然,我正在使用SpinnerNumberModel只能将整数用作数据。

与JCombobox渲染器和/或编辑器,JTable渲染器和/或编辑器相比,我一直在寻找模拟行为......但是看起来JSpinner不能这样工作。我发现this example,用于微调器内的自定义内容。该示例使用JLabel来显示图标,但在我的情况下,我必须能够编辑内容并在点击后输入来检查输入。

所以这是我主要做:

JSpinner spinner = new JSpinner(new SpinnerNumberModel(1,1,10,1)); 
spinner.setEditor(new CustomSpinnerEditor(spinner)); 
其中CustomSpinnerEditor正在扩展了JTextField

。我在其上释放了一些输入映射/动作映射(对于输入行为),向微调器添加了一个ChangeListener,以便在用户单击箭头时刷新文本框内容,添加FocusListener以选择focusGained上的所有文本并验证focusLost上的输入,...以及它的工作原理。

所以问题不在于它的工作。问题是,对于一些非常简单的事情来说,这样做太多了,而且我可能会因为不使用默认编辑器而失去一些功能。如果组件只是提供了设置渲染器的能力,那么我就会有一个钩子,我只是用正确的String返回一个JLabel,就像我使用JComboBox一样。

有没有更简单的方法来实现我想要的?

回答

2

可避免创建一个专用的编辑,但如果它变得更简单,我不知道:使用

JFormattedTextField f = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField(); 

检索默认编辑的文本字段,然后设置格式工厂对文本字段:

f.setFormatterFactory(new AbstractFormatterFactory() { 
    @Override 
    public AbstractFormatter getFormatter(JFormattedTextField tf) { 
     // return your formatter 
    } 
}); 

getFormatter方法返回则必须在价值和它的字符串表示之间进行转换,利用其stringToValuevalueToString方法格式化。

1

我不知道你是否会考虑这个更简单。

JSpinner Test

我创建了一个Renderer类,用于保存要显示的值和值的字符串。

在自定义微调模型中,我创建了一个Renderer实例列表,并导航了列表。

我把类放在一起,所以我可以复制和粘贴一段代码。这3个类应保存在不同的源代码模块中。

这里有一种方法可以做你想做的事。

import java.awt.Color; 
import java.awt.Dimension; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.AbstractSpinnerModel; 
import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JSpinner; 
import javax.swing.SwingUtilities; 
import javax.swing.border.Border; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class SpinnerTesting implements Runnable { 

    @Override 
    public void run() { 
     JFrame frame = new JFrame("JSpinner Test"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     JPanel mainPanel = new JPanel(); 
     final JSpinner spinner = new JSpinner(new CustomSpinnerModel(4, 1, 10, 
       1)); 
     setBorder(spinner); 
     spinner.addChangeListener(new ChangeListener() { 
      @Override 
      public void stateChanged(ChangeEvent event) { 
       Renderer renderer = (Renderer) spinner.getValue(); 
       System.out.println(renderer.getValue()); 
      } 
     }); 
     mainPanel.add(spinner); 

     frame.add(mainPanel); 
     frame.setSize(new Dimension(300, 100)); 
     frame.setVisible(true); 
    } 

    private void setBorder(JSpinner spinner) { 
     Border lineBorder = BorderFactory.createLineBorder(Color.BLACK); 
     Border insetBorder = BorderFactory.createEmptyBorder(0, 10, 0, 10); 
     spinner.setBorder(BorderFactory.createCompoundBorder(lineBorder, 
       insetBorder)); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new SpinnerTesting()); 
    } 

    public class CustomSpinnerModel extends AbstractSpinnerModel { 

     private int    value; 
     private int    minimum; 
     private int    maximum; 
     private int    stepSize; 

     private int    listIndex; 

     private List<Renderer> spinnerList; 

     public CustomSpinnerModel(int value, int minimum, int maximum, 
       int stepSize) throws IllegalArgumentException { 
      if (!((minimum <= value) && (value <= maximum))) { 
       throw new IllegalArgumentException(
         "(minimum <= value <= maximum) is false"); 
      } 

      this.value = value; 
      this.minimum = minimum; 
      this.maximum = maximum; 
      this.stepSize = stepSize; 

      this.spinnerList = new ArrayList<Renderer>(); 
      setSpinnerList(); 
     } 

     private void setSpinnerList() { 
      int index = 0; 
      for (int i = minimum; i <= maximum; i += stepSize) { 
       Renderer renderer = new Renderer(i, maximum); 
       if (i == value) { 
        listIndex = index; 
       } 
       spinnerList.add(renderer); 
       index++; 
      } 
     } 

     @Override 
     public Object getNextValue() { 
      listIndex = Math.min(++listIndex, (spinnerList.size() - 1)); 
      fireStateChanged(); 
      return spinnerList.get(listIndex); 
     } 

     @Override 
     public Object getPreviousValue() { 
      listIndex = Math.max(--listIndex, 0); 
      fireStateChanged(); 
      return spinnerList.get(listIndex); 
     } 

     @Override 
     public Object getValue() { 
      return spinnerList.get(listIndex); 
     } 

     @Override 
     public void setValue(Object object) { 

     } 

    } 

    public class Renderer { 

     private int  value; 

     private String valueString; 

     public Renderer(int value, int maximum) { 
      this.value = value; 
      this.valueString = value + "/" + maximum; 
     } 

     public int getValue() { 
      return value; 
     } 

     public String getValueString() { 
      return valueString; 
     } 

     @Override 
     public String toString() { 
      return valueString + " "; 
     } 

    } 

}