2013-07-14 4 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; 
    } 

Однако в TransferHandler для моих JPanel с бегаю эта линия

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; 
    } 

} 

Edit:

Ниже приведены три класса, которые Я написал: VisualObject (Transferable), ObjectFrame (в котором содержится VisualObject s в его области содержимого) и 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

Вы реализовали метод 'equals' и' hashcode' в 'VisaualObject'? и почему вы возвращаете 'Object' из этого метода вместо' Transferable'? –

+0

Если вы внедрили equals плохо, он всегда может вернуть значение false, так как интересный тест показывает, что == также возвращает false (== (sort)) смотрит адрес памяти и проверяет, являются ли они одним и тем же объектом) –

+0

@RohitJain , Я не реализовал эти методы. Мое понимание заключалось в том, что оставшиеся нереализованные «равные» проверки, если ссылка буквально одна и та же. Возможно, я ошибаюсь? Не знаю, почему это возвращает 'Object' вместо' Transferable', этот метод был автоматически сгенерирован Eclipse. Должен ли я изменить его на «Transferable»? – sync

ответ

1

Относительно SimplifiedVisualObject версии: getTransferData() метод RETU rn this. Поскольку вы создаете два разных экземпляра, вы эффективно сравниваете a.equals(b), который, как правило, всегда является ложным, если equals() не является избыточным.

Что касается вашего оригинального вопроса: Если вы отлаживаете свой код, вы увидите, что это также в случае с VisualObject. Каждый раз, когда вы вызываете getTransferData(), возвращается другой экземпляр, поэтому сравнение equals() возвращает false.

Если вы используете DataFlavor.imageFlavor, он будет работать должным образом, хотя я не могу точно объяснить, почему.

Возможно, при использовании неизвестного аромата по умолчанию перетащить & drop реализация не знает, как с ним справиться. В результате переносимый объект сериализуется и де-сериализуется во время передачи, что приводит к созданию другого экземпляра.

Edit: На самом деле ответ дается Java tutorial that suggests, что, когда вы знаете, что вы будете только передавать объекты локально (внутри одного приложения), вы должны создать свой новый DataFlavor как visualObjectDataFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=tryone.VisualObject"); (чтобы иметь его в качестве статического поля как в вашем примере используйте статический блок инициализатора). Это позволит системе знать, что вы переносите локальный объект в приложение, чтобы он возвращал тот же экземпляр, который передавал ваш тест сравнения объектов.

+0

. Вы определенно правы в ** SimplifiedVisualObject **, это была глупая ошибка с моей стороны. Вы также правы в DataFlavor.imageFlavor, устраняющем проблему. Это быстро исправить, но мне интересно, почему выбор другого аромата меняет что-то. Спасибо за помощь, вы определенно начали пролить свет на то, где проблема. – sync

+0

@sync Недостающая часть заключалась в том, как сообщить механизму DnD, что вы переносите локальные объекты, поэтому нет необходимости в сериализации. См. Мой обновленный ответ –

+0

, который отлично работает! Спасибо! – sync

Смежные вопросы