2013-07-14 50 views
1

我對Java相對比較陌生,我正在嘗試創建一個名爲VisualObject的類,其實例可以在JPanel之間拖放。爲什麼不返回對當前對象的引用總是返回相同的引用?

這是getTransferData功能VisualObject,它實現Transferable

public Object getTransferData(DataFlavor d) 
     throws UnsupportedFlavorException, IOException { 

     if (d != visualObjectDataFlavor) { 
      throw new UnsupportedFlavorException(d); 
     } 
     return this; 
    } 

然而,在TransferHandlerJPanel的I跑這條線

System.out.println(t.getTransferData(VisualObject.visualObjectDataFlavor).equals(t.getTransferData(VisualObject.visualObjectDataFlavor))); 

而且它總是返回false。我怎樣才能實際返回一個指向正在傳輸的對象的一致指針?或者有更好的方法來傳輸它?

第二個編輯:

我原來的代碼仍然低於,但問題仍然出現在這個大大簡化代碼:

package trytwo; 

import java.awt.datatransfer.DataFlavor; 
import java.awt.datatransfer.Transferable; 
import java.awt.datatransfer.UnsupportedFlavorException; 
import java.io.IOException; 

public class SimplifiedVisualObject implements Transferable { 

    public static void main(String[] args) {   
     SimplifiedVisualObject a, b; 
     a = new SimplifiedVisualObject(); 
     b = new SimplifiedVisualObject(); 
     try { 
      System.out.println(a.getTransferData(DataFlavor.imageFlavor).equals(b.getTransferData(DataFlavor.imageFlavor))); 
     } catch (UnsupportedFlavorException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public Object getTransferData(DataFlavor flavor) 
      throws UnsupportedFlavorException, IOException { 
     return this; 
    } 

    @Override 
    public DataFlavor[] getTransferDataFlavors() { 
     return null; 
    } 

    @Override 
    public boolean isDataFlavorSupported(DataFlavor flavor) { 
     return false; 
    } 

} 

編輯:

下面是三個類我寫道:VisualObjectTransferable),ObjectFrame(它在內容窗格中保存着VisualObject)和Main,它們只是創建兩個ObjectFrame s。

VisualObject

package tryone; 

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.datatransfer.DataFlavor; 
import java.awt.datatransfer.Transferable; 
import java.awt.datatransfer.UnsupportedFlavorException; 
import java.awt.geom.Ellipse2D; 
import java.io.IOException; 
import javax.swing.JComponent; 

public class VisualObject extends JComponent implements Transferable { 

    private static final long serialVersionUID = -7105793092357377791L; 
    public static DataFlavor visualObjectDataFlavor = new DataFlavor(VisualObject.class, "Visual Object"); 

    public VisualObject() { 
     setOpaque(true); 
     setLayout(null); 
    } 


    @Override 
    protected void paintComponent(Graphics g) { 
     Graphics2D g2d = (Graphics2D) g; 
     g2d.setColor(Color.black); 
     g2d.fill(new Ellipse2D.Double(0, 0,getWidth(),getHeight())); 
    } 

    @Override 
    public Transferable getTransferData(DataFlavor d) 
      throws UnsupportedFlavorException, IOException { 

     if (d != visualObjectDataFlavor) { 
      throw new UnsupportedFlavorException(d); 
     } 
     return this; 
    } 


    @Override 
    public DataFlavor[] getTransferDataFlavors() { 
     DataFlavor d[] = {visualObjectDataFlavor}; 
     return d; 
    } 


    @Override 
    public boolean isDataFlavorSupported(DataFlavor d) { 
     if (d == visualObjectDataFlavor) { 
      return false; 
     } 
     return false; 
    } 

    public VisualObject getThis() { 
     return this; 
    } 
} 

ObjectFrame

package tryone; 

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Cursor; 
import java.awt.datatransfer.Transferable; 
import java.awt.datatransfer.UnsupportedFlavorException; 
import java.awt.dnd.DnDConstants; 
import java.awt.dnd.DragGestureEvent; 
import java.awt.dnd.DragGestureListener; 
import java.awt.dnd.DragSource; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.io.IOException; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.TransferHandler; 


public class ObjectFrame extends JFrame implements DragGestureListener { 

    private static final long serialVersionUID = 4330669242071962048L; 
    protected Cursor draggingCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); 
    private JPanel panel; 



    public ObjectFrame() { 
     setVisible(true); 
     setSize(300, 400); 
     setLayout(new BorderLayout()); 
     setTitle("Object Tray"); 

     addWindowListener(new WindowAdapter() { 
      @Override 
      public void windowClosing(WindowEvent e) { 
       System.exit(0); 
      } 
     }); 

     panel = new JPanel(); 
     panel.setBackground(Color.white); 
     panel.setLayout(null); 
     add(panel, BorderLayout.CENTER); 


     final DragSource ds = new DragSource(); 
     final DragGestureListener handle = this; 

     panel.setTransferHandler(new ObjectTransferHandler()); 

     java.awt.EventQueue.invokeLater(new Runnable() { 

      public void run() { 
       VisualObject v = null; 


       v = new VisualObject(); 
       v.setSize(50, 50); 
       v.setLocation(100, 100); 
       ds.createDefaultDragGestureRecognizer(v, 
         DnDConstants.ACTION_COPY, handle); 
       panel.add(v); 

       panel.repaint(); 
      } 
     }); 
    } 

    @Override 
    public void dragGestureRecognized(DragGestureEvent dge) { 
     if (dge.getComponent() instanceof Transferable) { 
      dge.startDrag(draggingCursor, (Transferable) dge.getComponent()); 
     } 
    } 

    private class ObjectTransferHandler extends TransferHandler { 
     private static final long serialVersionUID = 5072686271469629699L; 

     public ObjectTransferHandler() { 
     } 

     public boolean canImport(TransferSupport t) { 
      if (t.isDataFlavorSupported(VisualObject.visualObjectDataFlavor)) { 
       return true; 
      } 
      return false;   
     } 

     public boolean importData(TransferSupport ts) { 
      Transferable t = ts.getTransferable(); 
      try { 
       System.out.println(t.getTransferData(VisualObject.visualObjectDataFlavor) == (t.getTransferData(VisualObject.visualObjectDataFlavor))); 

       return true; 
      } catch (UnsupportedFlavorException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      }   
      return false; 
     } 
    } 
} 

Main

package tryone; 

import javax.swing.JFrame; 

public class Main { 

    public static void main(String[] args) { 
     JFrame f1 = new ObjectFrame(); 
     JFrame f2 = new ObjectFrame(); 
    } 

} 
+1

你在'VisaualObject'中實現了'equals'和'hashcode'方法嗎?爲什麼你從這個方法而不是'Transferable'返回Object? –

+0

如果你已經實現了equals,那麼它可能總是返回false,作爲一個有趣的測試,看看==是否也返回false(==(排序))查看內存地址並測試它們是否是同一個對象) –

+0

@RohitJain ,我還沒有實現這些方法。我的理解是,左側未實現的'equals'檢查引用是否字面上相同。也許我錯了?不知道爲什麼這會返回'Object'而不是'Transferable',該方法是由Eclipse自動生成的。我應該將其改爲「可轉讓」嗎? – sync

回答

1

關於SimplifiedVisualObject版本:該getTransferData()方法換貨政... this。由於您正在創建兩個不同的實例,因此您正在比較a.equals(b),除非equals()被重寫,否則通常總是爲false。

關於你的原始問題:如果你調試你的代碼,你會發現這也是VisualObject的情況。每次您撥打getTransferData()時都會返回一個不同的實例,因此equals()比較返回false。

如果您使用DataFlavor.imageFlavor它將按預期工作,但我無法準確解釋原因。

也許當使用未知風味時,默認拖拽&拖放實現不知道如何處理它。結果是可傳輸對象在傳輸過程中被序列化和反序列化,導致始終創建不同的實例。

編輯:其實答案由Java tutorial that suggests因爲當你知道你只會傳遞本地對象(在同一應用程序內),你應該創建新DataFlavorvisualObjectDataFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=tryone.VisualObject");(把它作爲一個靜態字段在你的例子中使用一個靜態初始化塊)。這將讓系統知道您正在傳遞應用程序中的本地對象,以便它將返回通過對象比較測試的相同實例。

+0

你對** SimplifiedVisualObject **肯定是正確的,那是我的一個愚蠢的錯誤。解決問題的DataFlavor.imageFlavor也是正確的。這是目前的快速修復,但我想知道爲什麼選擇不同的味道會改變任何東西。感謝您的幫助,您已經明確瞭解問題所在。 – sync

+0

@sync缺少的部分是如何告訴DnD機制你正在傳輸本地對象,所以不需要序列化。看到我更新的回答 –

+0

,完美的作品!謝謝! – sync

相關問題