1

In my application, I'd like to create a rollover effect with the rows of a JTable. For example, when the mouse enters the row, the background color of that row will change; conversely, the color of that row will return to normal when the mouse exits that row.

How can i do this?

ddk
  • 159
  • 1
  • 4
  • 13

2 Answers2

2

Use the below code, which will give you an idea about applying rollover effect with rows of a JTable.

import java.awt.Component;
import java.awt.event.MouseEvent;

import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import javax.swing.table.*;

public class RollOverTable extends JTable {

    private int rollOverRowIndex = -1;

    public RollOverTable(TableModel model) {
        super(model);
        RollOverListener lst = new RollOverListener();
        addMouseMotionListener(lst);
        addMouseListener(lst);
    }

    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
        Component c = super.prepareRenderer(renderer, row, column);
        if( isRowSelected(row) || (row == rollOverRowIndex) ) {
            c.setForeground(getSelectionForeground());
            c.setBackground(getSelectionBackground());
        }
        else {
            c.setForeground(getForeground());
            c.setBackground(getBackground());
        }
        return c;
    }


    private class RollOverListener extends MouseInputAdapter {

        public void mouseExited(MouseEvent e) {
            rollOverRowIndex = -1;
            repaint();
        }

        public void mouseMoved(MouseEvent e) {
            int row = rowAtPoint(e.getPoint());
            if( row != rollOverRowIndex ) {
                rollOverRowIndex = row;
                repaint();
            }
        }
    }
}
Jigar Mistry
  • 352
  • 2
  • 12
  • 3
    If this is not your code, maybe some attribution seems just :-). Seen [here](https://community.oracle.com/thread/1389010) – Paul Samsotha Nov 22 '14 at 09:24
  • @ddk It works fine. What part is giving you problems. Please show your attempt at using this code, that is not working – Paul Samsotha Nov 22 '14 at 09:25
  • 1
    @ddk Do you know how to use a `TableModel`? All you need to do is a pass a `TableModel` into this table's constructor. – Paul Samsotha Nov 22 '14 at 09:57
  • Is there any difference between TableModel and DefaultTableModel? – ddk Nov 22 '14 at 10:03
  • @ddk `TableModel` is an interface. `DefaultTableModel` implements it, so, no there is no difference, meaning you can use it (`DefaultTableModel`) – Paul Samsotha Nov 22 '14 at 10:06
  • @ddk here is the sample working [source code link](https://www.dropbox.com/s/oot35dyu3cqc18c/JTable%20RollOver%20Sample.zip?dl=0) – Jigar Mistry Nov 22 '14 at 11:33
0

Above answer will not work in case the table have lot of rows and we use mouse wheel to scroll the table. Mouse will be on a new row but that rollover effect will be still on the old row.

Here is my modification to solve the problem.

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

public class RollOverTable extends JTable {

    private Color rollOverBackground = new Color(233,239,248);
    private Color rollOverForeground = UIManager.getDefaults().getColor("windowText");

    private int rollOverRowIndex = -1;
    private boolean dispatchedEvent = false;
    private RollOverListener lst = null;
    private JScrollPane scp = null;

    public RollOverTable(TableModel model) {
        super(model);
        lst = new RollOverListener();
        addMouseMotionListener(lst);
        addMouseListener(lst);
        addMouseWheelListener(lst);
    }

    public Color getRollOverBackground() {
        return rollOverBackground;
    }

    public void setRollOverBackground(Color value) {
        rollOverBackground = value;
    }

    public Color getRollOverForeground() {
        return rollOverForeground;
    }

    public void setRollOverForeground(Color value) {
        rollOverForeground = value;
    }

    @Override
    public void addNotify() {
        super.addNotify();
        for (Component c = this; c != null; c = c.getParent())
            if (c instanceof JScrollPane) {
                scp = (JScrollPane) c;
                scp.addMouseWheelListener(new RollOverMouseWheelListener(this));
                break;    
            }
    }

    @Override
    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
        Component c = super.prepareRenderer(renderer, row, column);
        if (isRowSelected(row)) {
            c.setForeground(getSelectionForeground());
            c.setBackground(getSelectionBackground());
        } else if (row == rollOverRowIndex) {
            c.setForeground(getRollOverForeground());
            c.setBackground(getRollOverBackground());
        } else {
            c.setForeground(getForeground());
            c.setBackground(getBackground());
        }
        return c;
    }

    protected void repaintRow(int row) {
        if (row == -1) return;
        int modelRow = convertRowIndexToModel(row);
        ((AbstractTableModel)getModel()).fireTableRowsUpdated(modelRow, modelRow);
    }

    private class RollOverListener extends MouseInputAdapter {

        @Override
        public void mouseExited(MouseEvent e) {
            if (rollOverRowIndex != -1) {
                repaintRow(rollOverRowIndex);
                rollOverRowIndex = -1;
            }
        }

        @Override
        public void mouseMoved(MouseEvent e) {
            int row = rowAtPoint(e.getPoint());
            if (row != rollOverRowIndex) {
                repaintRow(rollOverRowIndex);
                rollOverRowIndex = row;
                repaintRow(rollOverRowIndex);
            }
        }

        @Override
        public void mouseWheelMoved(MouseWheelEvent e) {
            if (rollOverRowIndex != -1) {
                repaintRow(rollOverRowIndex);
                rollOverRowIndex = -1;
                dispatchedEvent = true;
                scp.dispatchEvent(SwingUtilities.convertMouseEvent(
                        e.getComponent(), e, scp));
            }
        }
    }

    private class RollOverMouseWheelListener extends MouseInputAdapter {

        private final RollOverTable table;

        public RollOverMouseWheelListener(RollOverTable table) {
            this.table = table;
        }

        @Override
        public void mouseWheelMoved(MouseWheelEvent e) {
            if (dispatchedEvent) {
                dispatchedEvent = false;
                Point point = SwingUtilities.convertPoint(
                        e.getComponent(), e.getPoint(), table);
                int row = table.rowAtPoint(point);
                if (rollOverRowIndex != row) {
                    rollOverRowIndex = row;
                    table.repaintRow(rollOverRowIndex);
                }
            }
        }
    }

}
bbhar
  • 599
  • 5
  • 8
  • To whom it may concern: Running this code with a simple implementation of AbstractTableModel, I found I had to replace the repaintRow method content with RollOverTable.this.repaint() to make the hgihlighting work. I'm not sure why this is though. – steveman Jul 18 '18 at 08:00