Two JXTables with same custom model - How to make cells editable in one table but non-editable in the second?

StackOverflow https://stackoverflow.com/questions/13493431

Question

I have a custom table model whose data I want to edit in one JXTable, but view-only in a second JXTable. Can this be done without having two separate models? Is there some way of overriding model.isCellEditable for the view-only table?

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.HighlightPredicate;

public class SSCCE extends JPanel {

  private JSplitPane splitPane;
  private JXTable viewTable, editTable;

  private class CustomModel extends AbstractTableModel {

    public static final int SPORT_COL = 0;
    public static final int EQUIPMENT_COL = 1;
    private final String[] COLUMN_NAMES = {
      "Sport",
      "Equipment"
    };
    private Map<String, String> sports;
    private List<String> set;

    public CustomModel() {
      sports = new TreeMap<String, String>();
      sports.put("Rugby", "Headguard");
      sports.put("Hurling", "Sliotar");
      sports.put("Tennis", "Racket");
      set = new ArrayList<String>(sports.keySet());
    }

    public int getRowCount() {
      return sports.size();
    }

    public int getColumnCount() {
      return COLUMN_NAMES.length;
    }

    @Override
    public String getColumnName(int columnIndex) {
      return COLUMN_NAMES[columnIndex];
    }

    public Object getValueAt(int rowIndex, int columnIndex) {
      String sport = set.get(rowIndex);
      switch (columnIndex) {
        case SPORT_COL:
          return sport;
        case EQUIPMENT_COL:
          return sports.get(sport);
      }
      return null;
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
      if (columnIndex == EQUIPMENT_COL) {
        if (aValue != null) {
          String sport = (String) getValueAt(rowIndex, SPORT_COL);
          String equip = (String) aValue;
          sports.put(sport, equip);
          fireTableDataChanged();
        }
      }
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
      return columnIndex == EQUIPMENT_COL;
    }
  }
  private CustomModel model;

  public SSCCE() {
    super();

    model = new CustomModel();
    viewTable = new JXTable(model);
    editTable = new JXTable(model);
    editTable.addHighlighter(new ColorHighlighter(new HighlightPredicate() {
      @Override
      public boolean isHighlighted(Component renderer, ComponentAdapter adapter) {
        return adapter.isEditable();
      }
    }, Color.GREEN.brighter(), Color.BLACK));

    JPanel panelLeft = new JPanel(new BorderLayout(0, 10));
    panelLeft.add(new JLabel("Editable"), BorderLayout.NORTH);
    panelLeft.add(new JScrollPane(editTable));
    JPanel panelRight = new JPanel(new BorderLayout(0, 10));
    panelRight.add(new JLabel("How to make non-editable?"), BorderLayout.NORTH);
    panelRight.add(new JScrollPane(viewTable));

    splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, panelLeft, panelRight);
    add(splitPane);
  }

  public static void main(String args[]) {
    JFrame frame = new JFrame("One Model | Two Views");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new SSCCE(), BorderLayout.CENTER);
    frame.setSize(360, 240);
    frame.setVisible(true);
  }
}
Was it helpful?

Solution

SwingX supports configuring the editability on the view layer. No need to touch your model, keep it editable as appropriate:

viewTable = new JXTable(model);
viewTable.setEditable(false);
editTable = new JXTable(model);

OTHER TIPS

Create a WrapperTableModel which delegates all the calls to the inner TableModel but returns false from isCellEditable().

Set the first editable model to the table1 and the wrapper model (holding reference to the first) in the table2.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top