Tentando pintar stroke de uma Shape após um mouseMoved() sobre ela

Olá pessoal,

Estou a tentar pintar a stroke de uma shape sempre que passo com o rato por cima dela, mas não tou a conseguir.

Segue o código da classe que extende a JFrame:

package dblauncher;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;

@SuppressWarnings("ResultOfObjectAllocationIgnored")
public class DBLauncher extends JFrame 
{
    public static void main(String args[]) throws IOException 
    {
        DBLauncher dbLauncher = new DBLauncher();
        
        dbLauncher.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        dbLauncher.setVisible(true);
    }
   
    //Construtor: serve apenas para inicializar o objeto e não para executar quaisquer ações sobre ele
    public DBLauncher() throws IOException
    {
        super("Database Launcher v1.0");
        
        setSize(500, 500);
        setLocation(430, 150);
        setResizable(false);
        
        DBPanel panel = new DBPanel();
        
        Container container = getContentPane();
        
        container.setLayout(new BorderLayout()); //Usar BorderLayout
        container.add(panel, BorderLayout.CENTER); //Inserir o panel no centro do BorderLayout
    }
}

final class DBPanel extends JPanel implements MouseListener, MouseMotionListener
{   
    private final float musicShapePosX = 85.0f;
    private float musicShapePosY = 100.0f;
    private final float tvShapePosX = 184.0f;
    private final float tvShapePosY = 164.0f;
    private final float gamesShapePosX = 283.0f;
    private final float gamesShapePosY = 100.0f;
    private final float booksShapePosX = 283.0f;
    private final float booksShapePosY = 228.0f;
    private final float techShapePosX = 184.0f;
    private final float techShapePosY = 293.0f;
    private final float SEGMENT_SHAPE_LENGTH = 50.0f;
    private final float SHAPE_HEIGHT = 10.0f;
    private float SHAPE_SPEED = 7.5f; 
    
    private final CustomShapeButton musicShapeButton;
    private final CustomShapeButton tvShapeButton;
    private final CustomShapeButton gamesShapeButton;
    private final CustomShapeButton booksShapeButton;
    private final CustomShapeButton techShapeButton;
    
    private final ArrayList<CustomShapeButton> shapeButtons;
    
    private boolean musicButtonPressed = false;
    private boolean tvButtonPressed = false;
    private boolean gamesButtonPressed = false;
    private boolean booksButtonPressed = false;
    private boolean techButtonPressed = false;
    
    private boolean buttonStop = true;
    
    public DBPanel() throws IOException
    {     
        BufferedImage musicShapeImage = ImageIO.read(getClass().getResource("/images/imageWoodMusic.png"));
        BufferedImage tvShapeImage = ImageIO.read(getClass().getResource("/images/imageWoodTv.png"));
        BufferedImage gamesShapeImage = ImageIO.read(getClass().getResource("/images/imageWoodGames.png"));
        BufferedImage booksShapeImage = ImageIO.read(getClass().getResource("/images/imageWoodBooks.png"));
        BufferedImage techShapeImage = ImageIO.read(getClass().getResource("/images/imageWoodTech.png"));
       
        shapeButtons = new ArrayList();
        
        musicShapeButton = new CustomShapeButton(musicShapePosX, musicShapePosY, SEGMENT_SHAPE_LENGTH, SHAPE_HEIGHT, musicShapeImage);
        
        musicShapeButton.setBackground(Color.LIGHT_GRAY);
        musicShapeButton.setForeground(Color.WHITE);
        shapeButtons.add(musicShapeButton);
        
        tvShapeButton = new CustomShapeButton(tvShapePosX, tvShapePosY, SEGMENT_SHAPE_LENGTH, SHAPE_HEIGHT, tvShapeImage);
        
        tvShapeButton.setBackground(Color.LIGHT_GRAY);
        tvShapeButton.setForeground(Color.WHITE);
        shapeButtons.add(tvShapeButton);
    
        gamesShapeButton = new CustomShapeButton(gamesShapePosX, gamesShapePosY, SEGMENT_SHAPE_LENGTH, SHAPE_HEIGHT, gamesShapeImage);
        
        gamesShapeButton.setBackground(Color.LIGHT_GRAY);
        gamesShapeButton.setForeground(Color.WHITE);
        shapeButtons.add(gamesShapeButton);
    
        booksShapeButton = new CustomShapeButton(booksShapePosX, booksShapePosY, SEGMENT_SHAPE_LENGTH, SHAPE_HEIGHT, booksShapeImage);
        
        booksShapeButton.setBackground(Color.LIGHT_GRAY);
        booksShapeButton.setForeground(Color.WHITE);
        shapeButtons.add(booksShapeButton);
    
        techShapeButton = new CustomShapeButton(techShapePosX, techShapePosY, SEGMENT_SHAPE_LENGTH, SHAPE_HEIGHT, techShapeImage);
    
        techShapeButton.setBackground(Color.LIGHT_GRAY);
        techShapeButton.setForeground(Color.WHITE);
        shapeButtons.add(techShapeButton);
         
        this.setOpaque(false);
        this.setFocusable(true);
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
        
        Thread thread = new Thread(() -> animate());
        
        thread.start();
    }
    
    public void delay(int milliseconds)
    {
        try
        {
            Thread.sleep(milliseconds);
        } 
        catch (InterruptedException e)
        {
        }
    }
    
    @Override
    protected void paintComponent(Graphics g) 
    {
        super.paintComponent(g);
        
        Graphics2D g2 = (Graphics2D) g;
        
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  
        g2.setColor(getBackground().darker());
        g2.fillRect(0, 0, getWidth(), getHeight());
        
        for (CustomShapeButton shapeButton : shapeButtons)
        {
            shapeButton.paintComponent(g2);
        }
    }
     
    @SuppressWarnings({"SleepWhileInLoop", "empty-statement"})
    public synchronized void animate() 
    {
        while (true)
        {   
            if (musicButtonPressed == true)
            {
                animateButtonShapeMusic();
            }
            else if (tvButtonPressed == true)
            {
                animateButtonShapeTv();
            }
            else if (gamesButtonPressed == true)
            {
                animateButtonShapeGames();
            }
            else if (booksButtonPressed == true)
            {
                animateButtonShapeBooks();
            }
            else if (techButtonPressed == true)
            {
                animateButtonShapeTech();
            }
        
            delay(35);
            repaint();
        }
    }
    
    @Override
    public void mouseClicked(MouseEvent me) 
    {   
        for (int i = 0; i < shapeButtons.size(); i++)
        {
            Shape shape = shapeButtons.get(i);            
            
            //Mostrar os icones respetivos, consoante o botão seleccionado (if's)
            
            if (shape.contains(me.getPoint()))
            {
                switch (i) 
                {
                    case 0: 
                    {
                        buttonStop = false;
                        musicButtonPressed = true;
                        
                        System.out.println("Clicked on shape number " + i + " that represents the music button!");
                        
                        break;
                    }
                   
                    case 1:
                    {
                        tvButtonPressed = true;
                        
                        System.out.println("Clicked on shape number " + i + " that represents the tv button!");
                        
                        break;    
                    }
                        
                    case 2:
                    {
                        gamesButtonPressed = true;
                        
                        System.out.println("Clicked on shape number " + i + " that represents the games button!");
                        
                        break;
                    }
                        
                    case 3:
                    {
                        booksButtonPressed = true;
                        
                        System.out.println("Clicked on shape number " + i + " that represents the books button!");
                        
                        break;    
                    }
                        
                    case 4:
                    {
                        techButtonPressed = true;
                        
                        System.out.println("Clicked on shape number " + i + " that represents the tech button!");
                        
                        break;    
                    }
                        
                    default: break;
                }
            }
        }
    }
    
    @Override
    public void mouseEntered(MouseEvent me) 
    {             
    }
    
    @Override
    public void mousePressed(MouseEvent me) 
    { 
    }

    @Override
    public void mouseReleased(MouseEvent me) 
    {   
    }

    @Override
    public void mouseExited(MouseEvent me) 
    {   
    }
    
    @Override
    public void mouseDragged(MouseEvent me) 
    {
    }

    @Override
    public void mouseMoved(MouseEvent me) 
    {   
        for (int i = 0; i < shapeButtons.size(); i++)
        {
            Shape shape = shapeButtons.get(i);            
            
            //Mostrar os icones respetivos, consoante o botão seleccionado (if's)
            
            if (shape.contains(me.getPoint()))
            {
                switch (i) 
                {
                    case 0: 
                    {   
                        musicShapeButton.setBorder(BorderFactory.createLineBorder(Color.red, 4));
                        musicShapeButton.revalidate();
                        musicShapeButton.repaint();
                        
                        System.out.println("Entered on shape number " + i + " that represents the music button!");
                        
                        break;
                    }
                   
                    case 1:
                    {
                        tvShapeButton.setBorder(BorderFactory.createLineBorder(Color.red, 4));
                        tvShapeButton.revalidate();
                        tvShapeButton.repaint();
                        
                        System.out.println("Entered on shape number " + i + " that represents the tv button!");
                        
                        break;    
                    }
                        
                    case 2:
                    {
                        System.out.println("Entered on shape number " + i + " that represents the games button!");
                        
                        break;
                    }
                        
                    case 3:
                    {
                        System.out.println("Entered on shape number " + i + " that represents the books button!");
                        
                        break;    
                    }
                        
                    case 4:
                    {
                        System.out.println("Entered on shape number " + i + " that represents the tech button!");
                        
                        break;    
                    }
                        
                    default: break;
                }
            }
         }
    }
    
    public void animateButtonShapeMusic()
    {       
        if ((musicShapePosY <= 227.5f) && (buttonStop == false))
        {   
            musicShapePosY = musicShapePosY + SHAPE_SPEED;  
            SHAPE_SPEED = SHAPE_SPEED * (-1);
            
            if ((musicShapePosY == 227.5f) || (musicShapePosY == 100.0f))
            {
               buttonStop = true;
            }
        }
        
        if ((musicShapePosY >= 100.0f) && (buttonStop == false))
        {   
            musicShapePosY = musicShapePosY - SHAPE_SPEED;  
            SHAPE_SPEED = SHAPE_SPEED * (-1);
             
            if ((musicShapePosY == 100.0f) || (musicShapePosY == 227.5f))
            {
               buttonStop = true;
            }
        }
        
        musicShapeButton.setShapePosition(musicShapePosX, musicShapePosY); 
    }
    
    public void animateButtonShapeTv()
    {    
    }
    
    public void animateButtonShapeGames()
    {     
    }
    
    public void animateButtonShapeBooks()
    {     
    }
    
    public void animateButtonShapeTech()
    {    
    }
}

E o código da classe que implementa a Shape:

package dblauncher;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.JButton;

public final class CustomShapeButton extends JButton implements Shape
{   
    private float segmentLength;
    private float shapeHeight;
    
    private GeneralPath path;
    private BufferedImage image;

    public CustomShapeButton(float posX, float posY, float segmentLength, float shapeHeight)
    {   
        this(posX, posY, segmentLength, shapeHeight, null);
    }

    CustomShapeButton(float posX, float posY, float segmentLength, float shapeHeight, BufferedImage image) 
    {
        this.segmentLength = segmentLength;
        this.shapeHeight = shapeHeight;
        this.image = image;
        
        setShapePosition(posX, posY);
    }
    
    public void setShapePosition(float posX, float posY)
    {   
        float x0 = posX;
        float y0 = posY + shapeHeight;
        float x1 = posX - 3.0f + (segmentLength * 0.65f);
        float y1 = posY - segmentLength;
        float x2 = x1 - 6.0f + segmentLength * 1.35f;
        float y2 = y1;
        float x3 = x2 - 3.0f + (segmentLength * 0.65f);
        float y3 = y2 + shapeHeight + segmentLength;
        float x4 = x3 + 3.0f - (segmentLength * 0.65f);
        float y4 = y3 + shapeHeight + segmentLength;
        float x5 = x4 + 6.0f - (segmentLength * 1.35f);
        float y5 = y4;
        
        path = new GeneralPath();
        
        path.moveTo(x0, y0);
        path.lineTo(x1, y1);
        path.lineTo(x2, y2);
        path.lineTo(x3, y3);
        path.lineTo(x4, y4);
        path.lineTo(x5, y5);
        path.closePath();
    }
    
    @Override
    public Rectangle2D getBounds2D() 
    {
        return path.getBounds2D();
    }

    @Override
    public boolean contains(double d, double d1) 
    {
        return path.contains(d, d1);
    }

    @Override
    public boolean contains(Point2D pd) 
    {
        return path.contains(pd);
    }
    
    @Override
    public boolean intersects(double d, double d1, double d2, double d3) 
    {
        return path.intersects(d, d1, d2, d3);
    }

    @Override
    public boolean intersects(Rectangle2D rd) 
    {
        return path.intersects(rd);
    }

    @Override
    public boolean contains(double d, double d1, double d2, double d3) 
    {
        return path.contains(d, d1, d2, d3);
    }

    @Override
    public boolean contains(Rectangle2D rd) 
    {
        return path.contains(rd);
    }

    @Override
    public PathIterator getPathIterator(AffineTransform at) 
    {
        return path.getPathIterator(at);
    }

    @Override
    public PathIterator getPathIterator(AffineTransform at, double d) 
    {
        return path.getPathIterator(at, d);
    }
    
    public void translate(float distanceX, float distanceY) 
    {
        AffineTransform translation = new AffineTransform();
        
        translation.translate(distanceX, distanceY);
        path = (GeneralPath) path.createTransformedShape(translation);
    }
    
    @Override
    protected void paintComponent(Graphics g)
    {
        Graphics2D g2 = (Graphics2D) g;
        BasicStroke stroke = new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL);
        
        g2.setStroke(stroke);
        g2.setColor(getBackground());
        g2.fill(path);
        g2.setColor(getForeground());
        g2.draw(path);
        
        if (image != null)
        {
            Rectangle imageBounds = getBounds2D().getBounds();
            
            g2.drawImage(image, imageBounds.x, imageBounds.y, imageBounds.width, imageBounds.height, this);
        }
    }  
}

O que estarei fazendo de errado dentro do método mouseMoved()??

Obrigado,
J Amorim

Alguém disponível para dar uma ajuda, pf? Obrigado mais uma vez.