本文實例講述了Java利用滑鼠的拖放來實作交換程式資料的方法,即所謂的滑鼠拖放功能。滑鼠的拖放功能在圖形化系統中非常常用,Java 提供了java.awt.dnd 和java.awt.datatransfer 套件來支援此功能。本例示範如何在程式中實作拖放的實作方法,當在視窗上部的「Hello World!」標籤點下滑鼠,並拖曳至視窗下部的文字方塊放開,則在文字方塊中將新增「Hello World !
此程式功能具體的實作思路和方法為:在滑鼠拖曳的實作中,兩個最重要的概念是拖曳來源和放置目標,即drag source 和drop target。拖曳來源和放置目標都是與可視化的組件相關聯的(如果不可視,還怎麼拖呢?!)。拖放技術的實質就是將拖曳來源元件上的資料傳遞到放置目標元件上,因此從底層看,拖曳和上例中的剪貼簿技術很接近。
拖曳來源的實作:拖曳來源類別必須先建立一個DragGestureRecognizer 實例,表示該類別是拖曳來源元件類別或包含拖曳來源元件。可以透過呼叫DataSource 物件的createDefaultDragGestureRecognizer()方法來實現。具體的實現如下:
int action = DnDConstants.ACTION_COPY_OR_MOVE; //拖曳的型別ds.createDefaultDragGestureRecognizer(this,action,this);
上面的語句表明, 拖曳來源元件是本類別本身的實例對象, 要完成的拖曳的種類是DnDConstants.ACTION_COPY_OR_MOVE 型的,實作DragGestureListener 介面的類別是本類別。拖曳來源一般實作DragGestureListener 接口,該介面中定義了一個dragGestureRecognized()方法,當開始拖曳是,DragGestureListener 監聽到事件,隨即轉入dragGestureRecognized()方法處理事件,如將拖曳來源的資料傳送出去。具體代碼:
public void dragGestureRecognized(DragGestureEvent dge) {//throw new java.lang.UnsupportedOperationException("Method dragGestureRecognized() not yet implemented.");try{Transferable tr = new StringSelection(this.");try{Transferable tr = new StringSelection(this.F.文字作為數據,由Transferable物件包裝//開始拖拽,設定遊標為DragSource.DefaultCopyNoDrop 形,拖放的資料是tr 對象,DragSourceListener 是本類別dge.startDrag(DragSource.DefaultCopyNoDrop,tr,this);}catch(Exception err){err. printStackTrace();}}
拖曳來源還得實現DragSourceListener 接口,該接口定義了拖曳相關的各狀態的事件處理方法。如dragEnter、dragOver、dropActionChanged、dragExit等方法。本例中,將實作dragEnter()方法來設定拖曳時的遊標形狀,其他的方法為空方法。具體實作程式碼如下:
public void dragEnter(DragSourceDragEvent dsde) {//throw new java.lang.UnsupportedOperationException("Method dragEnter() not yet implemented.");DragSourceContext dsc = dsde.getDragSourceContext(); //得到拖曳來源的上下文參考來源的上下文參考//設定拖曳時的遊標形狀int action = dsde.getDropAction();if ((action&DnDConstants.ACTION_COPY)!=0)dsc.setCursor(DragSource.DefaultCopyDrop);elsedsc.setCursor(DragSource.DefaultCopyNoDrop);}
放置目標的實作:放置目標的類別中必須先建立一個DragTarget 實例,來表示本類別是放置目標元件類別或包含放置目標元件,實作如下:
new DropTarget(this.jTextField1,DnDConstants.ACTION_COPY_OR_MOVE,this);
上面的語句表明, 放置目標是this.jTextField1 對象, 拖放操作是DnDConstants.ACTION_COPY_OR_MOVE 型的,而實作DropTargetListener 介面的類別是本類別。與DrafSourceListener 相對應,放置目標或其所在類別一般實作DropTargetListener 介面。此介面也定義了許多的方法,如dragEnter、dragOver 等,用於處理當拖放過程進入不同階段時的事件。本例只關心drop()方法,即在放置目標元件上放開滑鼠時的事件處理,一般用來處理傳遞到的數據,如本例中將在JTextField 元件上顯示傳遞來的文字數據,其他方法為空方法,具體程式碼如下:
public void drop(DropTargetDropEvent dtde) {//throw new java.lang.UnsupportedOperationException("Method drop() not yet implemented.");try{Transferable tr = dtde.getTransferable(); //得到傳遞來的資料物件/ /處理資料對象,得到其中的文字資訊if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)){dtde.acceptDrop(dtde.getDropAction());String s = (String) tr.getTransferData(DataFlavor.stringFlavor);this.jTextField1.setText(this.getTextFd1. +s); //在放置目標上顯示從拖曳來源傳遞來的文字訊息dtde.dropComplete(true);}else{dtde.rejectDrop();}}catch(Exception err){err.printStackTrace();}}
程式碼:
1.新建一個Project,取名為JDragAndDropDemo。
2.新建一個Application,取名為JDragAndDropDemo;主視窗取名為MainFrame,標題為JDragAndDropDemo。
3.新建一個Class,取名為DragJLabel,繼承JLabel 類別。
4.利用wizards|implements interface 使DragJLabel 類別實作DragGestureListener 、DragSourceListener 介面。
5.在類別DragJLabel 中新增新的屬性DragSource ds,程式碼如下:
class DragJLabel extends JLabel implements DragGestureListener, DragSourceListener {DragSource ds = DragSource.getDefaultDragSource(); //建立DragSource 實例…}
6.編寫DragJLabel 類別的建構方法。
public DragJLabel(String title,int alignment){super(title,alignment); //使用父類別的方法int action = DnDConstants.ACTION_COPY_OR_MOVE;ds.createDefaultDragGestureRecognizer(this,action,this); //建立}
7.實作DragJLabel 類別中的dragGestureRecognized()方法,包裝並傳送資料。
public void dragGestureRecognized(DragGestureEvent dge) {//throw new java.lang.UnsupportedOperationException("Method dragGestureRecognized() not yet implemented.");try{Transferable tr = new StringSelection(this.getText());dge.startDrag(DragSource.DefaultCopyNoDrop,tr,this);}catch(Exception err){err.printStackTrace();}}
8.實作DragJLabel 類別中的dragEnter()方法,設定遊標的形狀。
public void dragEnter(DragSourceDragEvent dsde) {//throw new java.lang.UnsupportedOperationException("Method dragEnter() not yet implemented.");DragSourceContext dsc = dsde.getDragSourceContext();int action = deSource. ((action&DnDConstants.ACTION_COPY)!=0)dsc.setCursor(DragSource.DefaultCopyDrop);elsedsc.setCursor(DragSource.DefaultCopyNoDrop);}
9.在MainFrame 類別的設計視窗中下部新增一個JTextField 元件,並在類別中建立一個DragJLabel實例,具體程式碼如下:
public class MainFrame extends JFrame implements DropTargetListener {private JPanel contentPane;private BorderLayout borderLayout1 = new BorderLayout();private JTextField jTextField1 = new JTextField());private JTextField jTextField1 = new JTextField()DabelD WorldJragd/ !",SwingConstants.CENTER);……}
10.編寫MainFrame 類別的初始化方法jbInit(),設定元件的初始屬性,並建立一個新的DropTarget實例,程式碼如下:
private void jbInit() throws Exception {//setIconImage(Toolkit.getDefaultToolkit().createImage(MainFrame.class.getResource("[Your Icon]")));contentPane = (JPanel) this.getp. (borderLayout1);this.setSize(new Dimension(410, 114));this.setTitle("JDragAndDropDemo");jTextField1.setFont(new java.awt.Font("Dialog", 0, 14));contentPane.add(jTextField1, BorderLayout.SOUTH);contentPanePanePaneout. .add(this.label,BorderLayout.NORTH);new DropTarget(this.jTextField1,DnDConstants.ACTION_COPY_OR_MOVE,this);}
11.利用wizards|implements interface 使MainFrame 類別實作DropTargetListener 介面。
12.實作繼承自DropTargetListener 介面的方法drop(),處理傳遞來的數據,具體程式碼如下:
public void drop(DropTargetDropEvent dtde) {//throw new java.lang.UnsupportedOperationException("Method drop() not yet implemented.");try{Transferable tr = dtde.getTransferable();if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)){dtde.acceptDrop(dtde.getDropAction());String s = (String) tr.getTransferData(DataFlavor.stringFlavor);this.jTextField1.setText(this.jTextField1.getText()+s);dtde.dropComplete(true);}else{dtde.rejectDrop();}}catch(Exception err){Exception err){Exception err){ err.printStackTrace();}}