0

enter image description here Hi All, I'm trying to add a checkbox in Jtable header to select and deselect all, that is working fine except that the header renderer is different that the rest of the cells. can you please help me to place the checkbox in the center of the Jtable header? another problem is the header for that column border is gone.

thanks in advance, Maan

JTable

    import java.awt.Component;
    import java.awt.Point;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import javax.swing.JCheckBox;
    import javax.swing.JComponent;
    import javax.swing.JLabel;
    import javax.swing.JTable;
    import javax.swing.SwingConstants;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.JTableHeader;
    import javax.swing.table.TableCellRenderer;
    
    
    public class EditableHeaderRenderer extends JCheckBox implements TableCellRenderer
    {
    
      private JTable table = null;
      private MouseEventReposter reporter = null;
      private JComponent editor;
    
    
      public EditableHeaderRenderer(JComponent editor)
      {
        this.editor = editor;
        this.editor.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
      }
    
      @Override
      public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
      {
        if (table != null && this.table != table)
        {
          this.table = table;
          final JTableHeader header = table.getTableHeader();
    
          if (header != null)
          {
            DefaultTableCellRenderer centerRenderer = (DefaultTableCellRenderer) header.getDefaultRenderer();
            centerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
            header.setDefaultRenderer(centerRenderer);
            table.repaint();
    
    
            this.editor.setBackground(header.getTable().getBackground());
            this.editor.setFont(header.getTable().getFont());
            reporter = new MouseEventReposter(header, col, this.editor);
            header.addMouseListener(reporter);
          }
        }
    
        if (reporter != null)
          reporter.setColumn(col);
    
        return this.editor;
      }

1 Answers1

0

To each their own but I'm not convinced that what you are trying to do is the way to go, so... I'm just going to provide an alternative. The code below is based from code originally posted is SO by @trashgod way back in 2011. It's basically a good alternative to what you're doing.

enter image description here

Read the comments in the code:

/**
 * Original code was created and provided by @trashgod way back in 2011 and was 
 * acquired from this StackOverflow Post:
 *
 *     https://stackoverflow.com/a/7137801/4725875
 *
 * Give the entire thread a good read.
 *
 * This is a good example of how you can carry out a "Select All"
 * on a specific JTable column. I modified this code to some extent
 * to utilize the standard Header cell component rather than a toggle 
 * button. This should play pretty good in most Look & Feels. I also 
 * changed header names and added a class to apply ToolTips to the 
 * Header cells.
 *
 * I think this is a good alternative to placing an actual CheckBox
 * into a Header cell. The JTable Header is meant to be descriptive
 * rather than actionary even though it does have sorting capabilities.
 * In my opinion, all Header cells should always maintain a good form
 * of descriptive quality with regards to the columns they represent.
 *
 * A Header cell with a CheckBox in it that states "Check All" doesn't
 * really describe what all the CheckBoxes are for within that column
 * <b>unless</b> the CheckBoxes are merely used to select all the rows for
 * processing of some kind in which case, it would be far easier to use a 
 * single line of code "anywhere" to basically do the same thing:
 * <p>
 *        jTable1.selectAll();
 * 
 * Of course, this may not always be the case.
 * 
 * This is a runnable code and has been tested using Java8. Note that when 
 * you run this application, there will be tool tips that pop up when the 
 * mouse pointer moves over the Header cells. The sort capability has been
 * disabled for the "Confirm Purchase" header cell. If you click on this cell 
 * then all CheckBoxes within the column will be selected. If you click on it 
 * again, all CheckBoxes will be un-selected. Note the tool tip for this header 
 * cell for either state.
 * 
 * Basic HTML has been used to provide color (and bold for the checkmark 
 * character) to the Header cell text. 
 * 
 * I think this is better than placing a CheckBox into the Header cell but hey,
 * to each their own.
 */
package selectallheadertest;

import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
import javax.swing.table.*;


public class SelectAllHeaderTest {

    public static final int BOOLEAN_COL = 2;
    public static final String PLAIN_ALL = "Confirm Purchase";
    public static final String PLAIN_NONE = "✓ Confirm Purchase";
    public static final String HTML_ALL = "<html><font color=blue>Confirm Purchase</font></html>";
    public static final String HTML_NONE = "<html><font color=red><b>✓</b></font>"
            + "<font color=blue> Confirm Purchase</font></html>";
    public static final String SELECT_ALL = "<html> Click to Select All <br><center><font size='2'>"
            + "(toggle)</font></center></html>";
    public static final String UNSELECT_All = "<html> Click to Unselect All <br>"
            + "<center><font size='2'>(toggle)</font></center></html>";
    private static final Object colNames[] = {"Sale Item 1", "Sale Item 2", HTML_ALL};
    private DefaultTableModel model = new DefaultTableModel(null, colNames) {
        private static final long serialVersionUID = 2020L;

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            if (columnIndex == BOOLEAN_COL) {
                return Boolean.class;
            }
            else {
                return String.class;
            }
        }
    };
    public final JTable table = new JTable(model);

    // Fill the table with data...
    public void create() {
        for (int x = 1; x < 20; x++) {
            model.addRow(new Object[]{
                "Row " + x + ", Col 1", "Row " + x + ", Col 2", false
            });
        }
        table.setAutoCreateRowSorter(true);
        table.setPreferredScrollableViewportSize(new Dimension(400, 160));
        TableColumn tc = table.getColumnModel().getColumn(BOOLEAN_COL);

        // Set initial ToolTips for Header..
        String[] columnHeaderToolTips = {"On Sale Item 1",
            "On Sale Item 2",
            "<html> Click to Select All <br>"
            + "<center><font size='2'>(toggle)</font>"
            + "</center></html>"};
        setJTableHeaderColumnToolTips(table, columnHeaderToolTips);

        /* Remove the Header column sorting capabilities for
           the column with all the CheckBoxes which is Header
           column 3 (index 2).               */
        @SuppressWarnings("unchecked")
        DefaultRowSorter<TableModel, String> sorter
                = (DefaultRowSorter<TableModel, String>) table.getRowSorter();
        sorter.setSortable(2, false);
        JTableHeader header = table.getTableHeader();
        header.addMouseListener(new TableHeaderMouseListener(table));

        JFrame f = new JFrame(" Select All Demo ");
        f.setAlwaysOnTop(true);
        f.add(new JScrollPane(table));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }

    /**
     * Sets Tooltips to each JTable Header cell.<br><br>
     * <p>
     * This method utilizes the TokenJar JTableColumnHeaderToolTips subclass.
     * <p>
     * <b>Example Usage:</b><pre>
     *
     *          String[] columnToolTips = {"First Name",
     *                                     "Last Name",
     *                                     "The person's address",
     *                                     "The person's phone number",
     *                                     "The person's age",
     *                                     "The person's salary"};
     *          SetJTableHeaderColumnToolTips(recordsTable, columnToolTips);</pre>
     *
     * @param table          (JTable) The JTable variable name to apply Header
     *                       tool-tips to.<br>
     *
     * @param columnToolTips (String[] Array) The tooltip strings to apply to
     *                       each header cell.
     */
    public void setJTableHeaderColumnToolTips(JTable table, String[] columnToolTips) {
        JTableHeader tableHeader = table.getTableHeader();

        // See the JTableColumnHeaderToolTips SubClass found 
        // at the end of this Class.
        JTableColumnHeaderToolTips toolTips = new JTableColumnHeaderToolTips();
        for (int col = 0; col < table.getColumnCount(); col++) {
            TableColumn columnIndex = table.getColumnModel().getColumn(col);
            toolTips.setHeaderColumnToolTip(columnIndex, columnToolTips[col]);
        }
        tableHeader.addMouseMotionListener(toolTips);
    }

    public static void main(String[] args) {
        /* LOOK & FEEL: 
         * If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;

                }
            }
        }
        catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(SelectAllHeaderTest.class
                    .getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new SelectAllHeaderTest().create();
            }
        });
    }

    // Mouse Listener for JTable Header
    class TableHeaderMouseListener extends MouseAdapter {

        private JTable table;

        TableHeaderMouseListener(JTable table) {
            this.table = table;
        }

        @Override
        public void mouseClicked(MouseEvent evt) {
            boolean state = false;
            JTableHeader header = (JTableHeader) evt.getSource();

            TableColumnModel colModel = table.getColumnModel();
            int colIndex = colModel.getColumnIndexAtX(evt.getX());
            TableColumn column = null;
            if (colIndex >= 0) {
                String colName = colModel.getColumn(colIndex).getHeaderValue()
                                         .toString().replaceAll("<.+?>", "");
                column = colModel.getColumn(colIndex);
                if (colIndex == BOOLEAN_COL) {
                    column.setHeaderValue(colName.equals(PLAIN_ALL) ? HTML_NONE : HTML_ALL);
                    header.setToolTipText(colName.equals(PLAIN_ALL) ? UNSELECT_All : SELECT_ALL);
                    state = colName.equals(PLAIN_ALL);
                    for (int r = 0; r < table.getRowCount(); r++) {
                        table.setValueAt(state, r, colIndex);
                    }
                }
            }
        }

        // Just in case you might want these....
        @Override
        public void mouseEntered(MouseEvent evt) {
            // Here if you want it...
        }

        @Override
        public void mouseExited(MouseEvent evt) {
            // Here if you want it...
        }
    }

    // Class for setting JTable Header ToolTips
    class JTableColumnHeaderToolTips extends MouseMotionAdapter {

        TableColumn curCol;
        Map headerColumnTips = new HashMap();

        public void setHeaderColumnToolTip(TableColumn column, String tooltip) {
            if (tooltip == null) {
                headerColumnTips.remove(column);
            }
            else {
                headerColumnTips.put(column, tooltip);
            }
        }

        @Override
        public void mouseMoved(MouseEvent event) {
            JTableHeader header = (JTableHeader) event.getSource();
            JTable table = header.getTable();
            TableColumnModel colModel = table.getColumnModel();
            int colIndex = colModel.getColumnIndexAtX(event.getX());
            TableColumn column = null;
            String colName = "";
            if (colIndex >= 0) {
                // Get Header Column Text and Remove HTML Tags (if any)...
                colName = colModel.getColumn(colIndex).getHeaderValue()
                                            .toString().replaceAll("<.+?>", "");
                column = colModel.getColumn(colIndex);
            }
            if (column != curCol) {
                if (colIndex == BOOLEAN_COL) {
                    header.setToolTipText(colName.equals(PLAIN_ALL) ? SELECT_ALL : UNSELECT_All);
                }
                else {
                    header.setToolTipText((String) headerColumnTips.get(column));
                }
                curCol = column;
            }
        }
    }
}
DevilsHnd - 退職した
  • 8,739
  • 2
  • 19
  • 22
  • thanks for your reply, the code is working fine regarding the select all part, what im missing is only that the check box in the header is not aligned with the check boxes in the table and I couldn't center it above it. – Maan Boushi Apr 26 '22 at 08:47