O'Reilly logo

Swing Hacks by Chris Adamson, Joshua Marinacci

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Translucent Drag-and-Drop #69
Chapter 9, Drag-and-Drop
|
353
HACK
solution is simply to display a translucent copy of the component itself,
referred to as a ghost in the code. Figure 9-10 shows a ghost in mid-drag.
This time, you will not use the package
java.awt.dnd; you’ll need your own
framework for this level of sophistication. By breaking out of the pre-built
box, you gain full control of drag-and-drop.
Drawing a Ghost
The very first thing you need is a glass pane able to draw a translucent pic-
ture over the UI. A glass pane is nothing more than a transparent
JPanel.
The code of
GhostGlassPane is very simple, as shown in Example 9-7.
Figure 9-10. A ghost is a translucent copy of a Swing component
Example 9-7. Creating a glass pane for ghosting
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
public class GhostGlassPane extends JPanel
{
private AlphaComposite composite;
private BufferedImage dragged = null;
private Point location = new Point(0, 0);
354
|
Chapter 9, Drag-and-Drop
#69 Translucent Drag-and-Drop
HACK
This glass pane has two properties: the picture to be displayed and its loca-
tion. To make the picture translucent, use an
AlphaComposite instance.
Besides colors, strokes, and painters, Java2D drawings can be affected by
composites that define how the newly drawn pixels are mixed with the
underlying pixels. In this case, you want the new pixels—i.e., the picture—
to be drawn at 50% of their initial opacity. You can change the second
parameter of
getInstance( ) to choose the opacity. The valid value range is
from a totally opaque
0.0 to a totally transparent 1.0. An AlphaComposite can
be used to define how the alpha channels of the source (the pixels being
drawn), and the target (the existing pixels) are mixed together. You can
select the mixing mode with the first parameter of
getInstance( ) and refer
to the documentation of
AlphaComposite to get a comprehensive list of possi-
ble modes. It turns out that the
AlphaComposite.SRC_OVER composite gives
the best result for our job.
public GhostGlassPane( )
{
setOpaque(false);
composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
}
public void setImage(BufferedImage dragged)
{
this.dragged = dragged;
}
public void setPoint(Point location)
{
this.location = location;
}
public void paintComponent(Graphics g)
{
if (dragged == null)
return;
Graphics2D g2 = (Graphics2D) g;
g2.setComposite(composite);
g2.drawImage(dragged,
(int) (location.getX( ) - (dragged.getWidth(this) / 2)),
(int) (location.getY( ) - (dragged.getHeight(this) / 2)),
null);
}
}
Example 9-7. Creating a glass pane for ghosting (continued)
Translucent Drag-and-Drop #69
Chapter 9, Drag-and-Drop
|
355
HACK
The only job of the paintComponent( ) will be to draw the dragged picture.
Therefore, there is no need to call
super.paintComponent( ), as it will per-
form unnecessary operations.
Do not forget to set the composite in this method, or you
might draw the picture fully opaque.
The center of the picture is painted at the location specified in setLocation( ).
This means assuming the location given is the location of the mouse cursor.
Now, you’ve got a fully functional glass pane, and you just need to add it to
a Swing frame:
glassPane = new GhostGlassPane( );
setGlassPane(glassPane);
Also, do not forget that a glass pane is not visible by default: you will have to
call
setVisible(true) when a drag-and-drop operation is initiated. The final
step is the activation of drag-and-drop on components requiring it. You can
use a picture as drag-and-drop feedback:
JLabel label = new JLabel("New Sale");
GhostDropAdapter pictureAdapter;
pictureAdapter = new GhostPictureAdapter(glassPane,
"new_sale",
"images/new_sale.png")
label.addMouseListener(pictureAdapter);
label.addMouseMotionListener(new GhostMotionAdapter(glassPane));
You can also use a ghost feedback:
JButton button = new JButton("Ghost Feedback"));
GhostDropAdapter componentAdapter;
componentAdapter = new GhostComponentAdapter(glassPane, "button_pushed");
button.addMouseListener(componentAdapter);
button.addMouseMotionListener(new GhostMotionAdapter(glassPane));
Whatever choice you make, you need two adapters to perform drag-and-
drop. The first one is an adapter for the
MouseListener interface. It can be
either a
GhostPictureAdapter, to handle pictures, or a GhostComponentAdapter,
to handle a component ghost. The role of this adapter is to handle the begin-
ning and the end of a drag-and-drop gesture. When a drop action is per-
formed, an event is fired to every
GhostDropListener registered by the
adapter. The code in Example 9-8 shows how
GhostComponentAdapter works.
The code of
GhostPictureAdapter is almost the same, and it’s left to you to
check out (all the code for this book is online; visit http://www.oreilly.com/
catalog/swinghks).
356
|
Chapter 9, Drag-and-Drop
#69 Translucent Drag-and-Drop
HACK
Example 9-8. Handling component ghosts
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
public class GhostComponentAdapter extends GhostDropAdapter
{
public GhostComponentAdapter(GhostGlassPane glassPane, String action) {
super(glassPane, action);
}
public void mousePressed(MouseEvent e)
{
Component c = e.getComponent( );
BufferedImage image = new BufferedImage(c.getWidth( ),
c.getHeight( ),
BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics( );
c.paint(g);
glassPane.setVisible(true);
Point p = (Point) e.getPoint().clone( );
SwingUtilities.convertPointToScreen(p, c);
SwingUtilities.convertPointFromScreen(p, glassPane);
glassPane.setPoint(p);
glassPane.setImage(image);
glassPane.repaint( );
}
public void mouseReleased(MouseEvent e)
{
Component c = e.getComponent( );
Point p = (Point) e.getPoint().clone( );
SwingUtilities.convertPointToScreen(p, c);
Point eventPoint = (Point) p.clone( );
SwingUtilities.convertPointFromScreen(p, glassPane);
glassPane.setPoint(p);
glassPane.setVisible(false);
glassPane.setImage(null);
fireGhostDropEvent(new GhostDropEvent(action, eventPoint));
}
}

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required