セルエディターでアクションが呼び出された後、セルは更新されません
-
28-10-2019 - |
質問
セルレンダラーを備えたテーブルを使用しているため、各セルにボタン「x」を値で配置できるようにして、ボタンを押すとセルの値を削除できるようにします。セルエディターはアクションリスナーをボタンに割り当て、ボタンが押されたときに適切なアクションが呼び出されます。
デフォルトのテーブルモデルであるテーブルモデルのすべての列には、値の配列リストが入力されます。変更後、テーブル内の他のすべてのセルが削除された後、テーブル内の他のすべてのセルを押して、配列リストから正しい値を削除することに成功しましたが、削除されたセルは変更されません。アプリケーションを再起動するか、配列リストに値を追加すると、テーブルのリフレッシュが予想どおりに表示され、すべてが必要に見えます。
MOの問題は、セルレンダラーがセルの初期値を忘れないように思われるため、テーブルが再描画されていても、この値をセルに印刷し続けています。値が正しく表示されるように、テーブルを適切にリフレッシュできる方法について誰かが考えていますか?
テーブルクラス:
public class Table extends JTable {
public static DefaultTableModel model = new DefaultTableModel();
private Days d;
private JFrame frame;
private AddCellRenderer renderer;
private AddCellEditor editor;
public Table(Days d, JFrame frame) {
// Assign the table model to the table
super(model);
this.d = d;
this.frame = frame;
// Define dimensions of table
model.setRowCount(11);
model.setColumnCount(5);
// Block resizing and reordering of headers
this.setColumnSelectionAllowed(false);
this.setRowSelectionAllowed(false);
this.setCellSelectionEnabled(true);
this.setTableHeader(null);
// Define first row height
this.setRowHeight(38);
// Define all other row's heights
this.setRowHeight(0, 45);
this.d.setTable(this);
for (int i = 0; i < 5; i++) {
editor = new AddCellEditor(new JCheckBox(), d.getVisibleDays().get(i), this);
renderer = new AddCellRenderer(d.getVisibleDays().get(i), editor);
this.getColumnModel().getColumn(i).setCellRenderer(renderer);
this.getColumnModel().getColumn(i).setCellEditor(editor);
}
this.refresh();
}
public void refresh() {
// Empty table
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 11; j++) {
this.getModel().setValueAt(null, j, i);
}
}
// Populate table with entries for each day
for (int i = 0; i < 5; i++) {
Iterator<String> iterator = d.getVisibleDays().get(i).getEntryListIterator();
int j = 0;
while(iterator.hasNext()){
String s = iterator.next();
this.getModel().setValueAt(s, (j+1), i);
j++;
}
this.getModel().setValueAt(d.getVisibleDays().get(i).getDayName(), 0, i);
}
}
public void modelClearValueAt(int row, int column) {
this.getModel().setValueAt(null, row, column);
}
}
セルエディタークラス:
public class AddCellEditor extends DefaultCellEditor {
private JPanel headerPanel;
private JPanel entryPanel;
private JLabel dayName;
private JLabel entryValue;
protected JButton addButton;
private JButton removeButton;
private String label;
private int row;
private int column;
private Day day;
private String date;
private Table table;
private AddCellRenderer renderer;
public AddCellEditor(JCheckBox checkBox, Day day, Table table) {
super(checkBox);
this.day = day;
this.table = table;
date = day.getDayDate();
headerPanel = new JPanel();
headerPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
entryPanel = new JPanel();
entryPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
dayName = new JLabel();
entryValue = new JLabel();
addButton = new JButton();
removeButton = new JButton();
headerPanel.add(dayName);
headerPanel.add(addButton);
entryPanel.add(entryValue);
entryPanel.add(removeButton);
addButton.setOpaque(true);
addButton.setPreferredSize(new Dimension(16, 16));
removeButton.setOpaque(true);
removeButton.setPreferredSize(new Dimension(16, 16));
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Add pressed");
addItem();
fireEditingStopped();
}
});
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Remove pressed");
removeItem();
getTable().refresh();
fireEditingStopped();
}
});
}
public void setRenderer(AddCellRenderer renderer) {
this.renderer = renderer;
}
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
this.row = row;
this.column = column;
if (row == 0) {
return this.headerPanel;
}
if (row != 0 && value != null) {
return this.entryPanel;
}
return null;
}
public void addItem() {
String input = JOptionPane.showInputDialog("Add entry for " + label + ":");
if ((input != null) && (input.length() > 0)) {
System.out.println("Added: " + input + "Item");
day.addEntry(input, column);
}
}
public void removeItem() {
table.modelClearValueAt(row, column);
day.removeEntry(row-1);
System.out.println("Item removed");
}
public Table getTable() {
return this.table;
}
public boolean stopCellEditing() {
return super.stopCellEditing();
}
protected void fireEditingStopped() {
super.fireEditingStopped();
}
}
前もって感謝します
解決
さて、抵抗できませんでした(代替手段はバスルームをスクラブすることです:-)
以下は、行儀の良い編集者とカスタムテーブルデルであなたの目標を解決する方法の非常に生のアウトライン(あなたにアイデアを与えるのに十分です)です。
- MyTableModelは、基本的に任意のエントリのリストに裏付けられたカスタム実装です
- このTablemodelは、アイテムの削除/追加をサポートします。今のところ個人的には、編集者から電話をかけるように誘惑されていません:-)彼らはパブリックスコープで公開するのに十分安全です。
- モデルは、setValueatでさまざまな値タイプを処理できます:変更マーカー、新しいエントリー、または平易な値
- カスタムエディターは、削除するボタンを備えたパネルで、行を追加します。
- ボタンのアクションは、必要に応じて編集を呼び出す/キャンセルする前に、必要に応じて編集数を設定します
モデル:
public static class MyTableModel extends AbstractTableModel {
public enum Modify {
ADD,
REMOVE
}
public static class NewItem {
public final Object entry;
public NewItem(Object entry) {
this.entry = entry;
}
}
private List entries;
public MyTableModel(List entries) {
this.entries = entries;
}
@Override
public int getRowCount() {
return entries.size();
}
@Override
public int getColumnCount() {
return 1;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return entries.get(rowIndex);
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (aValue instanceof NewItem) {
addEntry(((NewItem) aValue).entry);
} else if (Modify.REMOVE == aValue) {
removeEntry(rowIndex);
} else {
entries.set(rowIndex, aValue);
}
}
private void removeEntry(int rowIndex) {
entries.remove(rowIndex);
fireTableRowsDeleted(rowIndex, rowIndex);
}
private void addEntry(Object aValue) {
int last = getRowCount();
entries.add(aValue);
fireTableRowsInserted(last, last);
}
}
編集者:
public static class MyCellEditor extends AbstractCellEditor implements TableCellEditor {
private Object editorValue;
private JLabel entryView;
JComponent editor;
public MyCellEditor() {
editor = new JPanel();
entryView = new JLabel();
editor.add(entryView);
Action add = createAddAction();
editor.add(new JButton(add));
Action remove = createRemoveAction();
editor.add(new JButton(remove));
}
public Action createRemoveAction() {
Action remove = new AbstractAction("Remove Entry") {
@Override
public void actionPerformed(ActionEvent e) {
editorValue = MyTableModel.Modify.REMOVE;
fireEditingStopped();
}
};
return remove;
}
public Action createAddAction() {
Action add = new AbstractAction("Add Entry") {
@Override
public void actionPerformed(ActionEvent e) {
String input = JOptionPane.showInputDialog("Add entry: ");
if ((input != null) && (input.length() > 0)) {
editorValue = new MyTableModel.NewItem(input);
fireEditingStopped();
} else {
fireEditingCanceled();
}
}
};
return add;
}
@Override
public Object getCellEditorValue() {
return editorValue;
}
@Override
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
entryView.setText(value != null ? value.toString() : "");
return editor;
}
}
使用法:
List entries = new ArrayList();
for (int i = 0; i < 5; i++) {
entries.add("entry " + i);
}
TableModel model = new MyTableModel(entries);
JTable table = new JTable(model);
table.getColumnModel().getColumn(0).setCellEditor(new MyCellEditor());
table.getColumnModel().getColumn(0).setPreferredWidth(200);
table.setRowHeight(50);
他のヒント
DefaultTableModelを使用している場合、モデル自体が保持している値を削除する必要があります。これは、モデルの構築に使用されたアレイリストの値ではありません。電話をかけることでこれを行います setValueAt(...)
DefaultTableModelオブジェクトのメソッド。
あなたは投稿したいかもしれません sscce より具体的なヘルプのために。