Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JTable: How to get the cell as a component for a given position

I made an interactive Calendar as JTable, however, I would like to change the background colour for some of the cells based on data I have. I figured out how I can get the position of the cell I need to edit but I have no idea how to get the cell at that position as a component so I can edit the cell background and foreground.

So basically I have the (x,y) position of the cell. I want to use that and get the cell to change its background colour.

This is how I create my calendar:

public static JTable createInteractiveCalender(int month, int year) {       

    JTable calender =  new JTable(Calender.getMonthsCalender(month, year), new String[] {"Su","Mo","Tu","Wed","Th","Fri","Sat"}){
         public boolean isCellEditable(int row, int column) {                
                return false;               
        };
    };
    calender.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    calender.setCellSelectionEnabled(true);

    return calender;
}

This is how I get the dates I want to be marked:

public static ArrayList<Date> getDatesInSpecificMonth(ArrayList<Date> allDates, int month) {

DateFormat df = new SimpleDateFormat("MM");
ArrayList<Date> dates = allDates;
for (Date d: dates)
    if(Integer.parseInt(df.format(d)) != month)
        dates.remove(d);
    return dates;
}

This is where I got stuck trying to mark the dates on the calendar:

public static void markDatesOnCalender(DefaultTableModel model, Section sec, int datesToMark, int month, int year) {
        ArrayList<Date> dates = Calender.getDatesInSpecificMonth(sec.getSelectedDatesforSection(datesToMark),month);
        DateFormat df = new SimpleDateFormat("dd");

        for (Date d: dates) {
            model.getValueAt(getCellPosition(model,df.format(d))[0],getCellPosition(model, d

f.format(d))[1]);



/*
         I have method that gets the cell position of 'd', however I need to get the                    
         */
        }                       
    //TODO 1
}

Thank you

like image 382
BlacKnight BK Avatar asked May 18 '17 12:05

BlacKnight BK


1 Answers

The cells of a JTable are not components in the conventional sense, i.e. you can't get them as child components of the JTable component.

Instead, when the JTabel is rendered, for each cell a TableCellRenderer provides a JComponent which is used to paint that cell at the required position, in the method TableCellRenderer.getTableCellRendererComponent(...).

Note that the JComponent provided by TableCellRenderer.getTableCellRendererComponent(...) is not added to the component tree, but is used ad hoc to paint the corresponding table cell. In fact, most TableCellRenderer implementations use the same component instance for all cells, setting anew the relevant properties (most notably the text to be displayed) for each cell.

So, in your case, what you have to do is to store the relevant properties that drive the coloring of the cells in the cell data, then use a custom TabelCellRenderer. The renderer reads those properties and returns a JComponent which is configured based on those properties.

For example: The class Cell represents the content of your table cells. What class exactly you use here depends on the table model you want to use. It could be as simple as String, but if you want to render your table cells based on some property, you need to use a table model based on a class which can hold that property, hence the custom class Cell:

class Cell{
   ...
   String text;
   boolean isHighlighted;
   ...
}

class MyTableCellRenderer implements TableCellRenderer{
    // cellLabel will be used to render each cell. Note that
    // this component is re-used for painting each cell, we
    // don't have separate instances for all cells.
    private JLabel cellLabel=new JLabel();

    @Override
    public Component getTableCellRendererComponent(
        JTable table,
        Object value,
        boolean isSelected,
        boolean hasFocus,
        int row,
        int column) {

        Cell cell=(Cell)value;
        cellLabel.setText(cell.getText());
        if(cell.isHighlighted)
            cellLabel.setForeground(Color.RED);
    }    
}         

Note that you have to set the TableCellRenderer, and you can do it for specific column classes:

table.setDefaultRenderer(columnClass, renderer);

And lastly, once you have changed the properties of cells, you have to force a repaint of the JTable. As @trashgod pointed out, when you correctly update your table model and notify its listeners, the JTable should repaint automatically (as it is a TableModelListener which registers with the model and listens for changes to the model).

like image 179
Markus Fischer Avatar answered Oct 03 '22 21:10

Markus Fischer