0
我有一個JComboBoxes列的GUI,其中每個列都是唯一的。我真的不明白我在做什麼,所以最近在一個特別長的障礙序列中,當編輯一個盒子時,它不顯示新選擇的值。如果再次選中該框,單元格中的值將更新爲之前選擇的值,因此推測這只是表/渲染器未更新的問題。在JTable中,當編輯單元格獨特的JComboBoxes時更新顯示的項目
我懷疑我可能需要在某個地方爲每個組合框註冊一個偵聽器,但我不知道哪一類偵聽器在哪個類上。
下面是說明作爲簡潔的,因爲它代表我會管理設計的SSCCE:
import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
@SuppressWarnings("serial")
public class ComboBoxTableGUI extends JFrame {
public List<SampleCollection> masterList;
public static void main(String[] args) {
new ComboBoxTableGUI();
}
public ComboBoxTableGUI() {
// create a collection of 10 collections, each with 1-10 Strings
masterList = new ArrayList<SampleCollection>();
Random rnd = new Random();
for (int i = 0; i < 10; i++) {
SampleCollection sc = new SampleCollection("Option " + i + ":");
int choices = rnd.nextInt(9) + 1;
for (int j = 0; j < choices; j++) {
sc.choices.add("Choice " + j);
}
sc.selectedChoice = sc.choices.get(0);
masterList.add(sc);
}
this.setSize(500, 500);
this.setLocationRelativeTo(null);
TableModel optionTableModel = new OptionTableModel();
JTableWithCustomEditors optionsTable = new JTableWithCustomEditors(optionTableModel);
this.add(optionsTable);
TableColumn optionCol = optionsTable.getColumnModel().getColumn(1);
optionCol.setCellRenderer(new CustomComboBoxRenderer());
List<TableCellEditor> editors = new ArrayList<TableCellEditor>();
for (SampleCollection collection : masterList) {
JComboBox<String> cb = new JComboBox<String>();
for (String choice : collection.choices) {
cb.addItem(choice);
}
DefaultCellEditor editor = new DefaultCellEditor(cb);
editors.add(editor);
}
optionsTable.editors = editors;
this.setVisible(true);
}
public class SampleCollection {
public String name, selectedChoice;
public List<String> choices;
public SampleCollection(String name) {
this.name = name;
this.choices = new ArrayList<String>();
}
}
public class JTableWithCustomEditors extends JTable {
public List<TableCellEditor> editors;
public JTableWithCustomEditors(TableModel model) {
super(model); // lol
}
@Override
public TableCellEditor getCellEditor(int row, int column) {
if (column == 1)
return editors.get(row);
else
return super.getCellEditor(row, column);
}
}
class CustomComboBoxRenderer extends JComboBox<String> implements
TableCellRenderer {
public CustomComboBoxRenderer() {
setBorder(new EmptyBorder(0, 0, 0, 0));
}
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
removeAllItems();
addItem(((SampleCollection) value).selectedChoice);
this.setSelectedIndex(0);
return this;
}
}
public class OptionTableModel implements TableModel {
private List<TableModelListener> listeners;
public OptionTableModel() {
listeners = new ArrayList<TableModelListener>();
}
@Override
public void addTableModelListener(TableModelListener l) {
listeners.add(l);
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 1)
return SampleCollection.class;
else
return String.class;
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public String getColumnName(int columnIndex) {
if (columnIndex == 0)
return "Name";
else
return "Selection";
}
@Override
public int getRowCount() {
if (masterList == null)
return 0;
else
return masterList.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0)
return masterList.get(rowIndex).name;
else
return masterList.get(rowIndex);// also tried .choices
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (columnIndex == 1)
return true;
else
return false;
}
@Override
public void removeTableModelListener(TableModelListener l) {
listeners.remove(l);
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
// the values are grabbed when the user clicks an OK button, right
// now I just need to get it rendering
}
}
}
數據生活在遙遠的地方,當TableModel顯示時,'TableModel'確實獲得了對相應'List的引用;我只想爲這個例子提供儘可能少的方法,參數和字段。 您可以詳細說明調用'fireTableCellUpdated()'嗎? –
已解決:添加到'setValueAt(...)'行'masterList.get(rowIndex).selectedChoice =(String)aValue;'和框更新正確。 我對這個所謂的'fireWhateverThing'感到困惑,因爲它在'AbstractTableModel'中,我沒有使用它。 –
@ Mr.Wallet,您應該擴展AbstractTableModel,以便調用相應的fireXXX方法。 「數據生活很遙遠,TableModel確實得到了一個參考,這不是正確的設計。數據應該駐留在TableModel中。所有更新數據的方法都應該是模型的一部分。這是所有Swing組件使用的MVC設計的基礎。不要做愚蠢的事情,因爲你認爲它更容易。從長遠來看,這並不容易,我相信你會回到論壇上提問,因爲你目前的設計。 – camickr