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对象 , <br>
|
* 如果有多个,就会导致冲突。 <br>
|
* 如果该窗口要实现拖拽功能,必须有一个DragManage对象,<br>
|
*
|
* @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();
|
}
|
}
|
}
|
}
|