Help understanding class parts.

Well im still stuck on this dang DnD stuff. Here is a working class that I am trying to implement (take the right peices from) to make my DnD work correctly from label fields (equiped area) to a list (inventory) area. Ive got over the following class for days now and tried a couple of different things but need some help understanding whats exactly going on in it to see what i need and how to do it.

Or if there is a better way to do it please let me know :slight_smile:


import java.awt.*;
import java.awt.event.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;
import javax.swing.*;
import java.io.*;

public class Drag1 extends JFrame 
implements DragGestureListener, DragSourceListener, DropTargetListener
{
static String items[] = { "Item 1", "Item No. 2", "The Third Item!" };

Container cpane;
DropTarget mytarget;
DragSource mysource;
DragGestureRecognizer dgr;

JLabel source1;
JList list1;
JTextArea text1;
DefaultListModel lmod;

public Drag1() {
super("Drag1 Test");
cpane = getContentPane();
cpane.setLayout(new BorderLayout());

source1 = new JLabel("Drag Source Label - drag me!");
lmod = new DefaultListModel();
list1 = new JList(lmod);
for(int i = 0; i < items.length; i++)
lmod.addElement(items[i]);
text1 = new JTextArea("Drag from the label to\nthe list, then drop!", 
5, 24);

mysource = new DragSource();

mytarget = new DropTarget(list1, 
DnDConstants.ACTION_COPY_OR_MOVE, this);

dgr = mysource.createDefaultDragGestureRecognizer(source1,
DnDConstants.ACTION_COPY_OR_MOVE, this);

cpane.add("North", source1);
cpane.add("Center", list1);
cpane.add("South", text1);
text1.setBackground(Color.pink);
setBounds(100, 100, 320, 460);
setVisible(true);
}

public void dragGestureRecognized(DragGestureEvent e) {
String sel = source1.getText();
e.startDrag(DragSource.DefaultCopyDrop, 
new StringSelection(sel), this);
}

public void dragEnter(DropTargetDragEvent e) {
System.out.println("dragEnter");
e.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
}
public void drop(DropTargetDropEvent e) {
System.out.println("drop");
try {
if (e.isDataFlavorSupported(DataFlavor.stringFlavor)) {
Transferable tr = e.getTransferable();
e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
String s = (String)tr.getTransferData(DataFlavor.stringFlavor);
lmod.addElement(s);
e.dropComplete(true);
}
else {
e.rejectDrop();
}
}
catch (Exception ex) {
System.out.println("Data transfer exception: " + ex);
}
}
public void dragExit(DropTargetEvent e) { 
System.out.println("dragExit");
}
public void dragOver(DropTargetDragEvent e) { 
System.out.println("dragOver (drop)");
}
public void dropActionChanged(DropTargetDragEvent e) {
System.out.println("dropActionChanged");
}

public void dragDropEnd(DragSourceDropEvent e) {
System.out.println("dragDropEnd");
}
public void dragEnter(DragSourceDragEvent e) {
System.out.println("dragEnter");
}
public void dragExit(DragSourceEvent e) {
System.out.println("dragExit");
}
public void dragOver(DragSourceDragEvent e) {
System.out.println("dragOver (drag)");
}
public void dropActionChanged(DragSourceDragEvent e) {
System.out.println("dragActionChanged (drag)");
}


public static void main(String [] args) {
Drag1 d1;
d1 = new Drag1();
d1.addWindowListener(new WindowAdapter() { 
public void windowClosing(WindowEvent we) {
System.exit(0);
} } );
}
}


you using a lot of old ways of doing things, also add(String, Component) is even obsolete as of 1.1. In what version are you working in?

can I just cook something up in 1.5?

Im using the 1.4 and newer I would guess since its the lastest version of eclipse. Its really hard to find examples of DnD and working ones for Labels at that.

Here is what I currently have.

Equipable

/*
 * Created on Dec 14, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.inventory;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.border.*;


import com.util.DragMouseAdapter;

/**
 * @author zalexander
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class InvEquipPane extends JPanel{
	
	private JLabel invHelmet = new JLabel();
	private JLabel invArmor = new JLabel();
	private JLabel invMainHand = new JLabel();
	private JLabel invOffHand = new JLabel();
	private JLabel invAcc1 = new JLabel();
	private JLabel invAcc2 = new JLabel();
	
	
	public InvEquipPane() {
			//Set pane equipable slots
			super(new GridLayout(6, 1));
			
			//Define Equipable slots - Helmet, Armor, Main Hand, Off-Hand, Accessory 1, Accessory 2

			invHelmet = new JLabel( "test", SwingConstants.LEADING );
	        invHelmet.setTransferHandler(new TransferHandler("text"));
	        	        
	        invArmor = new JLabel( "", SwingConstants.LEADING );
	        invArmor.setTransferHandler(new TransferHandler("text"));
	        
	        
	        invMainHand = new JLabel( "", SwingConstants.LEADING );
	        invMainHand.setTransferHandler(new TransferHandler("text"));
	        
	        invOffHand = new JLabel( "", SwingConstants.LEADING );
	        invOffHand.setTransferHandler(new TransferHandler("text"));
	        
	        invAcc1 = new JLabel( "", SwingConstants.LEADING );
	        invAcc1.setTransferHandler(new TransferHandler("text"));
	        
	        invAcc2 = new JLabel( "", SwingConstants.LEADING );
	        invAcc2.setTransferHandler(new TransferHandler("text"));

	        //Add Mouse Listeners to InvEquip Items
	        MouseListener listener = new DragMouseAdapter();
	        
	        invHelmet.addMouseListener(listener);
	        invArmor.addMouseListener(listener);
	        invMainHand.addMouseListener(listener);
	        invOffHand.addMouseListener(listener);
	        invAcc1.addMouseListener(listener);
	        invAcc2.addMouseListener(listener);
	        
	        //Create and Add the individual Equipable Item Drop and Drag boxes
	        JPanel invHelmetPanel = new JPanel(new GridLayout(1,1));
	        TitledBorder invHelmetPanelBorder = BorderFactory.createTitledBorder("Helmet");
	        invHelmetPanel.add(invHelmet);
	        invHelmetPanel.setBorder(invHelmetPanelBorder);
	        
	        JPanel invArmorPanel = new JPanel(new GridLayout(1,1));
	        TitledBorder invArmorPanelBorder = BorderFactory.createTitledBorder("Armor");
	        invArmorPanel.add(invArmor);
	        invArmorPanel.setBorder(invArmorPanelBorder);
	        
	        JPanel invMainHandPanel = new JPanel(new GridLayout(1,1));
	        TitledBorder invMainHandPanelBorder = BorderFactory.createTitledBorder("Main-Hand");
	        invMainHandPanel.add(invMainHand);
	        invMainHandPanel.setBorder(invMainHandPanelBorder);
	        
	        JPanel invOffHandPanel = new JPanel(new GridLayout(1,1));
	        TitledBorder invOffHandPanelBorder = BorderFactory.createTitledBorder("Off-Hand");
	        invOffHandPanel.add(invOffHand);
	        invOffHandPanel.setBorder(invOffHandPanelBorder);
	        
	        JPanel invAcc1Panel = new JPanel(new GridLayout(1,1));
	        TitledBorder invAcc1PanelBorder = BorderFactory.createTitledBorder("Accessory-1");
	        invAcc1Panel.add(invAcc1);
	        invAcc1Panel.setBorder(invAcc1PanelBorder);
	        
	        JPanel invAcc2Panel = new JPanel(new GridLayout(1,1));
	        TitledBorder invAcc2PanelBorder = BorderFactory.createTitledBorder("Accessory-2");
	        invAcc2Panel.add(invAcc2);
	        invAcc2Panel.setBorder(invAcc2PanelBorder);
	        
	        //Create the equipable plane to show in applet
	        JPanel invEquipPanel = new JPanel();
	        invEquipPanel.setLayout(new GridLayout(6,1));
	        TitledBorder invEquipPanelTitle = BorderFactory.createTitledBorder("Equipped");
	        //Add items to the plane
	        invEquipPanel.add(invHelmetPanel);
	        invEquipPanel.add(invArmorPanel);
	        invEquipPanel.add(invMainHandPanel);
	        invEquipPanel.add(invOffHandPanel);
	        invEquipPanel.add(invAcc1Panel);
	        invEquipPanel.add(invAcc2Panel);
	        invEquipPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
	        invEquipPanel.setPreferredSize(new Dimension(300, 480));
	        invEquipPanel.setBorder(invEquipPanelTitle);
	        
	        setLayout(new BorderLayout());
	        add(invEquipPanel, BorderLayout.CENTER);
	        setBorder(BorderFactory.createEmptyBorder(10,10,10,10));

	     
	        

	        
	        
	}


}

Items


/*
 * Created on Dec 14, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.inventory;


import java.awt.*;

import javax.swing.*;
import javax.swing.border.TitledBorder;


import com.util.ArrayListTransferHandler;

/**
 * @author zalexander
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class InvItemPane extends JPanel{
	
	public ArrayListTransferHandler arrayListHandler;
	
	public InvItemPane(){
		arrayListHandler = new ArrayListTransferHandler();
		JList invList;
		
		DefaultListModel invListModel = new DefaultListModel();
		//Call and add list items from DB
		invListModel.addElement("0 (invList)");
		invListModel.addElement("1 (invList)");
		invListModel.addElement("2 (invList)");
		invListModel.addElement("3 (invList)");
		invListModel.addElement("4 (invList)");
		invListModel.addElement("5 (invList)");
		invListModel.addElement("6 (invList)");
		//End add of items from DB
		
		//Set some status stuff
		invList = new JList(invListModel);
		invList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		invList.setTransferHandler(arrayListHandler);
		invList.setDragEnabled(true);
		
		//Setup the list
		JScrollPane invListView = new JScrollPane(invList);
        invListView.setPreferredSize(new Dimension(200, 100));
        
        JPanel invListPanel = new JPanel();
        invListPanel.setLayout(new BorderLayout());
        TitledBorder invListPanelTitle = BorderFactory.createTitledBorder("Items");
        
        invListPanel.add(invListView, BorderLayout.CENTER);
        invListPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
        invListPanel.setPreferredSize(new Dimension(200, 480));
        invListPanel.setBorder(invListPanelTitle);
        
        setLayout(new BorderLayout());
        add(invListPanel, BorderLayout.CENTER);
        setBorder(BorderFactory.createEmptyBorder(10,10,10,10));

		
	}


}


And i need to make these two react together in DnD.

Individually they work fine. But I can’t drag from the list to the labels and vice versa.

how does your TransverHandler look?

I have a working clamp of code here.

here is Array Transfer Handler

/*
 * Created on Dec 16, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.util;

import java.util.*;
import java.io.*;
//import java.awt.*;
//import java.awt.event.*;
import java.awt.datatransfer.*;
//import java.awt.dnd.*;
import javax.swing.*;

/**
 * @author zalexander
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */


public class ArrayListTransferHandler extends TransferHandler {
	
    public DataFlavor localArrayListFlavor, serialArrayListFlavor;
    
    public String localArrayListType = DataFlavor.javaJVMLocalObjectMimeType + ";class=java.util.ArrayList";
    
    public JList source = null;
    public int[] indices = null;
    public int addIndex = -1; //Location where items were added
    public int addCount = 0;  //Number of items added

    public ArrayListTransferHandler() {
        try {
            localArrayListFlavor = new DataFlavor(localArrayListType);
        } catch (ClassNotFoundException e) {
            System.out.println(
             "ArrayListTransferHandler: unable to create data flavor");
        }
        serialArrayListFlavor = new DataFlavor(ArrayList.class,
                                              "ArrayList");
    }

    public boolean importData(JComponent c, Transferable t) {
        JList target = null;
        ArrayList alist = null;
        if (!canImport(c, t.getTransferDataFlavors())) {
            return false;
        }
        try {
            target = (JList)c;
            if (hasLocalArrayListFlavor(t.getTransferDataFlavors())) {
                alist = (ArrayList)t.getTransferData(localArrayListFlavor);
            } else if (hasSerialArrayListFlavor(t.getTransferDataFlavors())) {
                alist = (ArrayList)t.getTransferData(serialArrayListFlavor);
            } else {
                return false;
            }
        } catch (UnsupportedFlavorException ufe) {
            System.out.println("importData: unsupported data flavor");
            return false;
        } catch (IOException ioe) {
            System.out.println("importData: I/O exception");
            return false;
        }

        //At this point we use the same code to retrieve the data
        //locally or serially.

        //We'll drop at the current selected index.
        int index = target.getSelectedIndex();

        //Prevent the user from dropping data back on itself.
        //For example, if the user is moving items #4,#5,#6 and #7 and
        //attempts to insert the items after item #5, this would
        //be problematic when removing the original items.
        //This is interpreted as dropping the same data on itself
        //and has no effect.
        if (source.equals(target)) {
            if (indices != null && index >= indices[0] - 1 &&
                  index <= indices[indices.length - 1]) {
                indices = null;
                return true;
            }
        }

        DefaultListModel listModel = (DefaultListModel)target.getModel();
        int max = listModel.getSize();
        if (index < 0) {
            index = max; 
        } else {
            index++;
            if (index > max) {
                index = max;
            }
        }
        addIndex = index;
        addCount = alist.size();
        for (int i=0; i < alist.size(); i++) {
            listModel.add(index++, alist.get(i));
        }
        return true;
    }

    protected void exportDone(JComponent c, Transferable data, int action) {
        if ((action == MOVE) && (indices != null)) {
            DefaultListModel model = (DefaultListModel)source.getModel();

            //If we are moving items around in the same list, we
            //need to adjust the indices accordingly since those
            //after the insertion point have moved.
            if (addCount > 0) {
                for (int i = 0; i < indices.length; i++) {
                    if (indices[i] > addIndex) {
                        indices[i] += addCount;
                    }
                }
            }
            for (int i = indices.length -1; i >= 0; i--)
                model.remove(indices[i]);
        }
        indices = null;
        addIndex = -1;
        addCount = 0;
    }

    private boolean hasLocalArrayListFlavor(DataFlavor[] flavors) {
        if (localArrayListFlavor == null) {
            return false;
        }

        for (int i = 0; i < flavors.length; i++) {
            if (flavors[i].equals(localArrayListFlavor)) {
                return true;
            }
        }
        return false;
    }

    private boolean hasSerialArrayListFlavor(DataFlavor[] flavors) {
        if (serialArrayListFlavor == null) {
            return false;
        }

        for (int i = 0; i < flavors.length; i++) {
            if (flavors[i].equals(serialArrayListFlavor)) {
                return true;
            }
        }
        return false;
    }

    public boolean canImport(JComponent c, DataFlavor[] flavors) {
        if (hasLocalArrayListFlavor(flavors))  { return true; }
        if (hasSerialArrayListFlavor(flavors)) { return true; }
        return false;
    }

    protected Transferable createTransferable(JComponent c) {
        if (c instanceof JList) {
            source = (JList)c;
            indices = source.getSelectedIndices();
            Object[] values = source.getSelectedValues();
            if (values == null || values.length == 0) {
                return null;
            }
            ArrayList alist = new ArrayList(values.length);
            for (int i = 0; i < values.length; i++) {
                Object o = values[i];
                String str = o.toString();
                if (str == null) str = "";
                alist.add(str);
            }
            return new ArrayListTransferable(alist);
        }
        return null;
    }

    public int getSourceActions(JComponent c) {
        return COPY_OR_MOVE;
    }

    public class ArrayListTransferable implements Transferable {
        ArrayList data;

        public ArrayListTransferable(ArrayList alist) {
            data = alist;
        }

        public Object getTransferData(DataFlavor flavor)
                                 throws UnsupportedFlavorException {
            if (!isDataFlavorSupported(flavor)) {
                throw new UnsupportedFlavorException(flavor);
            }
            return data;
        }

        public DataFlavor[] getTransferDataFlavors() {
            return new DataFlavor[] { localArrayListFlavor,
                                      serialArrayListFlavor };
        }

        public boolean isDataFlavorSupported(DataFlavor flavor) {
            if (localArrayListFlavor.equals(flavor)) {
                return true;
            }
            if (serialArrayListFlavor.equals(flavor)) {
                return true;
            }
            return false;
        }
    }
}

and the Drag Mouse Adapter

/*
 * Created on Dec 15, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.util;


import java.awt.event.*;
import javax.swing.*;



/**
 * @author zalexander
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

public class DragMouseAdapter extends MouseAdapter {
	
    public void mousePressed(MouseEvent e) {
        JComponent c = (JComponent)e.getSource();
        TransferHandler handler = c.getTransferHandler();
        handler.exportAsDrag(c, e, TransferHandler.COPY);
    }
}

http://oege.ie.hva.nl/~bischo03/java/charactersheet.jar

design flaws, not production ready etc.

didn’t really have time to clean it up I was away for a long weekend, it should give you an idea of how it could work. I would also note that perhaps its better to avoid serialised variants sine you rather not want ppl dragging items from one app to an other.

Cool deal I will take a looksee. Thanx!!!

also note how you can easly exchange the string representation with an picture representation with this approach. simply add an getImage() or getVisualRepresentation() to the Item Object.

change the ItemView and ItemViewRenderer(the flywaight), (standard swing approch) and presto.

also note how the remove on the inventory isn’t correct (the Item gets lost now, it should return to the Inventory(List)), and how the view and the model are unnessasery tangled up, perhaps there should be an CharacterSheetModel etc etc. oh well thats what revisions are for.

Okay im tearing it apart and reading and learning and such and ran into @Override that my eclipse doesn’t like. I guess im running java 1.4 sdk and such.

whats the 1.4 equivalent to this command.

oh just remove it its an indicator that the methode is overwritten.

/**

  • Indicates that a method declaration is intended to override a
  • method declaration in a superclass. If a method is annotated with
  • this annotation type but does not override a superclass method,
  • compilers are required to generate an error message.
  • @author Joshua Bloch
  • @since 1.5
    */

Rock on. I went ahead and upgraded to 1.5 instead.

Can you help me understand the model(item) stuff that you are doing throughout your classes. I believe it is simply turning it all to text. But I can’t quite figure out where to put that and where to modify a transfer handler to fit my existing classes for equipment and such. Im trying to keep the already made look and feel and implement your drag and drop transfer logic.

Any ideas.

as it is now the Item is simply a wrapper for a String. if you wanted to assosiate an image for it simply added to Item and adapt/change de (cell)renders to use it. the Item is a POJO you can simply subsitute it with your current Item class. all you need to do then is to alter your renders to call the right methodes so they show what you want to show.

Item(model) -> ItemView(view)

if you would create a view(Object) for every item beeing displayed it would cause performance issues. instead we use 1 view and ‘plug’ the model into it. (creating a flywaight pattern) the flywaight class is ItemViewRenderer . also have a look at Custom renderers in the swing tutourial.

but yes its all turning it into text. As the DefaultRenderer does, only that calls toString() or String.valueof() rather. its just easely extended like this, and you save the toString() for displaying something more usefull.

Can I import as a string from a DB and then set as an image for the string object for the transfer?

could you explain that in more detail? are we talking about blob’s here? string with a location of the image? an indentifier? what?

For example I have a constants or DB access class. it has Sword, Armor, Ring.

In the database these are lines like. Sword +1atk +1dmg such and so forth.

If i input the “Sword” as a string value given the Item Model, can I in the Item Model convert that or associate that with an image that holds the same placer and characteristics. So instead of selecting the text “Sword” from the JLabel and dragging back and forth to the list I can click, hold, drag a Sword image.