package com.vci.client.portal.Formdesign;
import java.awt.AlphaComposite;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import com.vci.client.portal.Formdesign.object.ObjectUtil;
/**
* 实现组件拖拽的类
*
* 参考swing hacks
*
* @author liudi
*
*/
public class ControlDragManager extends Object {
private JFrame frame;
private JComponent target;
private ControlGhostGlassPane glass = null;
private Component dragSource;
public static final Image right_img = ObjectUtil.getImage("right.png");
public static final Image wrong_img = ObjectUtil.getImage("wrong.png");
/**
* @param frame
* 参数frame为要实现拖拽的frame,frame中一定只能有一个DragManage对象 ,
* 如果有多个,就会导致冲突。
* 如果该窗口要实现拖拽功能,必须有一个DragManage对象,
*
* @param target
* 拖拽目标
*/
public ControlDragManager(JFrame frame, JComponent target) {
this.frame = frame;
this.target = target;
// target.setLayout(null);
this.frame.setGlassPane(this.glass = new ControlGhostGlassPane());
}
/**
* 指定能拖拽的组件
*
*
* @param souce
* 被拖拽的组件
*/
public void canDrag(Component source) {
DragAction action = null;
action = new DragAction(glass, target);
source.addMouseListener(action);
source.addMouseMotionListener(action);
dragSource = source;
}
/**
* 返回拖拽源对象
*
* @return
*/
public Component getDragSource() {
return dragSource;
}
/**
* 用来画图形做跨组件的视觉效果的面板
*
*
*/
static class ControlGhostGlassPane extends JPanel {
private static final long serialVersionUID = 1L;
private AlphaComposite composite;
private BufferedImage dragged = null;
private int state;
private Point location = new Point(0, 0);
public static final int STATE_ACCEPT = 1;
public static final int STATE_UNACCEPT = 2;
public static final int STATE_NOMAR = -1;
public ControlGhostGlassPane() {
setOpaque(false);
// 半透明效果
composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
0.5f);
}
public void setState(int state) {
this.state = state;
}
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;
}
// 在蒙版上画图
int x = (int) (location.getX() - (dragged.getWidth(this) / 2));
int y = (int) (location.getY() - (dragged.getHeight(this) / 2));
Graphics2D g2 = (Graphics2D) g;
g2.setComposite(composite);
g2.drawImage(dragged, x, y, null);
switch (state) {
case STATE_ACCEPT:
g2.drawImage(right_img, x + dragged.getWidth(this), y, this);
break;
case STATE_UNACCEPT:
g2.drawImage(wrong_img, x + dragged.getWidth(this), y, this);
break;
case STATE_NOMAR:
break;
}
}
}
/**
* 拖拽动作
*
* @author liudi
*
*/
class DragAction implements MouseMotionListener, MouseListener {
private ControlGhostGlassPane glassPane;
private JComponent targetComp;
private boolean flag;
public DragAction(ControlGhostGlassPane glassPane, JComponent targetComp) {
this.glassPane = glassPane;
this.targetComp = targetComp;
flag = false;
}
public void mouseDragged(MouseEvent e) {
flag = true;
Component c = e.getComponent();
Point p = (Point) e.getPoint().clone();
SwingUtilities.convertPointToScreen(p, c);
Point eventPoint = (Point) p.clone();
SwingUtilities.convertPointFromScreen(p, glassPane);
// 鼠标是否在目标控件的上方
SwingUtilities.convertPointFromScreen(eventPoint, targetComp);
int state = targetComp.contains(eventPoint) ? ControlGhostGlassPane.STATE_ACCEPT
: ControlGhostGlassPane.STATE_UNACCEPT;
glassPane.setState(state);
glassPane.setPoint(p);
glassPane.repaint();
}
public void mouseMoved(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
flag = false;
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) {
if (!flag) {
glassPane.setImage(null);
glassPane.repaint();
glassPane.setVisible(false);
glassPane.setImage(null);
return;
}
ControlDragManager.this.dragSource = null;
System.gc();
final Component c = e.getComponent();
final Point p = (Point) e.getPoint().clone();
SwingUtilities.convertPointToScreen(p, c);
final Point eventPoint = (Point) p.clone();
SwingUtilities.convertPointFromScreen(p, glassPane);
SwingUtilities.convertPointFromScreen(eventPoint, targetComp);
glassPane.setPoint(p);
glassPane.repaint();
/*
* 移动控件有一下几种情况
*
* 1、控件在原来的位置之上,没动
*
* 2、控件从原来的位置移动到目标控件的位置
*
* 3、控件已经在目标的位置上,然后自动在目标的位置
*
* 4、控件在目标的位置上移动的其他控件上
*/
// 还没有进入目标组件
if (!c.getParent().equals(targetComp)
&& !targetComp.contains(eventPoint)) {
new Thread(new Runnable() {
public void run() {
// 没有接受
glassPane.setState(ControlGhostGlassPane.STATE_NOMAR);
// 拿到组件的原始位置
Point cp = (Point) c.getLocationOnScreen().clone();
// 转成glass位置
SwingUtilities.convertPointFromScreen(cp, glassPane);
// 当前组件在glass上的位置
int x = cp.x;
int y = cp.y;
// 拿到当前显示的图片的位置
int cx = p.x - (c.getWidth() / 2);
int cy = p.y - (c.getHeight() / 2);
int subX = (x - cx) / 10;
int subY = (y - cy) / 10;
x = p.x - (c.getWidth() / 2);
y = p.y - (c.getHeight() / 2);
for (int i = 0; i < 11; i++) {
x += subX;
y += subY;
if (i == 10) {
x = cp.x;
y = cp.y;
}
cx = x + (c.getWidth() / 2);
cy = y + (c.getHeight() / 2);
glassPane.setPoint(new Point(cx, cy));
glassPane.repaint();
try {
Thread.sleep(20);
} catch (Exception e2) {
e2.printStackTrace();
}
}
glassPane.setVisible(false);
glassPane.setImage(null);
}
}).start();
return;
}
// 移动到目标的位置
if (!c.getParent().equals(targetComp)
&& targetComp.contains(eventPoint)) {
// 复制出新的组件
Component obj = (Component) ObjectUtil.cloneObject(c);
// 让他能拖动
ControlDragManager.this.canDrag(obj);
// 添加到目标位置
targetComp.add(obj);
Point p2 = (Point) e.getPoint().clone();
SwingUtilities.convertPointToScreen(p2, c);
SwingUtilities.convertPointFromScreen(p2, targetComp);
int x = p2.x - obj.getWidth() / 2;
int y = p2.y - obj.getHeight() / 2;
obj.setLocation(x, y);
targetComp.repaint();
targetComp.updateUI();
glassPane.setVisible(false);
glassPane.setImage(null);
return;
}
// 控件已经在目标的位置上,然后自动在目标的位置
if (c.getParent().equals(targetComp)
&& targetComp.contains(eventPoint)) {
Point p2 = (Point) e.getPoint().clone();
SwingUtilities.convertPointToScreen(p2, c);
SwingUtilities.convertPointFromScreen(p2, targetComp);
int x = p2.x - c.getWidth() / 2;
int y = p2.y - c.getHeight() / 2;
c.setLocation(x, y);
targetComp.repaint();
glassPane.setVisible(false);
glassPane.setImage(null);
return;
}
// 控件在目标的位置上移动的其他控件上
if (c.getParent().equals(targetComp)
&& !targetComp.contains(eventPoint)) {
// 没有接受
glassPane.setState(ControlGhostGlassPane.STATE_NOMAR);
// 这里记录图形的
new Thread(new Runnable() {
public void run() {
// 组件在glass上的位置
Point cp = (Point) c.getLocationOnScreen().clone();
// 转成glass位置
SwingUtilities.convertPointFromScreen(cp, glassPane);
// 拿到组件的位置
int x = cp.x;
int y = cp.y;
// 拿到当前鼠标的位置
int cx = eventPoint.x;
int cy = eventPoint.y;
int subX = (x - cx) / 10;
int subY = (y - cy) / 10;
x = eventPoint.x;
y = eventPoint.y;
for (int i = 0; i < 11; i++) {
x += subX;
y += subY;
if (i == 10) {
x = cp.x;
y = cp.y;
}
cx = x + (c.getWidth() / 2);
cy = y + (c.getHeight() / 2);
glassPane.setPoint(new Point(cx, cy));
glassPane.repaint();
try {
Thread.sleep(20);
} catch (Exception e2) {
e2.printStackTrace();
}
}
glassPane.setVisible(false);
glassPane.setImage(null);
}
}).start();
}
}
}
}