Monday 28 December 2009

Upgrade to GWT 2

To upgrade the Eclipse Plugin to GWT 2, is an easy process. Unfortunately GWT is installed with the default name, GWT, GWT (1), GWT (2) and so on, for any different release. Ideally, the name used is a meaning full one, such as GWT 1.7.1 and GWT 2.0.0.

In this short article we discuss who to rename an existing GWT Eclipse Plugin and install GWT 2

Rename the existing GWT Eclipse Plugin

This step is optional.

By default, the GWT Eclipse plugin is installed with the name GWT as shown in the following figure. This can be misleading especially if you have multiple versions installed. Unfortunately, the name cannot be changed once installed. The only way to rename it is to remove it and then add it again with the proper name.

To rename the GWT Eclipse Plugin, please follow the steps below:

  1. From the menu, open Window > Preferences
  2. Expand the Google node and select the Web Toolkit

    As you can notice, the name set to GWT.
  3. Select it and click the Remove button
  4. Once removed, click the Add button
  5. A dialog will open. Click the Browse button to locate the current GWT Eclipse plugin

  6. Browse to the GWT Eclipse plugin folder. This is usually found at: C:\Program Files\Eclipse\eclipse-jee-galileo-SR1-win32\plugins\com.google.gwt.eclipse.sdkbundle.win32_1.7.1.v200909221731\gwt-windows-1.7.1.

    Note that the version numbers may be different depending on the version you have installed.

  7. Set the display name to correspond to the version, GWT X.X.X, and press OK

  8. Press OK to complete the process

This complete the renaming process.

Install the GWT 2 Eclipse plugin

This is installed as any other new Eclipse plugin.

  1. From the menu, open Help > Install New Software.... Make sure to select the Install New Software... and NOT Check for Updates
  2. Select the Google Eclipse URL: http://dl.google.com/eclipse/plugin/3.5 (for Eclipse 3.5), check both the Plugin and SDK options and press Next as shown in the image below.

  3. Next, Next, ..., Next through the installation. Once ready, restart Eclipse.

The GWT 2 Eclipse plugin is installed, with the name GWT. It is recommended to rename it to GWT 2.0.0 following the steps above discussed.

Draft Compile

One of the new features available in GWT2 is the draft compile, which is ideal for development as it skips the optimisation processes carried out by the compiler reducing the compile time. This is a great feature for development, but the production code SHOULD NOT be compiled in this mode.

To make use of this feature, simple add the -draftCompile to the advance compiler options as illustrated below.

Thursday 17 December 2009

Simple Java WAV Player

In this article we'll discuss a simple way how to play wav files in Java. We'll start with the complete example and explain each bit in the process. This example only involves one class, the one listed below.

package com.albertattard.pmm;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

public class TheMusicPlayer {

  public static void play(final InputStream inputStream) {
    new Thread() {
      @Override
      public void run() {
        AudioInputStream audioInputStream = null;
        try {
          audioInputStream = AudioSystem
              .getAudioInputStream(inputStream);
        } catch (UnsupportedAudioFileException e) {
          e.printStackTrace();
          return;
        } catch (IOException e) {
          e.printStackTrace();
          return;
        }

        SourceDataLine sourceDataLine = null;
        try {
          AudioFormat audioFormat 
              = audioInputStream.getFormat();
          DataLine.Info info = new DataLine.Info(
              SourceDataLine.class, audioFormat);
          sourceDataLine = 
              (SourceDataLine) AudioSystem.getLine(info);
          sourceDataLine.open(audioFormat);
        } catch (LineUnavailableException e) {
          e.printStackTrace();
          return;
        }

        sourceDataLine.start();
        byte[] data = new byte[524288];// 128Kb
        try {
          int bytesRead = 0;
          while (bytesRead != -1) {
            bytesRead = 
                audioInputStream.read(data, 0, data.length);
            if (bytesRead >= 0)
              sourceDataLine.write(data, 0, bytesRead);
          }
        } catch (IOException e) {
          e.printStackTrace();
          return;
        } finally {
          sourceDataLine.drain();
          sourceDataLine.close();
        }
      }
    }.start();
  }

  public static void play(final String wavFile)
      throws FileNotFoundException {
    play(new FileInputStream(wavFile));
  }
}

Those of you who are in a hurry, just copy and paste the above code and get on with your life. The others who can spare sometime, just read the following part.

Explained

The class has two static overloaded methods which play the wav file provides as a parameter. The second method simple invokes the first method passing an instance of input stream (and instance of FileInputStream, which inherits from InputStream)

All the logic is found in the first play() method, and that's what we'll be explaining next.

Let say we have a program and would like to play a sound (saved as a wav file) when an event/scenario occurs. The code to do so is very straight forward as illustrated below (a copy and paste from the example above).

        AudioInputStream audioInputStream = null;
        try {
          audioInputStream = AudioSystem
              .getAudioInputStream(The Input Stream);
        } catch (UnsupportedAudioFileException e) {
          e.printStackTrace();
          return;
        } catch (IOException e) {
          e.printStackTrace();
          return;
        }

        SourceDataLine sourceDataLine = null;
        try {
          AudioFormat audioFormat 
              = audioInputStream.getFormat();
          DataLine.Info info = new DataLine.Info(
              SourceDataLine.class, audioFormat);
          sourceDataLine = 
              (SourceDataLine) AudioSystem.getLine(info);
          sourceDataLine.open(audioFormat);
        } catch (LineUnavailableException e) {
          e.printStackTrace();
          return;
        }

        sourceDataLine.start();
        byte[] data = new byte[524288];// 128Kb
        try {
          int bytesRead = 0;
          while (bytesRead != -1) {
            bytesRead = 
                audioInputStream.read(data, 0, data.length);
            if (bytesRead >= 0)
              sourceDataLine.write(data, 0, bytesRead);
          }
        } catch (IOException e) {
          e.printStackTrace();
          return;
        } finally {
          sourceDataLine.drain();
          sourceDataLine.close();
        }

The above code fragment is made from three parts:

  • Initialisation of the audio input stream
  • Initialisation of the audio output
  • Playing the audio data

We're reading bytes from the input stream (the famous wav) and instead of writing/printing these in the console (as we traditionally do with text files), we're writing to the speaker/sound card of the computer.

We start by initialising the It's good to point out that the AudioInputStream, which inherits from the InputStream. This instance behaves the same like any other stream and can be treated/handled in the same manner as other streams.

AudioInputStream audioInputStream = null;
try {
  audioInputStream = AudioSystem
    .getAudioInputStream(The Input Stream);
} catch (UnsupportedAudioFileException e) {
  e.printStackTrace();
  return;
} catch (IOException e) {
  e.printStackTrace();
  return;
}

Then we initialise the audio output (this is NOT an OutputStream), that is, where the sound will be played. This has to match the audio input initialise in the previous step. Remember that there are many different sound files and not all these can be played with the following code.

SourceDataLine sourceDataLine = null;
try {
  AudioFormat audioFormat 
    = audioInputStream.getFormat();
  DataLine.Info info = new DataLine.Info(
    SourceDataLine.class, audioFormat);
  sourceDataLine = 
    (SourceDataLine) AudioSystem.getLine(info);
  sourceDataLine.open(audioFormat);
} catch (LineUnavailableException e) {
  e.printStackTrace();
  return;
}

The first two were quite straight forward. In the third step we're actually playing the sound by reading the bytes and play them in a similar fashion we do with other streams. We're reading a predefined amount of data (128k) into the array called data and saving the amount of bytes read in the other variable bytesRead.

bytesRead = audioInputStream.read(data, 0, data.length);

When the whole file is played, and there is no more data to be played, the read() method returns -1 (like it does with any other InputStream). This will have the while condition to false ending the playing process.

It is good to note that the third step will consume the focus of program until the wav file is played. That is, if you have a two minute wav file, than the above code will take two minutes to execute. All the other parts of the program (that are executed by this thread) will have to wait for the sound/music to finish. Since this is not what we want, the static method play() wraps this code into a thread which is started at the end of the method.

public static void play(final InputStream inputStream) {
  new Thread() {
    @Override
    public void run() {
      Code removed for brevity
    }
  }.start();
}

Since the code is started within a thread the control is immediately returned to the calling method which can proceed without having to wait for the file to play.

To play a wav file, all we need to do is invoke the pay method with the wav file as a parameter as illustrated below.

package com.albertattard.pmm;

public class TheMain {

  public static void main(String[] args) {
    // File downloaded from: 
    //   http://freewavesamples.com/bowed-bass-c2
    TheMusicPlayer.play(TheMain.class
        .getResourceAsStream("Bowed-Bass-C2.wav"));
  }
}

It's good to point out that the wav file Bowed-Bass-C2.wav (available at: http://freewavesamples.com/bowed-bass-c2) is in the same directory/package as the above class.

Wednesday 16 December 2009

Playing with the Mouse

In this article I'll be discussing how we can you can enhance an graphical component by handling mouse events such as mouse clicks and movements.

This article will not discuss the graphical aspect and assumes that you know how to create a simple UI component extending the JComponent and adding this component into a JFrame. For more information about how to do this, please read the article: Practical Example of Simple Java UI Component.

A note of caution to the reader: This is not an exhaustive article about events and some topics are simple mentioned while others not discussed at all. While you're encouraged to learn as much as you can, it's best to first read this topic as provided here in the order provided and then expand your knowledge once you have read it.

Create an Environment

Let's start by create a simple components (that does nothing) which will add into a frame.

package com.albertattard.pwtm;

import java.awt.Graphics;
import javax.swing.JComponent;

@SuppressWarnings("serial")
public class MyComponent extends JComponent {
  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
  }
}

Always start with a super simple class and then slowly evolve it testing each change on the way. Don't wait for bulk changes to test as then it may be too late to understand what's wrong.

Now it's time to create the frame and add the above component to it.

package com.albertattard.pwtm;

import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.JFrame;

@SuppressWarnings("serial")
public class MyFrame extends JFrame {

  private MyComponent myComp;

  public MyFrame() {
    initComponents();
  }

  private void initComponents() {
    setLayout(null);

    myComp = new MyComponent();
    myComp.setBorder(
      BorderFactory.createLineBorder(Color.RED));
    myComp.setBounds(10, 10, 400, 200);
    add(myComp);
  }
}

Now let's kick off this example by creating another with the main method and have this show rolling

package com.albertattard.pwtm;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class MyMain {
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createShowFrame();
      }
    });
  }

  private static void createShowFrame() {
    JFrame frame = new MyFrame();
    frame.setTitle("Playing with the Mouse");
    frame.setSize(600, 400);
    frame.setDefaultCloseOperation(
      JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}

Now that we have all the require components in place let's run. The above three classes should produce the following (or something very similar).


Let's start playing

Java provides three methods/mechanisms that allow us, the developers, to use to handle mouse events. Let say that we want to change the background colour of my component whenever the mouse hovers over it and rest the colour when the mouse moves away from the component.

We want that our component (the class called MyComponent defined above) to do something when the mouse is moved over it. Then, we have to register a mouse listener within this component and act accordingly. The JComponent class (which MyComponent inherits from) has all the logic we need, that is, methods that allow us to register mouse listeners. Whenever mouse events are occur, these methods will advise/notify our listeners with the changes and we can act accordingly. We first start by registering a mouse listener and then implement the methods we're interested in as illustrated below.

package com.albertattard.pwtm;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JComponent;

@SuppressWarnings("serial")
public class MyComponent extends JComponent {

  public MyComponent() {
    initListeners();
  }

  private void initListeners() {
    addMouseListener(new MouseAdapter() {
      public void mouseExited(MouseEvent e) {
        setBackground(Color.WHITE);
        repaint();
      }

      public void mouseEntered(MouseEvent e) {
        setBackground(Color.RED);
        repaint();
      }
    });
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    g.setColor(getBackground());
    g.fillRect(0, 0, getWidth(), getHeight());
  }
}

Hold your horses, I'm lost.

There's lot of new code in this class, so let's start understanding this bit by bit. Let's start with the initListeners() method. This method is registering a mouse listener by calling the addMouseListener () method inherited from the JComponent class and pass our listener. For simplicity, some code was removed.

  private void initListeners() {
    addMouseListener(/* The Mouse Listener*/);
  }

After removing all the other code, this method becomes very simple and understandable. If you refer to the previous example, we also included a constructor which is calling this method, which I don't believe it requires explanation. The paintComponent () method was also enhanced which now fills a rectangle with the set colour. This rectangle has the same size of our component which makes it appear as the background colour.

Let's now turn our attention to the MouseListener. What is it? Whenever a mouse event is fired, (in laymen terms) the JVM advise our listener about the change. It does so by execute one of the five methods defined by the MouseListener listed below:

  • mouseClicked()
  • mouseEntered()
  • mouseExited()
  • mousePressed()
  • mouseReleased()

The method names are self explanatory but the process may not be. We first create an instance of the MouseListener, which is an interface, and override these methods. Then we register our listener with the component. When the mouse is clicked on our component, the method mouseClicked() will be executed. When the mouse hovers on our component, the method mouseEntered() is executed and when the mouse moves away from our component, the mouseExited().

One last thing before we return to our example. How many from the mouse listener's methods do we need to use to fulfil our requirement? Only two, as the requirement is to change the background when the mouse hovers in and out of our component. Java provides what are referred to adaptors. WTF? Java provides a skeleton class that implement this interfaces and provide default methods (methods that do nothing) for all the interface methods. We can then extend this class and override the method we want. Since the adaptor overrides all the interface methods, we only have to override those we're interested in, which simplifies our work.

Back to our initListeners() method. We're creating an instance of MouseAdapter, and registering it with our component.

  private void initListeners() {
    addMouseListener(new MouseAdapter() {
      public void mouseExited(MouseEvent e) {
        setBackground(Color.WHITE);
        repaint();
      }

      public void mouseEntered(MouseEvent e) {
        setBackground(Color.RED);
        repaint();
      }
    });
  }

As you can see from the above code fragment, we're only overriding two methods, the mouseEntered() and mouseExited() methods. In these methods we're changing the background colour and calling the repaint method.

Straight forward he

Getting it to the next level

That was fun, but let's improve it. Let's draw (fill) a circle following the mouse motion.

Before we can do so, we have to discuss another thing, the MouseEvent.

Before the event is fired and our listeners' methods invoked, information about the event is gathered (by something else which you don't need to care about, at least for now) and forwarded to you (the developer) as an event object, the MouseEvent in this case. This object contains information pertaining to our event, such as the mouse position, the time of the event and other things which may be useful when processing such event. We can (need to) use such information to achieve our goal as shown below.

package com.albertattard.pwtm;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JComponent;

@SuppressWarnings("serial")
public class MyComponent extends JComponent {

  private Point mousePoint; 

  public MyComponent() {
    setForeground(Color.BLUE); 
    initListeners();
  }

  private void initListeners() {
    addMouseListener(new MouseAdapter() {
      public void mouseExited(MouseEvent e) {
        setBackground(Color.WHITE);
        repaint();
      }

      public void mouseEntered(MouseEvent e) {
        setBackground(Color.RED);
        repaint();
      }
    });

    addMouseMotionListener(new MouseMotionAdapter() {
      @Override
      public void mouseMoved(MouseEvent e) {
        mousePoint = e.getPoint();
        repaint();
      }
    });
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    g.setColor(getBackground());
    g.fillRect(0, 0, getWidth(), getHeight());

    if (mousePoint != null) {
      int ballSize = 15;
      g.setColor(getForeground());
      g.fillOval(mousePoint.x - ballSize / 2, 
                 mousePoint.y - ballSize / 2,
                 ballSize, ballSize);
    }
  }
}

The changes from the previous class are highlighted and discussed below.

An instance field was added to our component. Why? We need to transfer the mouse position, magically provided to us by the mouse events (discussed later on), to the paint method. Since we cannot call the paint method directly from the event (the reapint() call is something else), we need to save this information in the instance field, mousePoint, and the use it from the paint method. This instance field is accessible by both methods. First this field is updated by the method

      public void mouseMoved(MouseEvent e) {
        mousePoint = e.getPoint();
        repaint();
      }

within our new adaptor, . The method mouseMoved() is invoked every time the mouse is moved within our component. This is important to understand. Only the mouse events that are related with our component are captured by our listeners. So when the mouse moves out of our component, this method will stop being invoked.

Next we'll discuss the mouse clicks

Handling the clicks

Let say that we also want to handle the mouse click that happen on our component. For simplicity we'll display a simple text in the top left corner listing the number of click that occure as shown below.

A long story short, add a new instance field (called clickCount) of type int and paint its value in the paint method as highlighted below. Also, override the appropriate method in the mouse adaptor.

package com.albertattard.pwtm;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JComponent;

@SuppressWarnings("serial")
public class MyComponent extends JComponent {

  private Point mousePoint;
  private int clickCount; 

  public MyComponent() {
    setForeground(Color.BLUE);
    initListeners();
  }

  private void initListeners() {
    addMouseListener(new MouseAdapter() {
      public void mouseExited(MouseEvent e) {
        setBackground(Color.WHITE);
        repaint();
      }

      public void mouseEntered(MouseEvent e) {
        setBackground(Color.RED);
        repaint();
      }

      @Override
      public void mouseClicked(MouseEvent e) {
        clickCount++;
        repaint();
      }
    });

    addMouseMotionListener(new MouseMotionAdapter() {
      @Override
      public void mouseMoved(MouseEvent e) {
        mousePoint = e.getPoint();
        repaint();
      }
    });
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    g.setColor(getBackground());
    g.fillRect(0, 0, getWidth(), getHeight());

    if (mousePoint != null) {
      int ballSize = 15;
      g.setColor(getForeground());
      g.fillOval(mousePoint.x - ballSize / 2,
          mousePoint.y - ballSize / 2, ballSize, ballSize);
    }

    if (clickCount > 0) {
      g.setColor(getForeground());
      g.drawString("Click Count: " + clickCount, 10, 20);
    } else {
      g.setColor(getForeground());
      g.drawString("No Clicks!!!", 10, 20);
    }
  }
}

The above code is not rocket science but it has a little flaw. If you drag the mouse inside the component, the blue circle will not follow the mouse pointer as illustrated below.

Why not? The MouseMotionListener, which the MouseMotionAdapter implements has two methods but we're only overriding one as illustrated below.

    addMouseMotionListener(new MouseMotionAdapter() {
      @Override
      public void mouseMoved(MouseEvent e) {
        mousePoint = e.getPoint();
        repaint();
      }
    });

The other method, mouseDragged(), is used to handle mouse dragging events as illustrated code fragment below.

     addMouseMotionListener(new MouseMotionAdapter() {
      @Override
      public void mouseDragged(MouseEvent e) {
        mousePoint = e.getPoint();
        repaint();
      }
      
      @Override
      public void mouseMoved(MouseEvent e) {
        mousePoint = e.getPoint();
        repaint();
      }
    }); 

Dragging is more complex than one may think and is discussed further in the following section

Dragging the mouse

For this example, we'll create a new component and will make use of it rather than keep changing the other one. Like before, we'll start with a simple example and keep building on it. We'll start with the following simple component.

package com.albertattard.pwtm;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JComponent;

@SuppressWarnings("serial")
public class MyDragComponent extends JComponent {

  private Rectangle draggableShape;

  public MyDragComponent() {
    draggableShape = new Rectangle(20, 20, 50, 50);
    setForeground(Color.BLUE);
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    Graphics2D g2d = (Graphics2D) g;

    g2d.setColor(getBackground());
    g2d.fillRect(0, 0, getWidth(), getHeight());

    g2d.setColor(getForeground());
    g2d.fill(draggableShape);
  }
}

This component simply draws a solid blue 50 by 50 rectangle at the x and y coordinates 20 as illustrated below

Remember to add this component to the frame before you test it out

Let's start be arm our rectangle with a red border when the mouse enters the box as shown below. Note that the component has a red border and the mouse events are triggered for any mouse activity within the component. We need to filter out movements outside the rectangle and only arm the rectangle when the mouse is on it.

How can we do that? Quiet simple. Like before, we create a field (called mouseInside) and will set it to true when the mouse is within the rectangle and false otherwise. The updates are highlighted below.

package com.albertattard.pwtm;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JComponent;

@SuppressWarnings("serial")
public class MyDragComponent extends JComponent {

  private Rectangle draggableShape;
  private boolean mouseInside; 

  public MyDragComponent() {
    draggableShape = new Rectangle(20, 20, 50, 50);
    setForeground(Color.BLUE);
    initListeners();
  }

  private void initListeners() {
    addMouseMotionListener(new MouseMotionAdapter() {
      @Override
      public void mouseMoved(MouseEvent e) {
        mouseInside = draggableShape.contains(e.getPoint());
        repaint();
      }
    });
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    Graphics2D g2d = (Graphics2D) g;

    g2d.setColor(getBackground());
    g2d.fillRect(0, 0, getWidth(), getHeight());

    g2d.setColor(getForeground());
    g2d.fill(draggableShape);

    if (mouseInside) {
      g2d.setColor(Color.RED);
      g2d.setStroke(new BasicStroke(3));
      g2d.draw(draggableShape);
      g2d.setStroke(new BasicStroke(1));
    }
  }
}
Why are we resetting the stroke at the end of the paint component method? Ideally you rest all changes made to the graphics component once done as other paint methods for this object such paint border method will inherit your changes. In this case, if you do not reset the stroke the border will be painted with this stroke.

The following code fragment does the trick. The method mouseMoved () is continually called by the underlying system (so to say) every time the mouse is moved over our component. When the mouse point (retrieved from the mouse event provided as the method parameter) is within the rectangle area, the mouseInside field is set to true.

      public void mouseMoved(MouseEvent e) {
        mouseInside = draggableShape.contains(e.getPoint());
        repaint();
      }

Let's not stop here. Let's make the rectangle draggable. By draggable I mean that the user can drag the rectangle around our component as shown below.

This is not an easy task and some may find it hard to understand but let's not panic. The following code does the job.

package com.albertattard.pwtm;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JComponent;

@SuppressWarnings("serial")
public class MyDragComponent extends JComponent {

  private Rectangle draggableShape;
  private boolean mouseInside;
  private Point lastMousePoint; 

  public MyDragComponent() {
    draggableShape = new Rectangle(20, 20, 50, 50);
    setForeground(Color.BLUE);
    initListeners();
  }

  private void initListeners() {
    addMouseMotionListener(new MouseMotionAdapter() {
      @Override
      public void mouseMoved(MouseEvent e) {
        mouseInside = draggableShape.contains(e.getPoint());
        lastMousePoint = e.getPoint();
        repaint();
      }

      @Override
      public void mouseDragged(MouseEvent e) {
        mouseInside = draggableShape.contains(e.getPoint());
        if (mouseInside) {
          if (lastMousePoint != null) {
            draggableShape.x += 
                e.getPoint().x - lastMousePoint.x;
            draggableShape.y += 
                e.getPoint().y - lastMousePoint.y;
          }
        }
        lastMousePoint = e.getPoint();
        repaint();
      }
    });
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    Graphics2D g2d = (Graphics2D) g;

    g2d.setColor(getBackground());
    g2d.fillRect(0, 0, getWidth(), getHeight());

    g2d.setColor(getForeground());
    g2d.fill(draggableShape);

    if (mouseInside) {
      g2d.setColor(Color.RED);
      g2d.setStroke(new BasicStroke(3));
      g2d.draw(draggableShape);
      g2d.setStroke(new BasicStroke(1));
    }
  }
}

Let's starts discussing the code.

When the mouse is dragged within the rectangle, we're also moving it. The rectangle can be dragged from anywhere within. So we have to take under consideration where the mouse was clicked within the rectangle and shift the rectangle by the offset, that is, by the amount the mouse was moved. We cannot simply set the rectangle's x and y coordinates to match those of the event. The following sketch highlights this (hopefully).

To do this we added a new field called lastMousePoint, which is used to save the last mouse position (as the name infers). Instead of setting the rectangle coordinates equal to the mouse coordinates we adjust them by how much the mouse was moved using the following (copy and paste from above) logic.

      @Override
      public void mouseDragged(MouseEvent e) {
        mouseInside = draggableShape.contains(e.getPoint());
        if (mouseInside) {
          if (lastMousePoint != null) {
            draggableShape.x += 
                e.getPoint().x - lastMousePoint.x;
            draggableShape.y += 
                e.getPoint().y - lastMousePoint.y; 
          }
        }
        lastMousePoint = e.getPoint();
        repaint();
      }

It is important to also update the lastMousePoint field before we exit the above method.

A tip for the champions. If you observe the previous class, you notice that the field lastMousePoint is only used within the adaptor. Ideally we move this field within the adaptor as highlighted below.

 addMouseMotionListener(new MouseMotionAdapter() {
      
      private Point lastMousePoint; 
      
      @Override
      public void mouseMoved(MouseEvent e) {
        mouseInside = draggableShape.contains(e.getPoint());
        lastMousePoint = e.getPoint();
        repaint();
      }

      @Override
      public void mouseDragged(MouseEvent e) {
        mouseInside = draggableShape.contains(e.getPoint());
        if (mouseInside) {
          if (lastMousePoint != null) {
            draggableShape.x += 
                e.getPoint().x - lastMousePoint.x;
            draggableShape.y += 
                e.getPoint().y - lastMousePoint.y;
          }
        }
        lastMousePoint = e.getPoint();
        repaint();
      }
    });

Too keep it simple, the above change will not apply to the rest of the examples

One last thing before we go. Note that we're able to drag the rectangle outside the component printable area. This is not always good and we would like to prevent this as illustrated below.

This is not a difficult change. All we need to do is cap the changes to the rectangle as illustrated in the following code fragment.

      @Override
      public void mouseDragged(MouseEvent e) {
        mouseInside = draggableShape.contains(e.getPoint());
        if (mouseInside) {
          if (lastMousePoint != null) {
            draggableShape.x += 
                e.getPoint().x - lastMousePoint.x;
            draggableShape.y += 
                e.getPoint().y - lastMousePoint.y;

            draggableShape.x = Math.max(draggableShape.x, 0);
            draggableShape.x = Math.min(draggableShape.x,
                getWidth() - draggableShape.width);
            draggableShape.y = Math.max(draggableShape.y, 0);
            draggableShape.y = Math.min(draggableShape.y,
                getHeight() - draggableShape.height);
          }
        }
        lastMousePoint = e.getPoint();
        repaint();
      }

The rest of the class is not listed for brevity.