2013-07-14 48 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

相关问题