Изображение на форме перерисовывается только после сворачивания и повторного разворачивания, хотя в листенере вызывается метод repaint

Чёрный квадрат должен перетаскиваться мышкой. Если его начать тащить, координаты действительно меняются, но само изображение – нет. Но если свернуть окно и развернуть заново, то квадрат появляется в нужном месте. Почему так и что делать, чтобы при событии MouseDragged квадрат тащился за мышкой и изображение менялось?

import javax.swing.*;

public class Main {
    public static void main(String[] args)
    {
        JFrame jf = new JFrame();
        jf.setSize(500, 500);
        jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        A a = new A();
        jf.add(a);

        Listener l = new Listener(a.Bs);
        jf.addMouseMotionListener(l);
        jf.addMouseListener(l);

        jf.setVisible(true);
    }
}
import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;

public class A extends JPanel{
    public ArrayList<B> Bs;
    public A()
    {
        Bs = new ArrayList<>();
        Bs.add(new B());
    }


    @Override
    public void paint(Graphics g) {
        super.paint(g);
        for (B b: Bs)
            b.paint(g);
    }
}
import java.awt.*;
import javax.swing.*;

public class B extends JPanel {
    public int x;
    public int y;

    public final int width = 100;
    public final int height = 100;

    public B()
    {
        x=0;
        y=0;
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(x,y, width, height);
    }
}
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;

public class Listener implements MouseListener, MouseMotionListener {
    private ArrayList<B> bs;
    private boolean b_isBeingDragged;
    private int DistanceToTheEndX;
    private int DistanceToTheEndY;
    private B CurrentB;

    public Listener(ArrayList<B> bs)
    {
        this.bs=bs;
        b_isBeingDragged=false;
        DistanceToTheEndX=DistanceToTheEndY=0;
    }
    @Override
    public void mouseClicked(MouseEvent e) {}

    @Override
    public void mousePressed(MouseEvent e) {
        if(e.getButton() == MouseEvent.BUTTON1)
        {
            for( B s: bs)
            {
                if(e.getX() >= s.x && e.getX() <= (s.x + s.width) &&
                    e.getY() >= s.y && e.getY() <= (s.y + s.height))
                {
                    CurrentB=s;
                    DistanceToTheEndX=e.getX()-s.getX();
                    DistanceToTheEndY=e.getY()-s.getY();
                    b_isBeingDragged=true;
                    System.out.println(CurrentB.x+" "+CurrentB.y+" "+e.getX()+" "+ e.getY()+" "+"pressed");
                }
            }
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
       if(b_isBeingDragged)
       {
           b_isBeingDragged=false;
           CurrentB.x=e.getX();
           CurrentB.y=e.getY();
           CurrentB.repaint();
           System.out.println(CurrentB.x+" "+CurrentB.y+" "+e.getX()+" "+ e.getY()+" "+"released");
       }
    }

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e){}

    @Override
    public void mouseDragged(MouseEvent e) {
        if (b_isBeingDragged) {
            CurrentB.x = e.getX()-DistanceToTheEndX;
            CurrentB.y = e.getY()-DistanceToTheEndY;
            CurrentB.repaint();
            System.out.println(CurrentB.x+" "+CurrentB.y+" "+e.getX()+" "+ e.getY()+" "+"dragged");
            }
    }

    @Override
    public void mouseMoved(MouseEvent e) { CurrentB.repaint();}
}

Ответы (1 шт):

Автор решения: Олексій Моренець

Вот фикс того, что вам нужно, но там еще не совсем правильно координаты обновляются

public class Main {
    public static void main(String[] args)
    {
        JFrame jf = new JFrame();
        jf.setSize(500, 500);
        jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        A a = new A();
        jf.add(a);

        Listener l = new Listener(a);
        jf.addMouseMotionListener(l);
        jf.addMouseListener(l);

        jf.setVisible(true);
    }
}



public class Listener implements MouseListener, MouseMotionListener
{
    private ArrayList<B> bs;
    private A a;
    private boolean b_isBeingDragged;
    private int DistanceToTheEndX;
    private int DistanceToTheEndY;
    private B CurrentB;

    public Listener(A a)
    {
        this.a = a;
        this.bs = a.Bs;
        b_isBeingDragged = false;
        DistanceToTheEndX = DistanceToTheEndY = 0;
    }

    @Override
    public void mouseClicked(MouseEvent e)
    {
    }

    @Override
    public void mousePressed(MouseEvent e)
    {
        if (e.getButton() == MouseEvent.BUTTON1)
        {
            for (B s : bs)
            {
                if (e.getX() >= s.x && e.getX() <= (s.x + s.width) &&
                        e.getY() >= s.y && e.getY() <= (s.y + s.height))
                {
                    CurrentB = s;
                    DistanceToTheEndX = e.getX() - s.getX();
                    DistanceToTheEndY = e.getY() - s.getY();
                    b_isBeingDragged = true;
                    System.out.println(CurrentB.x + " " + CurrentB.y + " " + e.getX() + " " + e.getY() + " " + "pressed");
                }
            }
        }
    }

    @Override
    public void mouseReleased(MouseEvent e)
    {
        if (b_isBeingDragged)
        {
            b_isBeingDragged = false;
            CurrentB.x = e.getX();
            CurrentB.y = e.getY();
            a.repaint();
            System.out.println(CurrentB.x + " " + CurrentB.y + " " + e.getX() + " " + e.getY() + " " + "released");
        }
    }

    @Override
    public void mouseEntered(MouseEvent e)
    {
    }

    @Override
    public void mouseExited(MouseEvent e)
    {
    }

    @Override
    public void mouseDragged(MouseEvent e)
    {
        if (b_isBeingDragged)
        {
            CurrentB.x = e.getX() - DistanceToTheEndX;
            CurrentB.y = e.getY() - DistanceToTheEndY;
            a.repaint();
            System.out.println(CurrentB.x + " " + CurrentB.y + " " + e.getX() + " " + e.getY() + " " + "dragged");
        }
    }

    @Override
    public void mouseMoved(MouseEvent e)
    {
        a.repaint();
    }
}
→ Ссылка