2016-11-06 14 views
0

コンテンツがクラス "アイテム"のVectorであるJTableを取得します。クラス項目には、文字列のArrayListであるフィールドaltを除いて、適切なgetter/setterを持つ数値フィールドと英数字フィールドが含まれています。このコラムでは、使用可能な選択肢の1つを選択して選択肢を表示するために、comboBoxスタイルのレンダラーとエディタを使用することを意図していました。 altフィールドは行ごとに異なり、それが問題になります。私はこのレンダラの例をたくさん見ましたが、すべての例で利用できる選択肢は各行で同じでした。ここでは、コードです:JTableでコンボボックスタイプのレンダラー/エディターを設定する

public class item extends Vector { 

private int no, code; 
private String ....; 
private List<String> alt; 

@SuppressWarnings("unchecked") 
public item(int no, int code, ...., List alt) { 
    super(); 
    this.add(no); 
    this.add(code); 
    .... 
    this.add(alt); 
} 

public int getNo() { 
    return (int) this.get(0); 
} 

public void setNo(int no) { 
    this.no = no; 
} 

// other setter/getters... 

public void setAlt(List<String> alt) { 
    this.alt = alt; 
} 

@SuppressWarnings("unchecked") 
public List<String> getAlt() { 
    return (List<String>) this.get(6); 
} 

@SuppressWarnings("all") 
public Vector getAsVector() { 
    // ArrayList<Object> a= new ArrayList<Object>(); 
    Vector a = new Vector(7); 
    a.add(no); 
    a.add(sifra); 
    a.add(red1); 
    a.add(red2); 
    a.add(sastojci); 
    a.add(eanKod); 
    a.add(alt); 
    return a; 
} 

}

JTableは必要な機能を得る:

public Class getColumnClass(int ci){ 
    if (ci==6) return JComboBox.class; 
    else return String.class;  
} 


@Override 
public void setValueAt(Object value, int rowIndex, int columnIndex) { 
    item it = data.get(rowIndex); 

    switch (columnIndex) { 
    case 0: 
     it.setNo((int) value); 
     break; 
    case 1: 
     it.setCode((int) value); 
     break; 
    case 2: 
     .... 
    case 6: 

     it.setAlt((List<String>) value); 
     break; 
    } 
} 

@Override 
public Object getValueAt(int rowIndex, int columnIndex) { 
    Object returnValue = null; 
    item it = data.get(rowIndex); 

    switch (columnIndex) { 
    case 0: 
     returnValue = it.getNo(); 
     break; 
    case 1: 
     returnValue = it.getCode(); 
     break; 
    case 2: 
     ... 
    case 6: 
     returnValue = it.getAlt(); 
     break; 
    } 

    return returnValue; 
}  

public boolean isCellEditable(int rowIndex, int columnIndex) { 
    return columnIndex > 0; 
} 

そして最後に、レンダラ/エディタクラス:

String[] sval = {"alfa", "Beta", "Gamma"}; //dummy array 

protected class ComboRenderer extends JComboBox implements TableCellRenderer { 

    public ComboRenderer(){ 
     super(sval);   //works, but this is not I want 
//  here should be used a similar super(list of options for a certain row), but how to get it? 
//  setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); 
     setOpaque(true); 
    } 


    public Component getTableCellRendererComponent(JTable table, Object value, 
      boolean isSelected, boolean hasFocus, int row, int column) { 

    if (isSelected) { 
       setForeground(table.getSelectionForeground()); 
       setBackground(table.getSelectionBackground()); 
     } else { 
       setForeground(table.getForeground()); 
       setBackground(table.getBackground()); 
     }   
     this.setSelectedItem(items); 
     return this; 
    } 

} 


protected class ComboEditor extends AbstractCellEditor 
implements TableCellEditor { 

    private List<String> alt; 

    protected ComboEditor() { 
     super(); 
    } 

    @Override 
    public Object getCellEditorValue() { 
     return this.alt; 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 
     if (value instanceof List) { 
      this.alt = (List<String>) value; 
     } 

     JComboBox<String> combo = new JComboBox<String>(); 
    // combo.setEditable(true); //does not work for editable combobox! 
     for (String a : alt) { 
      combo.addItem(a); 
     } 

     combo.setSelectedItem(alt); 

     if (isSelected) { 
      setForeground(table.getSelectionForeground()); 
      setBackground(table.getSelectionBackground()); 
     } else { 
      setForeground(table.getForeground()); 
      setBackground(table.getBackground()); 
     }   

     return combo; 
    } 

} 

そして、ここでは、質問のとおりです。

1)レンダラはコンストラクタの間違った部分(super(something))に対して明らかに動作しません。しかしこの部分では、レンダリングされたアイテムを取得できないため、初期化の選択肢のリストを取得できません。その問題を解決するには?

2)エディタはうまくいくように見えますが、行から移動すると再び古い値が表示されます。ここで私はどのようにsometingを保存する必要がありますか?新しいデータはなく、このアイテムで使用可能なオプションの中から選択するだけです。

3)外部から特定の行に選択した値に達する方法、印刷についてはどうですか?

4)修正可能なComboboxを入手するにはどうしたらいいですか?ライン

// combo.setEditable(true); //does not work for editable combobox! 

は(。なしを除く4)一方

答えて

0

が、私は問題を解決し、この場合には動作しませんが、私はそれがよりよい解決策でなければならないと思うので、私はまだ代替ソリューションを待っています。最初の場合

、私はレンダラの唯一のインスタンスを得たので、

setSelectedItems(<available options>) 

の戻り値は関係なく、そこに選択したものを、あまりにALL他の行の最初の行の選択を返さないことに気づきました。そこで、すべての行に対して1つのレンダラーインスタンスを作成することにしました。次のように

rendererList = new ArrayList<ComboRenderer>(); 
.... 
// create the Array of renderers, one for each row 
    for (int cnt=0; cnt<data.size(); cnt++){ 
     ComboRenderer a = new ComboRenderer(); 
     a.setOptions(cnt); 
     rendererList.add(a); 
    } 
.... 
// telling to JTable which renderer to use for every cell  
@Override 
public TableCellRenderer getCellRenderer(int row, int coll) { 
    if (coll==6) return rendererList.get(row); 
    else return this.getDefaultRenderer(this.getColumnClass(coll));  

} 

レンダラとエディタクラスは今になります:それは、JTableのコンストラクタ意志は次のコードが含まれていることを意味それは今働いているが、コードは、私にとって非常に不器用に見える

protected class ComboRenderer extends JComboBox implements TableCellRenderer { 

    List<String> items; 
    int selected; 
    //selected will contains the index of selected option, changed through the cell editor as listener 

    public ComboRenderer(){ 
     super(); 
     setOpaque(true); 
     selected=0; //initial value 
    } 

    public void setSel(int k) { 
     selected=k; 
    } 

    public int getSel() { 
     return selected; 
    } 
    // filling each renderer with available options; 
    @SuppressWarnings("unchecked") 
    public void setOptions(int row) { 
     items = data.get(row).getAlt(); 

     for (String a : items) { 
      this.addItem(a); 
     } 
    } 

    public Component getTableCellRendererComponent(JTable table, Object value, 
      boolean isSelected, boolean hasFocus, int row, int column) { 

     if (isSelected) { 
       setForeground(table.getSelectionForeground()); 
       setBackground(table.getSelectionBackground()); 
     } else { 
       setForeground(table.getForeground()); 
       setBackground(table.getBackground()); 
     }  
     this.setSelectedIndex(selected); 
     return this; 
    } 

} 


class ComboEditor extends AbstractCellEditor implements TableCellEditor{ 

    private List<String> alt ; 


    protected ComboEditor() { 
     super(); 
    } 

    @Override 
    public Object getCellEditorValue() { 
     return this.alt; 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 
     if (value instanceof List) { 
      this.alt = (List<String>) value; 
     } 

     JComboBox<String> combo = new JComboBox<String>(); 
     for (String a : alt) { 
      combo.addItem(a); 
     } 
     final ComboRenderer rend= rendererList.get(row); 
     // adding actionlistener to letting know the renderer the selection 
     combo.addActionListener(new ActionListener(){ 
      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       int i=((JComboBox<?>) arg0.getSource()).getSelectedIndex(); 
       // telling the renderer the selection  
       rend.setSel(i); 
      } 
     }); 

     combo.setSelectedIndex(rend.getSel()); 

     if (isSelected) { 
      setForeground(table.getSelectionForeground()); 
      setBackground(table.getSelectionBackground()); 
     } else { 
      setForeground(table.getForeground()); 
      setBackground(table.getBackground()); 
     }   

     return combo; 
    } 
} 

。よりエレガントな方法でこの問題を解決する方法がなければなりません。私は、各行ごとに別個のレンダラーを持たなければならないと信じることはできません。これは記憶の浪費です。誰か考えてもらえますか?

関連する問題