单击按钮时永久JTable颜色单元格

时间:2014-10-02 14:36:14

标签: java swing jtable cells tablecellrenderer

我想创建一个JTable并通过单击按钮永久地为其单元着色(非常类似于着色单元格中的excel)。到目前为止,我选择的每个单元格都会进入ArrayList<Cell>

首先,我希望单击按钮时列表中的每个单元格都会永久着色(这与我找到的代码不同)。我必须使用像table.getColumnModel().getColumn(column).setCellRenderer(this);这样的状态?

这是一个可编译的代码,如果您调试它,您将看到单击该按钮时,我无法访问getTableCellRendererComponent()方法。为什么会这样?如果你能告诉我你的意见,我将不胜感激。

(注意:它是一个巨大程序的重现,所以它在某些地方有点大乱和硬编码。不能让它变小我想解决的问题。)

Class ColorSelectedTableCells.java

public class ColorSelectedTableCells extends JPanel {
   private JButton btn = new JButton("color cells");
   private MyCellRenderer myCellRenderer = new MyCellRenderer();
   public static final Object[][] DATA = new Object[3][3];
   public static final String[] COLS = {"A", "B", "C"};
   private static final int PREF_WIDTH = 400;
   private static final int PREF_HEIGHT = 300;
   private static CellSelectionSet cellSelectionSet = new CellSelectionSet();

   private JTable table = new JTable(DATA,COLS){
       @Override
       public boolean isCellEditable(int row, int column) {return false;}

       @Override
       public boolean isCellSelected(int row, int column) {
          if (cellSelectionSet.containsOneOrLess()) {
            return super.isCellSelected(row, column);
          }
            return cellSelectionSet.contains(row, column);
        }

        @Override
        public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
          super.changeSelection(rowIndex, columnIndex, toggle, extend);
          if (toggle) {
            cellSelectionSet.add(rowIndex, columnIndex);
          } 
          else {
            if (extend) {
              cellSelectionSet.add(rowIndex, columnIndex);
            } 
            else {
              cellSelectionSet.clear();
              cellSelectionSet.add(rowIndex, columnIndex);
            }
          }
        }   
      };

 public ColorSelectedTableCells() {
  table.setDefaultRenderer(Integer.class, myCellRenderer);
  table.setCellSelectionEnabled(true);
  table.setColumnSelectionAllowed(false);
  table.setRowSelectionAllowed(false);

  JScrollPane scrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
  JPanel btnPanel = new JPanel();
  btnPanel.add(btn);

  setLayout(new BorderLayout());
  add(scrollPane, BorderLayout.CENTER);
  add(btnPanel, BorderLayout.SOUTH);

  btn.addActionListener(new ActionListener() {
     @Override
     public void actionPerformed(ActionEvent e) {
        myCellRenderer.setShowSelected(true);
        table.repaint();
     }
  });
}

@Override
public Dimension getPreferredSize() {
   return new Dimension(PREF_WIDTH, PREF_HEIGHT);
}

private static void createAndShowUI() {
  JFrame frame = new JFrame();
  frame.getContentPane().add(new ColorSelectedTableCells());
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.pack();
  frame.setLocationRelativeTo(null);
  frame.setVisible(true);
}

public static void main(String[] args) {
  java.awt.EventQueue.invokeLater(new Runnable() {
     public void run() {
        createAndShowUI();
     }
  });
}

Class MyCellRenderer.java

private static class MyCellRenderer extends DefaultTableCellRenderer {
  private boolean showSelected = false;
  private byte colorSwitcher;

  public void setShowSelected(boolean showSelected) {
     this.showSelected = showSelected;
  }

  public void setColorSwitcher(byte colorSwitcher){
      this.colorSwitcher = colorSwitcher;
  }

  @Override
  public Component getTableCellRendererComponent(JTable table,Object value, boolean isSelected, boolean hasFocus, int row,int column) {
    Component superComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

      if(showSelected && table.isCellSelected(row, column)){
        superComponent.setBackground(Color.GREEN);
      }
      else if (table.isCellSelected(row, column)){
        superComponent.setBackground(table.getSelectionBackground());
      }
      else {
        superComponent.setBackground(table.getBackground());
      }
       return superComponent;
    }
  }
}

类cellSelectionSet.java

  public class CellSelectionSet {
  private List<Cell> cells = new ArrayList<>();

  public void add(int r, int c) {
    if (!contains(r, c)) {
        cells.add(new Cell(r, c));
    }
  }

  public boolean containsOneOrLess() {
    return cells.size() <= 1;
  }

  public boolean contains(int r, int c) {
    for (Cell cell : cells) {
        if (cell.is(r, c)) {
            return true;
        }
    }
    return false;
  }

  public Cell getElementAt(int i){
    return cells.get(i);
  }

  public int getSize(){
    return this.cells.size();
  }

  public void clear() {
    cells.clear();
    System.out.println("CellSelectionSet cleared.");
  }  
}

Class Cell.java

public class Cell {
  private int row, column;

  public Cell(int row, int column){
    this.row = row;
    this.column = column;
  }

  public boolean is(int r, int c) {
    return row == r && column == c;
  }
}

1 个答案:

答案 0 :(得分:2)

主要问题:

table.setDefaultRenderer(Integer.class, myCellRenderer);

应该是

table.setDefaultRenderer(Object.class, myCellRenderer);

这将使您的细胞改变颜色。但是你有一个问题,之后按下按钮,你选择的每个单元格都会自动改变颜色,因为showSelected属性设置为true。谁知道,也许这就是你想要的。

另一个问题是细胞保持选择颜色。如果使用您的检查声明

,则会出现问题
if(showSelected && table.isCellSelected(row, column)){

进行更多选择后,将清除原始选择。修复方法是检查CellSelectionSet以查看它是否包含单元格,还要检查它是否是新选择的。像

这样的东西
if (cellSelectionSet.contains(row, column)
                  && !cellSelectionSet.getCellAt(row, column).isNewlySelected())

我在您的getCellAt

中添加了CellSelectionSet方法
public Cell getCellAt(int row, int column) {
    Cell c = null;
    for (Cell cell : cells) {
        if (cell.is(row, column)) {
            c = cell;
        }
    }
    return c;
}

还有一个Cell类中的标志,用于检查它是newlySelected。默认值为true

class Cell {

    private boolean newlySelected = true;

    public boolean isNewlySelected() {
        return newlySelected;
    }

    public void setNewlySelected(boolean newlySelected) {
        this.newlySelected = newlySelected;
    }
}

当您第一次添加单元格时,它将被新选择并且不会呈现不同的颜色,因为它没有通过检查

!cellSelectionSet.getCellAt(row, column).isNewlySelected()

但是当您按下按钮时,您将遍历列表并将所有单元格newlySelected设置为false。

public void actionPerformed(ActionEvent e) {
    //myCellRenderer.setShowSelected(true);
    for (int i = 0; i < cellSelectionSet.getSize(); i++) {
        cellSelectionSet.getElementAt(i).setNewlySelected(false);
    }
    table.repaint();
}