A Swing drag and drop code example

Drag and Drop is a powerful feature you should consider adding to your Java applications. When you check out the available tutorials on Java dnd, it may look fairly complex to you. Though it’s not all that hard, the hard part is remembering all the steps, objects and listeners involved. Here is a small example that shows you a basic drag and drop application (implemented with Swing).

A custom Drag and Drop (source) JList appears to the right and contains a file list of your root directory. Files with .txt extensions can be dragged upon our Drag and Drop JTextArea (target). The object transferred (Transferable) is a filename. When the drop occurs (you release the mouse button) the public void drop(DropTargetDropEvent event) is called. You can extract the filename from the Transferable object and go from there.

Main.java

import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.io.*;
 
public class Main extends JFrame
{
   private DNDJList list;
   private DNDJTextArea textarea;
 
   public static void main(String []args) {
      Main frame = new Main();
      frame.show();
   }
 
   public Main() {
      getContentPane().setLayout(new BorderLayout());
      list = new DNDJList(new DefaultListModel());
      getContentPane().add(BorderLayout.EAST, new JScrollPane(list));
      textarea = new DNDJTextArea();
      getContentPane().add(BorderLayout.CENTER, new JScrollPane(textarea));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
 
      fillUpList("c:\");
 
      setSize(700, 300);
   }

   /**
    *  Fills up the JList with the entries in the specified directory
    */
   private void fillUpList(String directory) {
      File dir = new File(directory);
      File []files = dir.listFiles();
 
      DefaultListModel dlm = (DefaultListModel) list.getModel();
      for (int i=0; i<files.length; i++) {
         dlm.addElement(directory + files[i].getName());
      }
   }
}

Our drag and drop JTextArea: DNDJTextArea.java

import java.awt.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;

import java.io.*;
import java.io.IOException;
 
import javax.swing.JTextArea;
 
public class DNDJTextArea extends JTextArea implements DropTargetListener
{
   DropTarget dropTarget = null;
  
   public DNDJTextArea() {
      // create a drop target
      dropTarget = new DropTarget(this, this);
   }
 
   public void dragEnter(DropTargetDragEvent event) { 
      event.acceptDrag(DnDConstants.ACTION_MOVE);
   }
 
   public void drop (DropTargetDropEvent event) {
      try {
         // get the object that is being transferred
         Transferable transferable = event.getTransferable();
       
         // DNDJTextArea accepts only Strings
         if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
            event.acceptDrop(DnDConstants.ACTION_MOVE);
 
            String filename = (String) transferable.getTransferData(DataFlavor.stringFlavor);
            setText(readFile(filename));

            event.getDropTargetContext().dropComplete(true);
         } 
         else {
            event.rejectDrop();
         }
      }
      catch (UnsupportedFlavorException e) {
         setText(""+e);
         event.rejectDrop();
      }
      catch (Exception e) {
         setText(""+e);
         event.rejectDrop();
      } 
   }
 
   public void dragExit (DropTargetEvent event) { }
   public void dragOver (DropTargetDragEvent event) { }
   public void dropActionChanged (DropTargetDragEvent event) { }
 
   public String readFile(String filename) throws Exception {
      String LINEEND = System.getProperties().getProperty("line.separator");      
      StringBuffer sb = new StringBuffer();
      BufferedReader br = new BufferedReader(new FileReader(filename));
 
      String line;
      while ((line = br.readLine()) != null) {
         sb.append(line + LINEEND);
      }         
 
      return sb.toString();
   }
}

A drag and drop JList:DNDJList.java

import java.awt.dnd.*;
import java.awt.datatransfer.*;
import java.io.IOException;
import java.io.*;
 
import javax.swing.*;
 
public class DNDJList extends JList implements DragSourceListener, DragGestureListener    
{
   DragSource dragSource = null;
 
   public DNDJList(ListModel lm) {
      super(lm);
 
      // create a dragsource
      dragSource = new DragSource();
 
      // create a drag gesture recognizer
      dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this);
   }    
 
   public void dragGestureRecognized( DragGestureEvent event) {  
      String fileSelected = (String) getSelectedValue();
 
      if (fileSelected != null) {
         if (fileSelected.endsWith(".txt")) {
            // StringSelection implements Transferable, wraps the data into a transferable object
            StringSelection text = new StringSelection(fileSelected.toString()); 
        
            // start the dragging
            dragSource.startDrag(event, DragSource.DefaultMoveDrop, text, this);
         }
         else {
            SwingUtilities.invokeLater(new Runnable() {
               public void run() {
                  JOptionPane.showMessageDialog(SwingUtilities.getRootPane(DNDJList.this), 
                                                "Only .txt files can be dragged!", "Error",
                                                JOptionPane.ERROR_MESSAGE);
               } 
            });
         }
      } else {
         System.out.println( "nothing was selected");   
      }
   }
 
   public void dragDropEnd (DragSourceDropEvent event) { }
   public void dragEnter (DragSourceDragEvent event) { }
   public void dragExit (DragSourceEvent event) { }
   public void dragOver (DragSourceDragEvent event) { }
   public void dropActionChanged ( DragSourceDragEvent event) { }
}

Drawing a polygon in Swing

Create a Polygon object that contains all corners of the polygon and use the method drawPolygon to render it.

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
   }
 
   public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
 
      Polygon p = new Polygon();
      p.addPoint(110, 120);
      p.addPoint(120, 110);
      p.addPoint(130, 110);
      p.addPoint(140, 120);
      p.addPoint(140, 130);
      p.addPoint(130, 140);
      p.addPoint(120, 140);
      p.addPoint(110, 130);
      p.addPoint(110, 120);
 
      g2d.drawPolygon(p);
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(300, 300);
      main.setVisible(true);
   }
}

Getting the dimensions of a text in Swing

This example shows you how to center a text on the JFrame. It will take into account the specifics of the chosen font. Run it from command line like java Main Helvetica.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
 
public class Main extends JFrame {
   private String fontname;
   private String text = "Easter Island";
 
   public Main(String fontname) {
      this.fontname = fontname;
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
   } 

   public void paint(Graphics g) {
      super.paint(g);
 
      Graphics2D g2d = (Graphics2D) g;
      Font f = new Font(fontname, Font.BOLD, 36);
      FontMetrics fm = getFontMetrics(f);
 
      int swidth = fm.stringWidth(text);
      int sheight = fm.getAscent();
 
      int width = getSize().width;
      int height = getSize().height;
 
      g2d.setColor(Color.gray);
      g2d.drawLine(0, height/2, width, height/2);
      g2d.drawLine(width/2, 0, width/2, height);
 
      g2d.setColor(Color.black);
      g2d.setFont(f);
      g2d.drawString(text, width/2 - swidth/2, height/2 + sheight/2);
   }
  
   public static void main(String []args) {
      if (args.length == 0) {
         System.err.println("Usage: java Main <fontname>");
         System.exit(1);
      }
 
      Main main = new Main(args[0]);
      main.setVisible(true);
      main.setSize(300, 300);
   }
}

Drawing a textured rectangle in Swing

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private BufferedImage image; 
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      image = toBufferedImage(new javax.swing.ImageIcon("c:\djkrush.jpg").getImage());
   }
 
   public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
 
      Rectangle2D tr = new Rectangle2D.Double(0, 0, image.getWidth(), image.getHeight());
      TexturePaint tp = new TexturePaint(image, tr);
 
      // draw texture filled ellipse, but with antialiasing
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                           RenderingHints.VALUE_ANTIALIAS_ON);
      BasicStroke bs = new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
                           10, null, 0);
      g2d.setStroke(bs);
      g2d.setPaint(tp);
      g2d.drawRect(10, 40, 150, 150);
   }
 
   public BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(170, 210);
      main.setVisible(true);
   }
}

Image used:

Inverting an image

To invert an image, you can use the class LookupOp. This class works with one or more tables that will be applied to the color values of the pixels. To invert an RGB image, every R, G, and B value are subtracted from 256. The lookup table reflects these changes.

The following example shows the original image and an image that has been inverted.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private boolean firstTime = true;
   private BufferedImage sourceBi;
   private BufferedImage destBi;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
   } 
 
   public void paint(Graphics graphics) {
      Graphics2D g2d = (Graphics2D) graphics;
  
      if (firstTime) {
         Image img = new javax.swing.ImageIcon("meatballs.jpg").getImage(); 
         sourceBi = toBufferedImage(img);
         destBi = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                    BufferedImage.TYPE_INT_RGB);
         setSize(sourceBi.getWidth(), sourceBi.getHeight()*2);
 
         byte[] intensity = new byte[256];
         for(int i=0; i<256; i++) {
            intensity[i] = (byte) (256 - i);
         }
  
         ByteLookupTable blt = new ByteLookupTable(0, intensity);
         LookupOp op = new LookupOp(blt, null);
         destBi = op.filter(sourceBi, null);
 
         firstTime = false;
      }
 
      g2d.drawImage(sourceBi, 0, 0, this);
      g2d.drawImage(destBi, 0, sourceBi.getHeight(), this);
   }
 
   public static BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Image used:

To learn more about image processing,
check out this expensive but excellent book:

Detecting if the right button was clicked in Swing

To determine whether a right mouse click button was clicked or not, write code in the mouseClicked function of the mouseListener Interface.

   class MyMouseListener extends MouseAdapter
   {
      public void mouseClicked(MouseEvent me)
      {
         if ((me.getModifiers() & InputEvent.BUTTON3_MASK) != 0)
            // right mouse clicked......   
         }
      }
   };
 
   /* getModifiers() gives constant modifier for a particular click();
      BUTTON3_MASK is constant modifier for the right moouse click */

Examples of Swing borders

You can combine these borders with CompoundBorder.

Main.java:

import javax.swing.border.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   public Main() {
      getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));
 
      JLabel labels[] = new JLabel[6];
      labels[0] = new JLabel("Label with EmptyBorder, margin 20");
      labels[0].setBorder(new EmptyBorder(20, 20, 20, 20));
      labels[1] = new JLabel("Label with LineBorder, red color, thickness 3");
      labels[1].setBorder(new LineBorder(Color.red, 3));
      labels[2] = new JLabel("Label with LOWERED BevelBorder");
      labels[2].setBorder(new BevelBorder(BevelBorder.LOWERED));
      labels[3] = new JLabel("Label with RAISED EtchedBorder");
      labels[3].setBorder(new EtchedBorder(EtchedBorder.RAISED));
      labels[4] = new JLabel("Label with MatteBorder and Icon");
      labels[4].setBorder(new MatteBorder(new ImageIcon("c:\female.gif")));
      labels[5] = new JLabel("Label with BevelBorder TitledBorder");
      labels[5].setBorder(new TitledBorder(new BevelBorder(BevelBorder.LOWERED), "Title"));
 
      for (int i=0; i<labels.length; i++) {
         labels[i].setOpaque(true);
         getContentPane().add(labels[i]);
      }
      
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static void main(String [] args) {
      Main main = new Main();
      main.setSize(300, 400);
      main.setVisible(true);
   } 
} 

Maximizing a JFrame

This is as close as you can get: just resize the window to the current screensize:

 
import javax.swing.*;
import java.awt.*;
   
public class Maximize extends JFrame {
 
   public Maximize() {
      Toolkit tk = getToolkit();
      
      setSize((int) getToolkit().getScreenSize().getWidth(), 
              (int) getToolkit().getScreenSize().getHeight());
   }
 
   public static void main(String args[]) {
      new Maximize().setVisible(true);     
   }
}

Detecting JScrollPane events

Add a AdjustmentListener to the horizontal or vertical scrollbar of the JScrollPane (you can get its reference with the methods getHorizontalScrollBar and getVerticalScrollBar).

Note that the AdjustmentType will always be AdjustmentEvent.TRACK.
(From the API: “Note that the AdjustmentEvents type property will always have a placeholder value of AdjustmentEvent.TRACK because all changes to a BoundedRangeModels value are considered equivalent. To change the value of a BoundedRangeModel one just sets its value property, i.e. model.setValue(123). No information about the origin of the change, e.g. it’s a block decrement, is provided. We don’t try fabricate the origin of the change here.”)

Main.java:

import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   public Main() throws Exception {
      getContentPane().setLayout(new BorderLayout());
 
      JPanel panel = createPanel();
 
      JScrollPane scrollpane = new JScrollPane(panel);
      JScrollBar scrollbar = scrollpane.getVerticalScrollBar();
      scrollbar.addAdjustmentListener(new AdjustmentListener() {
         public void adjustmentValueChanged(AdjustmentEvent ae) {
            System.out.println(translateAdjustmentEvent(ae));
         }
      });
 
      getContentPane().add(BorderLayout.CENTER, scrollpane);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public String translateAdjustmentEvent(AdjustmentEvent ae) {
      String s = "type = ";
      switch(ae.getAdjustmentType()) {
         case AdjustmentEvent.UNIT_INCREMENT:
            s += "UNIT_INCREMENT"; break;
         case AdjustmentEvent.UNIT_DECREMENT:
            s += "UNIT_DECREMENT"; break;
         case AdjustmentEvent.BLOCK_INCREMENT:
            s += "BLOCK_INCREMENT"; break;
         case AdjustmentEvent.BLOCK_DECREMENT:
            s += "BLOCK_DECREMENT"; break;
         case AdjustmentEvent.TRACK:
            s += "TRACK"; break;
         default: break;
      }
      s += ", current value = " + ae.getValue();
 
      return s;
   }
 
   public static JPanel createPanel() throws Exception {
      JPanel panel = new JPanel();
      panel.setLayout(new GridLayout(50, 20, 10, 10));
 
      for (int i=0; i<50; i++) {
         for (int j=0; j<20; j++) {
            JLabel label = new JLabel("label " + i + ", " + j);
            panel.add(label);    
         }
      }
 
      return panel;
   }
 
   public static void main(String [] args) throws Exception  {
      Main main = new Main();
      main.setSize(600, 600);
      main.setVisible(true);
   } 
} 

Preventing a JTabbedPane tab from being selected

Override the setSelectedIndex in the JTabbedPane object, as this is called before the change takes place. Here’s an example that only allows you to select tabs with even numbers:

import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame implements ActionListener {
   JTabbedPane tabbedPane;
   int ntabs = 0;
 
   public Main() {
      getContentPane().setLayout(new BorderLayout());
      tabbedPane = new JTabbedPane() {
         public void setSelectedIndex(int index) {
            System.out.println("index selected: " + index);
            if (index % 2 == 0) {
               System.out.println("allowed");
               super.setSelectedIndex(index);
            }
            else {
               System.out.println("not allowed");
            }
         }
      };
      createTab();
 
      getContentPane().add(BorderLayout.CENTER, tabbedPane);
      setJMenuBar(createMenuBar());
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      setTitle("JTabbedPane Selection Demonstration");
      setSize(new Dimension(400, 400));
   }
 
   protected JMenuBar createMenuBar() {
      JMenuBar menuBar = new JMenuBar();
 
      JMenu menu = new JMenu("JTabbedPane");
      JMenuItem menuItem1 = new JMenuItem("Create new tab");
      menuItem1.addActionListener(this);
      menu.add(menuItem1);
      menuBar.add(menu);
 
      return menuBar;
   }
  
   public void actionPerformed(ActionEvent e) {
      if (e.getActionCommand().equals("Create new tab")) {
         createTab();
      }
   }
 
   protected void createTab() {
      tabbedPane.addTab("Tab #" + ntabs, new JLabel("Tab #" + ntabs));
      ntabs++;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.show();
   }
}