Reputation: 373
I want to create a JTable and color its cells permanently by the click of a button (pretty like excel in coloring cells).So far, every cell I select, it gets in an ArrayList<Cell>
.
First of all, I want for every cell in the list to be colored permanently when I click the button (this is the difference from code I found). Shoud I have to use a statememnt like this table.getColumnModel().getColumn(column).setCellRenderer(this);
?
It is a compilable code and if you debug it, you will see that when the button is clicked, I cannot access getTableCellRendererComponent() method. Why is that happening? I would appreciate if you could tell me your opinions.
(Note: it's a reproduce of a huge program, so it's a little big messy and hard-coded in some places. Couldn't make it smaller for what I want to solve).
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;
}
}
}
Class 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;
}
}
Upvotes: 2
Views: 814
Reputation: 208944
Main problem:
table.setDefaultRenderer(Integer.class, myCellRenderer);
Should be
table.setDefaultRenderer(Object.class, myCellRenderer);
This will get your cells to change color. But then you have a the problem where after you press the button, each cell you select automatically changes color, because of the showSelected
property is set to true. Who knows, maybe that's how you want it.
Also another problem is with the cells staying the selection color. The problem if with your check statement
if(showSelected && table.isCellSelected(row, column)){
Once you make more selections, the original selections is cleared. A fix would be to check against the CellSelectionSet
to see if it contains the cell, but also to check if it's newly selected or not. Something like
if (cellSelectionSet.contains(row, column)
&& !cellSelectionSet.getCellAt(row, column).isNewlySelected())
I added a method getCellAt
to your CellSelectionSet
public Cell getCellAt(int row, int column) {
Cell c = null;
for (Cell cell : cells) {
if (cell.is(row, column)) {
c = cell;
}
}
return c;
}
And also a flag in the Cell
class to check if it's newlySelected
. The default is true
class Cell {
private boolean newlySelected = true;
public boolean isNewlySelected() {
return newlySelected;
}
public void setNewlySelected(boolean newlySelected) {
this.newlySelected = newlySelected;
}
}
When you first add the cell, it will be newly selected and will not render the different color, as it doesn't pass the check
!cellSelectionSet.getCellAt(row, column).isNewlySelected()
But when you press the button, you iterate through the list and set all the cell newlySelected
to false.
public void actionPerformed(ActionEvent e) {
//myCellRenderer.setShowSelected(true);
for (int i = 0; i < cellSelectionSet.getSize(); i++) {
cellSelectionSet.getElementAt(i).setNewlySelected(false);
}
table.repaint();
}
Upvotes: 2