Java drag and drop graphics

Java Swing Drag and Drop Example

This example will help us to know about how to enable drag feature for different components and how to customize drag and drop feature for custom flavors.

1. Introduction

In case we wish to transfer data from one UI component (Where applicable) to another, one way to carry it out is cut+ paste or copy+ paste. In this case data first gets stored in the clipboard and then from the clipboard it gets transferred over to the other program. Drag and drop facility is the other way to carry out transfer of information between two UI components (Where applicable). In this case clipboard is not used. In java swing based applications we can implement drag and drop feature to be used. Drag and drop can be done within different UI components of the same application as well as it can happen between two different applications.

2. Technologies Used

3. Overview

The default drag and drop feature for different such UI components are described in the below table for more information.

3.1 Default Drag and drop support for different components

Component Drag Support Drop Support
JColorChooser Yes Yes
JEditorPane Yes Yes
JFileChooser Yes No
JFormattedTextField Yes Yes
JLabel Click to see Click to see
JList Yes No
JPasswordField No Yes
JTable Yes No
JTextArea Yes Yes
JTextField Yes Yes
JTextPane Yes Yes
JTree Yes No
Читайте также:  Get last url php

In order to implement Default drag support, the property dragEnabled is required to be set to true for the component wherever applicable. Otherwise default drag behavior won’t become active.

Unlike drag support, Default drop support is by default active and works as mentioned in the table above.

For cursor shapes please click on this link.

Data item Data Transfer Handler is the basic support required to transfer the data in and out of the component. That is how ‘Drag and Drop’ works.

In order to perform custom drag and drop, the derived classes of TransferHandler class and implementation of Transferable is required to be implemented in the code.

The drag and drop feature is described in the block as described below.

4. Description of the drag and drop feature in the example

4.1 Features of the Example

In the example shared below, we have one JTree control. This control is populated with hierarchy of 3 levels. In the outer level, all drives of the system in which program is running will show. In the second level all directories inside the drives will appear. Lastly in the third level, all .txt files will be visible. This JTree component is added as a left component of a split panel.

As a right component of the split panel, one JTextArea component is added in the center location and one JTextField component is added in the top location.

One JList component is added to the right of the JTextArea .

If we choose a text file from JTree and drag that to the JTextArea , the program will try to open the file. The size and other validations will be done and after that the content will appear on the JTextArea portion. For large files it might take a few seconds to generate output. This demonstrates the customized drag and drop feature.

If we choose any item from the JList component and drag that over to the JTextBox , the text will appear on the JTextBox component. This will demonstrate the default drag and drop feature.

4.2 Description of the implementation.

Since default implementation of Transferable interface to transfer file type object doesn’t exist, we need to have customized implementation of Transferable interface. In the example from line# 1 – 49 the class definition is described. This class FileTransferable contains 2 attributes, list of File objects and array of DataFlavor objects. File list is initialized by the File object parameter passed on at the time of object creation and the DataFlavor array is initialized by DataFlavor.javaFileListFlavor value.

package com.javacodegeeks.example.swing.dnd; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; public class FileTransferable implements Transferable < final private List files; final private DataFlavor[] flavors; /** * A drag-and-drop object for transfering a file. * @param file file to transfer -- this file should already exist, * otherwise it may not be accepted by drag targets. */ public FileTransferable(Collection files) < this.files = Collections.unmodifiableList( new ArrayList(files)); this.flavors = new DataFlavor[] < DataFlavor.javaFileListFlavor >; > public DataFlavor[] getTransferDataFlavors() < // TODO Auto-generated method stub return this.flavors; >public boolean isDataFlavorSupported(DataFlavor flavor) < // TODO Auto-generated method stub return DataFlavor.javaFileListFlavor.equals(flavor); >public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException < // TODO Auto-generated method stub if (isDataFlavorSupported(flavor)) return this.files; else return null; >>

In order to support customized FileTransferable implementation, customization of FileTransferHandler class is also required. In the example from line# 1 – 36 the class definition of the class FileTransferHandler which is derived from TransferHandler is described. The class FileTransferHandler overrides methods viz. getSourceAction and createTransferable of the parent class. The method createTransferable creates a file object using the lastSelectedPathComponent attribute of the JTree . This File object is added to a list and a FileTransferable object is returned passing ‘File’ list as argument.

package com.javacodegeeks.example.swing.dnd; import java.awt.datatransfer.Transferable; import java.io.File; import java.util.ArrayList; import javax.swing.JComponent; import javax.swing.JTree; import javax.swing.TransferHandler; import javax.swing.tree.DefaultMutableTreeNode; public class FileTransferHandler extends TransferHandler < /** * */ private static final long serialVersionUID = 4278824893466339483L; public int getSourceActions(JComponent Source)< return COPY_OR_MOVE; >protected Transferable createTransferable(JComponent source) < JTree tree = (JTree)source; DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(); if(node == null) return null; File file = new File(node.getUserObject().toString()); ArrayList fileList = new ArrayList(); fileList.add(file); return new FileTransferable(fileList); >>

In order to customize drop operation, dropTarget attribute of the target component must be populated with a customized DropTarget object. In this case, from line# 60 – 99, for JTextArea component, while setting the dropTarget attribute, the drop method of DropTarget object is overridden. This drop method accepts DropTargetDropEvent type object. First of all, event object, acceptDrop is set as COPY . Then for that event object , getTransferData method of FileTransferable object is invoked with javaFileListFlavor so that transferred File type list is returned. Once the list is received, file is read and content is displayed.

package com.javacodegeeks.example.swing.dnd; import java.awt.BorderLayout; import java.awt.datatransfer.DataFlavor; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDropEvent; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; public class SwingDnDExampleFrame extends JFrame < /** * */ private static final long serialVersionUID = -224525322599947463L; public SwingDnDExampleFrame()< JSplitPane splitPane = new JSplitPane(); splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT); splitPane.setDividerLocation(200); JTree driveTree = new JTree(getTreeStructure()); final JEditorPane content = new JEditorPane(); JScrollPane treeContent = new JScrollPane(driveTree); JScrollPane scrollContent = new JScrollPane(content); driveTree.setDragEnabled(true); driveTree.setTransferHandler(new FileTransferHandler()); JPanel panel = new JPanel(new BorderLayout()); JTextField fileName = new JTextField(); JList list = new JList(new String[]); list.setDragEnabled(true); panel.add(fileName,BorderLayout.NORTH); panel.add(scrollContent, BorderLayout.CENTER); panel.add(list, BorderLayout.EAST); splitPane.setLeftComponent(treeContent); splitPane.setRightComponent(panel); content.setDropTarget(new DropTarget() < /** * */ private static final long serialVersionUID = -6418118605479053389L; @SuppressWarnings("unchecked") public synchronized void drop(DropTargetDropEvent evt) < try < evt.acceptDrop(DnDConstants.ACTION_COPY); List droppedFiles = (List) evt .getTransferable().getTransferData( DataFlavor.javaFileListFlavor); if(droppedFiles.size() >1) < JOptionPane.showMessageDialog(content, "Sorry. can't handle more than one files together."); >else < File droppedFile = droppedFiles.get(0); if(droppedFile.getName().endsWith(".txt"))< char[] contentBytes = readFile(droppedFile); if(contentBytes == null)< JOptionPane.showMessageDialog(content, "Sorry. file size is too long."); >else if(contentBytes.length == 0) < JOptionPane.showMessageDialog(content, "Sorry. file is empty."); >else < content.setText(new String(contentBytes)); >> else < JOptionPane.showMessageDialog(content, "Sorry. not a text file."); >> > catch (Exception ex) < ex.printStackTrace(); >> >); add(splitPane); pack(); > private char[] readFile(File inputFile) < BufferedReader inputReader = null; char[] content = null; long availableHeap = Runtime.getRuntime().freeMemory(); long fileSize = inputFile.length(); try < if(fileSize > catch (FileNotFoundException e) < // TODO Auto-generated catch block e.printStackTrace(); >catch (IOException e) < // TODO Auto-generated catch block e.printStackTrace(); >return content; > private File[] getAllDrives() < return File.listRoots(); >private ArrayList getAllDirectories(File file) < ArrayList directories = new ArrayList(); File[] allSub = file.listFiles(); if(allSub != null)< for(File sub: allSub)< if(sub.isDirectory())< directories.add(sub); >> > return directories; > private ArrayList getAllTXTs(File directory) < ArrayList pdfs = new ArrayList(); File[] allSub = directory.listFiles(); if(allSub != null)< for(File sub: allSub)< if(sub.isFile() && sub.getName().endsWith(".txt"))< pdfs.add(sub); >> > return pdfs; > private DefaultMutableTreeNode getTreeStructure() < File[] roots = getAllDrives(); DefaultMutableTreeNode allDrives = new DefaultMutableTreeNode("All Drives"); for(File root: roots)< DefaultMutableTreeNode drive = new DefaultMutableTreeNode(root); ArrayList folderNodes = getAllDirectories(root); for(File folderNode : folderNodes)< DefaultMutableTreeNode childDrive =new DefaultMutableTreeNode(folderNode.getName()); ArrayList txts = getAllTXTs(folderNode); for(File txt : txts)< childDrive.add(new DefaultMutableTreeNode(txt)); >drive.add(childDrive); > allDrives.add(drive); > return allDrives; > >

In order to enable drag operation, in lines 1 and 6 dragEnabled attribute is set to true for JList and JTree components.

driveTree.setDragEnabled(true); driveTree.setTransferHandler(new FileTransferHandler()); JPanel panel = new JPanel(new BorderLayout()); JTextField fileName = new JTextField(); JList list = new JList(new String[]); list.setDragEnabled(true);

5. Summary

This example is used to describe default as well as customized drag and drop. We have considered 4 different types of components to describe. For rest of the components and further study, supplied links can be referred.

Источник

Introduction to DnD

If you are writing an application you will want to support the ability to transfer information between components in your application. But you will also want your application to play well with others — this includes supporting the ability to transfer information between your application and other Java applications, and between your application and native applications. The ability to transfer data takes two forms:

  • Drag and drop (DnD) support. The following diagram illustrates dragging from a JList and dropping onto a JTextField component (the arrows show the path of the data): Drag and Drop Illustration
  • Clipboard transfer through cut or copy and paste. The following diagrams show cutting (or copying) from a JList and pasting onto a JTextField component: Cut/Copy/Paste Illustration

Drag and Drop — Behind the Scenes

Let us say there is a user named Rollo, who is running a Java application. He wants to drag some text from a list and deposit it into a text field. (Note that the process is the same when dragging from a native application to a Java application.) In a nutshell, the drag and drop process works like this:

  • Rollo has selected a row of text in the source component: the list. While holding the mouse button Rollo begins to drag the text — this initiates the drag gesture.
  • When the drag begins, the list packages up the data for export and declares what source actions it supports, such as COPY , MOVE , or LINK .
  • As Rollo drags the data, Swing continuously calculates the location and handles the rendering.
  • If Rollo simultaneously holds the Shift and/or Control key during the drag, this user action is also part of the drag gesture. Typically, an ordinary drag requests the MOVE action. Holding the Control key while dragging requests the COPY action, and holding both Shift and Control requests the LINK action.
  • Once Rollo drags the text over the bounds of a text field component, the target is continually polled to see if it will accept or reject the potential drop. As he drags, the target provides feedback by showing the drop location, perhaps an insertion cursor or a highlighted selection. In this case, the text field (the current target) allows both replacement of selected text and insertion of new text.
  • When Rollo releases the mouse button, the text component inspects the declared source actions and any user action and then it chooses what it wants out of the available options. In this case, the text field chooses to insert the new text at the point of the drop.
  • Finally, the text field imports the data.

While this might seem like a daunting process, Swing handles most of the work for you. The framework is designed so that you plug in the details specific to your component, and the rest «just works».

More on this in the next section.

We do not recommend that you create your own drag and drop support using the AWT classes. This implementation would require significant complex support internal to each component. Prior to release 1.4 when the dnd system was reworked, developers did occasionally create their own dnd support, but it does not work with sophisticated components, like tree and table, that have subtle selection and drop issues.

Источник

Оцените статью