Click here to Skip to main content
13,804,400 members
Click here to Skip to main content
Add your own
alternative version


25 bookmarked
Posted 6 Oct 2010
Licenced Apache

Draggable Components in Java Swing

, 7 Oct 2010
Rate this:
Please Sign up or sign in to vote.
Create a useful draggable generic component to create custom graphic desktop applications, like visual editors or multimedia management


For an attractive presentation of work, I show you this image:


This is the target. A visual photo manager, with draggable photos. Obviously this is a useless application, but it is been displayed here to demonstrate the power of Swings.


The base element of our treatment is JComponent.

This component is the graphic base element of Swing framework for our purpose. In this graph, we will examine the workflow of development:


Workflow is left to right, but inheritance is right to left. So we first have to develop a Draggable Component from a JComponent with drag&drop features, a simple feature at first glance, but a little bit more complex when viewed deeply. So we can develop a custom Draggable Component like an Image Component for this specific scope.

Draggable Component

We can start with properties and constructor:

public class DraggableComponent extends JComponent {

    /** If sets <b>TRUE</b> this component is draggable */
    private boolean draggable = true;
    /** 2D Point representing the coordinate where mouse is, relative parent container */
    protected Point anchorPoint;
    /** Default mouse cursor for dragging action */
    protected Cursor draggingCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
    /** If sets <b>TRUE</b> when dragging component, 
    it will be painted over each other (z-Buffer change) */
    protected boolean overbearing = false;

    public DraggableComponent() {
        setBackground(new Color(240,240,240));

The properties are self explanatory with comments. Pay attention to anchorPoint that is the point where we pinch object with the mouse. Overbearing is a custom way say to Drag.Comp. to change its z-index to overlap on each other.

The constructor is simple. The only word is for addDragListerner method that we see below:

     * Add Mouse Motion Listener with drag function
    private void addDragListeners() {
        /** This handle is a reference to THIS because in next Mouse Adapter 
	"this" is not allowed */
        final DraggableComponent handle = this;
        addMouseMotionListener(new MouseAdapter() {

            public void mouseMoved(MouseEvent e) {
                anchorPoint = e.getPoint();

            public void mouseDragged(MouseEvent e) {
                int anchorX = anchorPoint.x;
                int anchorY = anchorPoint.y;

                Point parentOnScreen = getParent().getLocationOnScreen();
                Point mouseOnScreen = e.getLocationOnScreen();
                Point position = new Point(mouseOnScreen.x - parentOnScreen.x - 
		anchorX, mouseOnScreen.y - parentOnScreen.y - anchorY);

                //Change Z-Buffer if it is "overbearing"
                if (overbearing) {
                    getParent().setComponentZOrder(handle, 0);

This method adds a listener to MouseMotion on object. He has to override two events. MouseMoved is used for keeping every time the relative coordinates mouse-component. MouseDragged instead is used to drag object (is MouseDown + MouseMove event). It uses a particular vector calculus to retrieve from anchorPoint (see above) the Position (left,top) of that component while dragging. If we use a simple Mouse coordinate to set position of component, there is a bad flicker effect. Below is a representation of calculus if you are interested (trust me otherwise:).


The last two important methods are:

   protected void paintComponent(Graphics g) {
       if (isOpaque()) {
           g.fillRect(0, 0, getWidth(), getHeight());

private void removeDragListeners() {
       for (MouseMotionListener listener : this.getMouseMotionListeners()) {

The first is only for painting a coloured box if isOpaque = true, because this component is a phantom component otherwise. The second one is for removing listeners when we decide that this component has to freeze.

Draggable Image Component

As always, we start from the beginning:

public class DraggableImageComponent 
	extends DraggableComponent implements ImageObserver {

    protected Image image;
    private boolean autoSize = false;
    private Dimension autoSizeDimension = new Dimension(0, 0);

    public DraggableImageComponent() {

We have less properties. Image is the picture to display in component, autoSize is TRUE if component display image with original ratio and autoSizeDimension is used for this purpose. We extend DraggableComponent because we want a draggable image item, but calling setDraggable(false) we have a simple static Image Component. It implements ImageObserver because it has to implement a callback method called when some images have been loaded. The application creates threads to load external data like images, because it can take more time, so we have a callback when the loading is finished.


   protected void paintComponent(Graphics g) {
       Graphics2D g2d = (Graphics2D) g;
       g2d.clearRect(0, 0, getWidth(), getHeight());
       if (image != null) {
           g2d.drawImage(image, 0, 0, getWidth(), getHeight(), this);
       } else {
           g2d.fillRect(0, 0, getWidth(), getHeight());

This is the core for an ImageComponent because here it paints the selected image. It avoids calling father corresponding method because it doesn't matter. However it is very simple to understand.

Methods for image resizing:

 private void setAutoSizeDimension() { //    }  

private Dimension adaptDimension(Dimension source, Dimension dest) { //    }

They are not very important for our discussion, however they are simple ways to resize image preserving w/h ratio. If you want further explanation on that, message me.

Important, how I said above, is create a callback for image loading.

public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) {
       if (infoflags == ALLBITS) {
           return false;
       return true;

This is the overridden method of ImageObserver implementation. InfoFlags can have multiple values, when it is equal to ImageObserver.ALLBITS the image is been loaded. If you don't create a callback image is loaded after first repaint(), so you can't see image, but only a black box or void box.


This is the application of the first screenshot. It is a simple foo application to explain the use of these components. I don't post pieces of code here because it is too dispersive. However you can read it in the source - Main.Java file with comments to understand the workflow. It is very simple: create a container for DraggableImageComponents and dynamically put images on it. You can see that you can do that with really few lines of code.


As always, the two main components are fully reusable. You can use them everywhere, and you can customize them. With few code lines, you can create a draggable component, like a draggable panel for several scopes. For example, if you think of a visual editor, like e.g. OpenOffice Draw, the base is just a set of draggable items. Another feature is RESIZE of a component. We can simply do that by inserting another level of inheritance, before or after DraggableComponent, so we can extend an XXXComponent fully draggable and resizable. If you are interested on this, please vote! So I'll find your need. :)


This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0


About the Author

Engineer n
Italy Italy
No Biography provided

You may also be interested in...

Comments and Discussions

QuestionGood job Pin
jbrodricksmith21-Mar-18 16:36
memberjbrodricksmith21-Mar-18 16:36 
Praise10000 volte grazie!! Pin
mattia pini15-Feb-16 8:54
membermattia pini15-Feb-16 8:54 
QuestionImages not appearing Pin
Stirling Statham1-Dec-14 8:27
memberStirling Statham1-Dec-14 8:27 
AnswerRe: Images not appearing Pin
jbrodricksmith21-Mar-18 16:34
memberjbrodricksmith21-Mar-18 16:34 
QuestionImages not appears Pin
Member 1069599524-Mar-14 11:47
memberMember 1069599524-Mar-14 11:47 
AnswerRe: Images not appears Pin
Member 1090765229-Jun-14 20:12
memberMember 1090765229-Jun-14 20:12 
GeneralRe: Images not appears Pin
Stirling Statham1-Dec-14 8:36
memberStirling Statham1-Dec-14 8:36 
QuestionImage Drag and Drop Pin
pooja vadiraja8-Feb-13 2:46
memberpooja vadiraja8-Feb-13 2:46 
QuestionMore optimal than setLocation? Pin
Member 968200631-Jan-13 6:03
memberMember 968200631-Jan-13 6:03 
GeneralMy vote of 5 Pin
Member 951138416-Oct-12 16:25
memberMember 951138416-Oct-12 16:25 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey18-Mar-12 23:12
professionalManoj Kumar Choubey18-Mar-12 23:12 
GeneralMy vote of 5 Pin
Nagy Vilmos2-Nov-10 2:27
professionalNagy Vilmos2-Nov-10 2:27 
GeneralI guess it was just me... Pin
MattTastic7-Oct-10 1:16
memberMattTastic7-Oct-10 1:16 
GeneralRe: I guess it was just me... Pin
b4rc0ll07-Oct-10 3:41
groupb4rc0ll07-Oct-10 3:41 
GeneralRe: I guess it was just me... Pin
MattTastic7-Oct-10 3:48
memberMattTastic7-Oct-10 3:48 
QuestionCan't download source files!? Pin
MattTastic6-Oct-10 23:51
memberMattTastic6-Oct-10 23:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web06 | 2.8.181218.1 | Last Updated 7 Oct 2010
Article Copyright 2010 by b4rc0ll0
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid