今年初学Java ,五周时间却啥也没学到,都睡了。。
最后老师布置了个大作业,实现一个在线的问卷调查,其中有一项就是实现不同项目分类,如下图~
图 -1
童鞋们多用树来做,拖拽的确不怎么好弄。但显然拖拽将更有魅力,更具亲和性!
可是自己什么也没听进去,老师也没怎么讲( 现在大学最后悔的事就是逃课太少,老师讲的大都 P 用没有 !) 最后只能看一点学一点,慢慢前行啦!
首先自己就像做了个demo ,看看拖拽到底是怎么用的 ~
刚开始自己给鼠标的各种动作,enter 、 exit 、 over 、 dragged 诸多事件,但总感力不从心,毕竟自己一边学一边用, o( ︶︿︶ )o 唉 ~
之后就发现了Java 的 dnd 机制,甚爽!何为 dnd , drag and drop 就是拖和放,这是两个动作。假设我想把一个 JButton 拖到一个 JPanel 里面,那么就给 JButton 加个 drag 侦听事件,给 JPanel 加个 drop 事件,那么这时我们就要问了,上图那么多 JButton ,那么多 JPanel 谁认识谁啊,我怎么知道你拖的是哪个?!这是我们的 Transfer able 闪亮登场了,这是一个接口,必须 找个实现的类啊 , 看来看去就是 StringSelection , ( 因为这俩单词我都认识 = =),它有什么作用呢?这就相当于一个用来专门传递信号的邮递员,此邮递员很是忠于职守,很忠贞啊,每次只携带一封信件!所以这样假设大写字母 A-Z 们给小写字母 a-z 发邮件,大家只有这个邮递员 (Transferable) ,那么只要给每个字母一个唯一的标识就 OK 了 ~ 到这里相信大家对 dnd 已经有点了解了,下面看我的 demo 吧 ~
先Show 张图 ~
图2
这里我们需要将上面三个 Jbutton随便拖到下面两个带色的 JPanel 中,而且可以随便的拽入拽出。考虑到最终图 -1 所需要的效果,我决定自定义控件 JButton 和 JPanel ,不然光给每个 JButton 和 JPanel 加拖拽属性就会把我累死的,即使有 for 可以用 ...
先上下代码~
=====================DraggableJButton.java=============================
DraggableJButton继承子JButton,实现DragGestureListener, DragSourceListener两个接口~这样它就成3P的杂交产物了,请允许我的邪恶。。于是此组件就具有了三者的属性!
dragSource=DragSource.getDefaultDragSource();
dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE,this);
此处我们先创建一个Drag源,然后给它创建一个默认拖拽手势识别器,不懂得拿着有道挨个单词翻译(比如偶。。)
JDK做如下解释:
================
createDefaultDragGestureRecognizer
public DragGestureRecognizer createDefaultDragGestureRecognizer (Component c, int actions, DragGestureListener dgl)
-
创建一个新的
DragGestureRecognizer
,为此DragSource
实现DragGestureRecognizer
的默认抽象子类并在新创建的对象上设置指定的Component
和DragGestureListener
。 对于此DragSource
,默认值是MouseDragGestureRecognizer
。 -
-
参数:
-
c
- 该识别器的Component
目标 -
actions
- 允许的源操作 -
dgl
- 要通知的DragGestureListener
返回:
-
新的
DragGestureRecognizer
,如果Toolkit.createDragGestureRecognizer
没有为所请求的DragGestureRecognizer
子类提供实现并返回null
,则此方法返回null
- ===============
-
因为我们此处需要操作的就是这个JButton,第一个参数即为this,动作为ACTION_MOVE,索要通知的监听器也在次JButton内,所以第三参数为this~
然后就将事件通知到下面的监听器~
唉?这不是Transferable么?对啦,大家现在可以看到我们把getID()值传递给邮递员Transferable,于是乎drag源开始了生命之旅startDrag~JDK如下解释:
=======================
startDrag
public void startDrag (DragGestureEvent trigger, Cursor dragCursor, Transferable transferable, DragSourceListener dsl) throws InvalidDnDOperationException
-
在给定发起拖动的
DragGestureEvent
、使用的初始Cursor
、拖动的Transferable
目标数据和DragSourceListener
的情况下开始拖动。 -
-
参数:
-
trigger
- 发起拖动的DragGestureEvent
-
dragCursor
- 初始Cursor
,或默认为null
-
transferable
- 拖动的目标数据 -
dsl
-DragSourceListener
抛出:
-
- 如果 Drag 和 Drop 系统不能发起拖动操作,或者用户试图在现有拖动操作仍在进行时开始拖动。java.awt.dnd.InvalidDnDOperationException
-
InvalidDnDOperationException
-
===================================
四个参数我就不多说了~相信大家都能看懂的~现在我们的Drag部分已经完成了,再瞅瞅我们的Drop~
同DraggableJButton,我也定制了自己JPanel,代码如下:
这里大家可以类比上面的DraggableJButton进行分析。
到这里我们的JButton,JPanel都定制好了,在主界面设置布局就可以把他们当成普通的的JButton进行布局,只不过不同的是
这些JButton和JPanel具有了dnd功能,很方便使用了。
这这里有点不得不说,就是自己发现Transferable可以传递JButton!!并且可以用:
dJButtond=(DraggableJButton)tf.getTransferData(DataFlavor.stringFlavor);来获取dJButton,也可以进行操作,只不过此处的JButton是
原来的JButton一个副本,传递的是JButton的各种信息,比如大小啊,位置啊样式边框啊什么的,而通过传递ID后再历遍所有JButton
操作的则是真正的原JButton,大家可以在自己需要的不用情况下选择不同的方式~
主界面布局文件如下~
==================================
哈哈,现在基本的拖拽就可以实现了~
==========================================================
PS: 用了令众人鄙视的绝对定位,没办法,demo,而且感觉java布局很高深。。。代码风格不好,诸位莫喷。。。
第一次写自己的编程新的,走不稳路的小菜!
这就是自己前些日子磨磨唧唧几天搞定的,总算小有成就,老师评价:很有钻研精神。你妹的,你要是都教了我不就省了钻研了!
。但心里听着还真是舒服。之后他又说了句:只编程序是不行的,某清华毕业的毕业五年一直都在编程,而我们学校某人既会写文档又会编程不久就当项目经理了。我当时就想抽他了,我写程序是为了自己高兴,是兴趣,像爱一个女人一样爱着程序,而不管其它。真想对老师说,我只是个写程序的,我只想写好自己的程序,其他关我鸟事!
We just love code!