Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JTable change cell background at mouse click - after release change background back?

Tags:

java

swing

jtable

my question is, how to solve following problem:

If i click on a cell in a JTable, i want to change its background. If i release the mousebutton, i want the background change back to normal color.

Is that possible?

Greetings ayk

like image 520
ayk Avatar asked Dec 27 '22 14:12

ayk


2 Answers

For doing it in the visual realm you need

  • a MouseListener which sets some state in cell-coordinates on pressed and resets that state on released
  • a PropertyChangeListener listeneng to that state which repaints the cell on change
  • a custom renderer which sets a custom background for the cell that is flagged

some code for the listeners

    MouseListener l = new MouseAdapter() {

        /** 
         * @inherited <p>
         */
        @Override
        public void mousePressed(MouseEvent e) {
            JTable table = (JTable) e.getComponent();
            int col = table.columnAtPoint(e.getPoint());
            int row = table.rowAtPoint(e.getPoint());
            if (col < 0 || row < 0) {
                table.putClientProperty("pressedCell", null);
            } else {
                table.putClientProperty("pressedCell", new Point(col, row));
            }
        }

        /** 
         * @inherited <p>
         */
        @Override
        public void mouseReleased(MouseEvent e) {
            ((JTable) e.getComponent()).putClientProperty("pressedCell", null);
        }

    };
    table.addMouseListener(l);
    PropertyChangeListener property = new PropertyChangeListener() {

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            JTable table = (JTable) evt.getSource();
            Point cell = evt.getNewValue() != null ? 
                    (Point) evt.getNewValue() : (Point) evt.getOldValue();
            if (cell != null) table.repaint(table.getCellRect(cell.y, cell.x, false));        
        }

    };
    table.addPropertyChangeListener("pressedCell", property);

Highlighting the cell in SwingX (cant resist :-)

    HighlightPredicate predicate = new HighlightPredicate() {

        @Override
        public boolean isHighlighted(Component renderer, ComponentAdapter adapter) {
            Point p = (Point) adapter.getComponent().getClientProperty("pressedCell");
            return p != null && p.x == adapter.column && p.y == adapter.row;

        }
    };
    table.addHighlighter(new ColorHighlighter(predicate, Color.YELLOW, null, Color.YELLOW, null));

For core Swing, either implement a custom TableCellRenderer or subclass the JTable and override prepareRenderer to set the background color according to the cell flag, as explained in Rob's Table Row Rendering

like image 154
kleopatra Avatar answered Mar 14 '23 16:03

kleopatra


in your renderer you have to overide hasFocus

for example

enter image description here

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

public class TableRenderer extends JFrame {

    private static final long serialVersionUID = 1L;
    private JTable table;
    private String[] columnNames = {"Date", "String", "Centered", "Integer", "Boolean"};
    private Object[][] data = {
        {new Date(), "A", "A", new Integer(1), true},
        {new Date(), "B", "B", new Integer(2), false},
        {new Date(), "C", "C", new Integer(10), null},
        {new Date(), "D", "D", new Integer(4), false}
    };

    public TableRenderer() {
        DefaultTableModel model = new DefaultTableModel(data, columnNames);
        table = new JTable(model) {

            private static final long serialVersionUID = 1L;
            //  Returning the Class of each column will allow different
            //  renderers to be used based on Class

            @Override
            public Class getColumnClass(int column) {
                return getValueAt(0, column).getClass();
            }
        };
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);
        getContentPane().add(scrollPane);

        //  Override default renderer on a specific Class
        TableCellRenderer colorRenderer = new ColorRenderer();
        table.setDefaultRenderer(String.class, colorRenderer);

        //  Override default renderer for a specific column
        DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
        centerRenderer.setHorizontalAlignment(JLabel.CENTER);
        table.getColumnModel().getColumn(2).setCellRenderer(centerRenderer);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                TableRenderer frame = new TableRenderer();
                frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    /*
     **  Color the focused cell
     */
    private class ColorRenderer extends DefaultTableCellRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getTableCellRendererComponent(
                JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            if (hasFocus) {
                setBackground(Color.cyan);
            } else if (isSelected) {
                setBackground(table.getSelectionBackground());
            } else {
                setBackground(table.getBackground());
            }
            return this;
        }
    }
}
like image 27
mKorbel Avatar answered Mar 14 '23 16:03

mKorbel