views:

53

answers:

2

Is there any way to get a cell renderer to respond to mouse events, such as mouseovers?

+3  A: 

Never tried it but I guess you would need to:

a) create a custom renderer to paint the cell in two states

b) you need to keep track of which cell should currently be painted in the "mouse over" state

c) add a mouse listener to track mouse entered/exited and mouseMoved. With each event you would need to update a variable that tracks which cell the mouse is positioned over. You can use the columnAtPoint() and rowAtPoint() methods of JTable

d) when the mouse leaves a cell you need to invoke repaint() on the cell. You can use the getCellRect() method to determine which cell to repaint

e) when the mouse enters a cell you need to reset the cell value for the "mouse over" state and then repaint the cell.

camickr
To elaborate a bit: Remember that cell renderer (in table, list, combo, etc) is always just a rubber stamp, so you need to add a mouse listener to your table, then delegate to your custom renderer/editor, using `columnAtPoint` and `rowAtPoint` to figure out where the mouse point is, as @camickr mentioned.
Geoffrey Zheng
How should I tell a jtable to retrieve and render a fresh cell renderer at my command?
NewlessClubie
The repaint() request should do this.
camickr
A: 

Ok, so I've tried implement camickr's approach, but I've encountered some very nasty problem in the process. I've added a MouseMotionListener to JTable to track the current and previous cell and added some methods that instruct a renderer about which component to return and then repaint the appropriate cell. However, for some odd reason each cell is repainted twice even though there was only one repaint request. Basically, I was able to highlight a cell on a mouse rollover, but it was impossible to remove highlighting from a cell once the mouse cursor leaved it. After initial confusion I've decided to do this in a different way. I've added a method which invokes the editor whe the mouse is over the cell and then added some code that stops editing as soon as the state of JToggleButton (my rendering and editing component) is changed. My current code looks like this :

package guipkg;

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;

public class Grid extends JTable implements MouseListener {

int currentCellColumn = -1;
int currentCellRow = -1;
int previousCellColumn = -1;
int previousCellRow = -1;

public void detectCellAtCursor (MouseEvent e) {
    Point hit = e.getPoint();
    int hitColumn = columnAtPoint(hit);
    int hitRow = rowAtPoint(hit);
    if (currentCellRow != hitRow || currentCellColumn != hitColumn) {
        this.editCellAt(hitRow, hitColumn);
        currentCellRow = hitRow;
        currentCellColumn = hitColumn;
    }

}


}







package guipkg;

import javax.swing.table.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;


public class TCEditor extends AbstractCellEditor implements TableCellEditor  {

    /**
     * A toggle button which will serve as a cell editing component
     */

    JToggleButton togglebutton = new JToggleButton();





    public Component getTableCellEditorComponent (JTable Table, Object value, boolean isSelected, int rindex, int cindex) {

        /**
         * We're adding an action listener here to stop editing as soon as the state of JToggleButton is switched.
         * This way data model is updated immediately. Otherwise updating will only occur after we've started to
         * edit another cell.
         */

        togglebutton.addActionListener(new ActionListener() {
            public void actionPerformed (ActionEvent e) {
                stopCellEditing();
            }
        });


        if (value.toString().equals("true")) {
            togglebutton.setSelected(true);
        }
 else {
            togglebutton.setSelected(false);
 }
        togglebutton.setBorderPainted(false);
        return togglebutton;
    }

    public Object getCellEditorValue () {
        return togglebutton.isSelected();
    }


}

I hope that will help someone

NewlessClubie