Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
JTrees has been covered already in Java Tip 97: Add Drag and Drop to Your JTrees. I encourage you to read that tip first to get a good understanding of the drag-and-drop paradigm.
The code I present in this tip has the following design goals:
JTreenode being dragged
JTreenodes right and left without keyboard interaction
As a bonus, I have included support for the
Autoscroll interface so that the
JTree content is automatically scrolled when the mouse nears the viewport's edge during a drag operation. This is implemented as
described in Eckstein, Loy, and Wood's Java Swing, which explains the autoscrolling process adequately, so I won't elaborate here.
Arguably, these capabilities should all be part of a Swing look-and-feel implementation, but I found them easier to implement
as part of a
JTree class extension. In spite of the number of goals, the actual code involved is quite minimal.
Figure 1 is an example of what you would see during a drag operation after implementing this tip -- the food folder is about to be dropped after the football node.
Figure 1. Screenshot of CTree drag image in action
To emulate this
JTree behavior, you must change both the
DragGestureListener and the
You add code to the
dragGestureRecognized() method to figure out which
JTree node is being dragged, and then build a
BufferedImage to represent the node during the drag operation.
First, find out where the mouse is clicked relative to the selected tree node's bounding rectangle. You'll need this later to keep the drag image positioned at the same distance from the mouse pointer as the node is being dragged.
Point ptDragOrigin = e.getDragOrigin(); TreePath path = getPathForLocation(ptDragOrigin.x, ptDragOrigin.y); Rectangle raPath = getPathBounds(path); m_ptOffset.setLocation(ptDragOrigin.x-raPath.x, ptDragOrigin.y-raPath.y);
Now, ask the tree cell renderer (if you are using the
DefaultTreeCellRenderer, the renderer is a
JLabel) to render itself into a
BufferedImage, using a
Graphics2D graphics context set up to create a semi-transparent image. The result is a ghosted version of the original tree node that
won't interfere with the ability to see the underlying
JTree nodes as they are dragged over.
// Get the tree cell renderer JLabel lbl = (JLabel) getCellRenderer().getTreeCellRendererComponent ( this, // tree path.getLastPathComponent(), // value false, // isSelected isExpanded(path), // isExpanded getModel().isLeaf(path.getLastPathComponent()), // isLeaf 0, // row false // hasFocus ); // The layout manager normally does this... lbl.setSize((int)raPath.getWidth(), (int)raPath.getHeight()); // Get a buffered image of the selection for dragging a ghost image _imgGhost = new BufferedImage ( (int)raPath.getWidth(), (int)raPath.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE ); // Get a graphics context for this image Graphics2D g2 = _imgGhost.createGraphics(); // Make the image ghostlike g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 0.5f)); // Ask the cell renderer to paint itself into the BufferedImage lbl.paint(g2);
To make the ghosted
JLabel look more flash, you also paint under the text with a
GradientPaint that fades from left to right: