JTreeTable DnD crazy blinking drop cursor
Asked Answered
M

1

6

I am using a slightly modified version of the Sun's example JTreeTable backed by my own model. That would be the third example (bookmarks one at http://java.sun.com/products/jfc/tsc/articles/bookmarks/).

Everything works as expected except drag and drop support. I wanted DnD which is more like what a JTree provides. Since JTreeTable is an extended JTable it provides the JTable.DropLocation class for determining drop locations which does not offer enough information when dropping stuff into the tree rendered column of the JTreeTable (no path and no child index). I've already solved that by creating a custom DropLocation class which is based on a combination of JTable and JTree versions of it. I've also modified the paint method of the TreeTableCellRenderer class which is provided by the mentioned JTreeTable implementation to show this new information to the user (she is now able to see if the new node will be placed inside, before or after the selected node if inside the tree column, as you would expect from a JTree).

There is one problem though. The mouse cursor is going crazy when the drop location is being rendered inside the tree column. It appears and then disappears a few milliseconds later or this happens so fast that the drag cursor is not even shown. This happens with the unmodified Sun's example too. I am completely in the dark as to why this is happening. Did find another person with the same problem at http://www.java.net/node/663106, but the solution provided there seems to set the component's drop location to null and cannot be retrieved using JTreeTable.getDropLocation() method any more. I need this to convert it to my modified DropLocation and then paint stuff based on it. I am so close to a proper solution for my use case that I can taste it. This cursor blinking thing is the only obstacle in my way. Any ideas?

Using Java 1.6.

P.S.: I've decided for a custom JTreeTable and not for one of the existing components (like Netbeans Outline or JXTreeTable) because they all appear to be suffering from the JTable.DropLocation problem and do not offer support for dropping before or after the selected tree node (only inside). If you know of a component which does provide such functionality I'd be glad to hear about it.

Murky answered 23/11, 2011 at 10:36 Comment(1)
In post scriptum of this question I wrongfully accuse org.netbeans.swing.Outline and JXTreeTable of not being able to support dropping before or after the selected tree node. This is not true as these components do in fact support it. They both indirectly subclass a JTable. While it's true that JTable.DropLocation does not provide path information, you can always obtain it through table row and column which is provided by it. Had I known this, I would have never bothered rolling my own component. I advise against it.Murky
C
10

that sounds like a manifestion of core bug #6700748 (can't verify, that darn bug parade takes ages to connect to ..). So citing from the fix in JXTreeTable:

    /**
     * {@inheritDoc} <p>
     * 
     * Overridden to hack around #766-swingx: cursor flickering in DnD
     * when dragging over tree column. This is a core bug (#6700748) related
     * to painting the rendering component on a CellRendererPane. A trick
     * around is to let this return false. <p>
     * 
     * This implementation applies the trick, that is returns false always. 
     * The hack can be disabled by setting the treeTable's client property
     * DROP_HACK_FLAG_KEY to Boolean.FALSE. 
     * 
     */
    @Override
    public boolean isVisible() {
        return shouldApplyDropHack() ? false : super.isVisible();
    }


    /**
     * Returns a boolean indicating whether the drop hack should be applied.
     * 
     * @return a boolean indicating whether the drop hack should be applied.
     */
    protected boolean shouldApplyDropHack() {
        return !Boolean.FALSE.equals(treeTable.getClientProperty(DROP_HACK_FLAG_KEY));
    }
Cola answered 23/11, 2011 at 11:40 Comment(1)
Indeed. This is the correct answer. Overriding TreeTableCellRenderer.isVisible() to always return false does the trick.Murky

© 2022 - 2024 — McMap. All rights reserved.