2

I have following method in my class which extends JTable:

  protected void setTableCursor(Cursor cursor) {
// data gathering
cursor = (cursor != null) ? cursor : Cursor.getDefaultCursor();
JTableHeader header = getTableHeader();

// set
header.setCursor(cursor);
setCursor(cursor);
}

This method is called from time to time to show WAIT cursor when table is updated from DB.

The problem with it is that now when i try and resize columns I can't see default SPLIT cursor. How this can be fixed? So I need to add some code in order for mouse cursor always show split cursor when mouse is near column's edge.

Please also check example below. To reproduce issue just double-click on table header exactly on columns divider:

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;
abstract public class DemoTable extends JTable
{
protected DemoTable() {
    super();
    compose(false);
}
private void compose(boolean allowMultipleSelection) {
    setModel(new DefaultTableModel(getColumnNames(), 0));
    setColumnSelectionAllowed(false);
    getSelectionModel().setSelectionMode(allowMultipleSelection ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION : ListSelectionModel.SINGLE_SELECTION);
    getTableHeader().setReorderingAllowed(false);
    getTableHeader().addMouseListener(new ColumnResizeListener(this));
}

protected void setTableCursor(Cursor cursor) {
    // data gathering
    cursor = (cursor != null) ? cursor : null;
    JTableHeader header = getTableHeader();
    // set
    header.setCursor(cursor);
    setCursor(cursor);
}

public void adjustColumnWidth(int column) {
    setPreferredColumnWidth(column, getPreferredSizeForColumn(column));
}

private int getPreferredSizeForColumn(int columnIndex) {
    // base setup
    int preferredWidth = 0;
    int rowCount = getRowCount();
    TableColumnModel columnModel = getColumnModel();
    TableColumn column = columnModel.getColumn(columnIndex);

    TableCellRenderer renderer;
    Component rendererComponent = null;

    // header
    renderer = column.getHeaderRenderer();
    if (renderer != null) {
        rendererComponent = renderer.getTableCellRendererComponent(this, column.getHeaderValue(), false, false, 0, 0);
        if (rendererComponent != null) {
            preferredWidth = rendererComponent.getPreferredSize().width;
        }
    }

    // rendered values
    Object value;
    for (int row = 0; row < rowCount; row++) {
        // base setup
        value = getValueAt(row, columnIndex);

        // renderer lookup
        renderer = getCellRenderer(row, columnIndex);
        if (renderer != null)
            rendererComponent = renderer.getTableCellRendererComponent(this, value, false, false, row, columnIndex);
        rendererComponent = (rendererComponent == null) ? new JLabel((value == null) ? "" : value.toString()) : rendererComponent;

        // calculate the preferred size
        preferredWidth = Math.max(preferredWidth, rendererComponent.getPreferredSize().width);
    }

    // exit
    return (preferredWidth <= 0) ? 25 : (preferredWidth + 15);
}

public void adjustColumnWidths() {

    Thread updateThread = new Thread()
    {
        public void run() {
            try {
                SwingUtilities.invokeAndWait(new Runnable()
                {
                    public void run() {
                        int columns = getModel().getColumnCount();
                        Map<Integer, Integer> preferredWidths = new HashMap<Integer, Integer>();
                        for (int column = 0; column < columns; column++)
                            preferredWidths.put(column, getPreferredSizeForColumn(column));

                        // run the sets
                        for (Map.Entry<Integer, Integer> column : preferredWidths.entrySet())
                            setPreferredColumnWidth(column.getKey(), column.getValue());
                    }
                });

                // pause momentarily to let the cursor update take place
                sleep(75);
            }
            catch (Exception e) {
                // ignore
            }
            finally {
                setTableCursor(null);
            }
        }
    };

    // execute the thread
    updateThread.start();
    if (updateThread.isAlive())
        setTableCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
}

private void setPreferredColumnWidth(int column, int preferredWidth) {
    getColumnModel().getColumn(column).setPreferredWidth(preferredWidth);
}

abstract protected String[] getColumnNames();

@Override
public boolean isCellEditable(int row, int column) {
    return false;
}

private static class ColumnResizeListener extends MouseAdapter
{
    DemoTable table;
    public ColumnResizeListener(DemoTable table) {
        super();

        // attribute initialization
        this.table = table;
    }
    @Override
    public void mouseClicked(MouseEvent e) {
        if (e.getSource() instanceof JTableHeader) {
            // data gathering
            int clicks = e.getClickCount();

            // single click
            if (clicks == 1) {
                int column = table.getColumnModel().getColumnIndexAtX(e.getX());
                table.adjustColumnWidth(column);
            }

            // double-click
            else if (clicks == 2)
                table.adjustColumnWidths();
        }
    }
}

public static void main(String args[]) {
    final DemoTable table = new DemoTable() {
        @Override
        protected String[] getColumnNames() {
            return new String[]{"one","two"};
        }
    };
    JFrame frame = new JFrame("Demo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    ((DefaultTableModel)table.getModel()).addRow(new String[]{"1", "2"});
    ((DefaultTableModel)table.getModel()).addRow(new String[]{"1","2"});
    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());
    panel.add(table.getTableHeader(), BorderLayout.NORTH);
    panel.add(table, BorderLayout.CENTER);
    frame.add(panel);
    frame.pack();
    panel.setSize(new Dimension(200, 100));
    frame.setVisible(true);
}
}
GrayR
  • 1,395
  • 2
  • 19
  • 32
  • 1
    there are two/three reasons why is that possible for better help sooner please edit your post with [SSCCE](http://sscce.org/) – mKorbel Mar 05 '12 at 12:53
  • 1
    the cursor reset logic is wrong - there are two "default" cursors, depending on the position of the mouse (one when inside the resize region the other when outside). You can distinguish between the two by checking for the resizing column. – kleopatra Mar 05 '12 at 13:55
  • @kleopatra : how to perform such check ? – GrayR Mar 05 '12 at 14:01
  • 1
    until this moment (waiting for @kleopatra's reply) you have to check her answer [here](http://stackoverflow.com/questions/8830642/cursor-icon-does-not-change-after-trigerring-setcursor-method/8835448#8835448), +1 for posting a SSCCE – mKorbel Mar 05 '12 at 14:28

1 Answers1

2

Instead of default cursor set both cursors (for header and table) to null when no need to show WAIT cursor.

StanislavL
  • 56,971
  • 9
  • 68
  • 98
  • Thanks! Unfortunately didn't work for my code, though I agree that what you are suggesting is better then initial code. – GrayR Mar 05 '12 at 13:48
  • turns out problem also was in setting Panel containing table to setEnabled(false) :( . After fixing that, and using comments and answers in this topic I was able to fix it. – GrayR Mar 16 '12 at 01:17