Arrastar componentes

tenho um jframe que que nele tem alguns botões e Label, tem alguma maneira de fazer com que o usuário possa alterar posição (arrastando) e tamanho em tempo de execução?
na aplicação que eu quero implementar isso ela irá ter uma foto de fundo(utilizando uma label e altero a icon dela)e essa jlabel o usuário poderá alterar o tamanho e posição conforme tamanho do jframe.

Alguem sabe me dizer como posso fazer isso?

Vc já conseguiu colocar um JLabel como imagem de fundo? Porque isso é difícil de fazer. Agora fazer o JLabel redimensionar ou mover é praticamente impossível, pelo menos não conheço um meio fácil.

O meio que conheço para fazer isso seria criar um componente próprio (não daria com JLabel) e criar também um Layout específico, criar todos os eventos do mouse para o drag-n-drop (arrastar) e efetuar vários cálculos para redimensionar com o JFrame, levaria algumas semanas.

Talvez uma forma mais simples seria buscando uma biblioteca, no Java não tem pronto.

Consegui fazer ele movimentar em tempo real, porém preciso fazer o redimencionamento também em tempo real, onde o usuário possa mudar o tamanho do componente.

new Mover().start();
lb_logo.addMouseListener(new MouseListener() {
public void mouseReleased(MouseEvent e) {
mousePressionado = false;
}

        public void mousePressed(MouseEvent e) {
            mousePressionado = true;
        }

        public void mouseExited(MouseEvent e) {
        }

        public void mouseEntered(MouseEvent e) {
        }

        public void mouseClicked(MouseEvent e) {
            //l.setIcon((Icon) lb_logo);
        }
    });
}

public class Mover extends Thread {

    public void run() {
        while (true) {
            Point ponto = getMousePosition();
            try {
                sleep(10);
            } catch (Exception e) {
                System.out.println("classe mover");
            }
            if (mousePressionado) {
                
                lb_logo.setBounds(ponto.x - 70, ponto.y - 65, 150, 80);
            }
            if(ponto != null) {
                
            }
        }
    }
}

Primeiro arrumar isso removendo a thread:

MouseAdapter mouseListener = new MouseAdapter() {
  public void mouseReleased(MouseEvent e) {
    mousePressionado = false;
  }
  public void mousePressed(MouseEvent e) {
    mousePressionado = true;
  }
  public void mouseDragged(MouseEvent e) {
    if (mousePressionado) {
      Point ponto = e.getPoint();
      lb_logo.setBounds(ponto.x - 70, ponto.y - 65, 150, 80);
    }
  }
}

addMouseListener(mouseListener);
addMouseMotionListener(mouseListener);

Não sei se tem como redimensionar a imagem usando o JLabel, eu usaria o JComponent e o paintComponent.

  public void mousePressed(MouseEvent e) {
    Point ponto = e.getPoint();
    if (ponto.y < 10) redimensionarParaCima = true;
    else if (ponto.y > lb_logo.getHeight() - 10) redimensionarParaBaixo = true;
    // acho que seriam 8 direções
    // else mousePressionado = true;
    else mover = true;
  }

Retirar a thread? mas no exemplo vc colocou “mover” seria a classe que eu coloquei? não intendi…

não:

// else mousePressionado = true;
else mover = true; // equivalente a mousePressionado, recomendo mudar o nome da variavel

Fiz uma mudança para ficar mais claro, arrume isso removendo a thread. Depois de testar e funcionar eu ajudo a redimensionar

MouseAdapter mouseListener = new MouseAdapter() {
  public void mouseReleased(MouseEvent e) {
    mousePressionado = false;
  }
  public void mousePressed(MouseEvent e) {
    mousePressionado = true;
  }
  public void mouseDragged(MouseEvent e) {
    if (mousePressionado) {
      Point ponto = e.getPoint();
      lb_logo.setBounds(ponto.x - 70, ponto.y - 65, 150, 80);
    }
  }
}

lb_logo.addMouseListener(mouseListener);
lb_logo.addMouseMotionListener(mouseListener);

alterei o código, porém esta tendo um bug, quando clica na imagem a imagem fica movimentando sem mexer no mouse.
você aconselha modificar o jlabel para um JComponent?

Me desculpe, lembro de ter feito algo parecido e não encontrei aqui:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Teste extends JFrame {
    public Teste() {
        JPanel lb_logo = new JPanel();
        lb_logo.setBackground(Color.RED);
        lb_logo.setBounds(0, 0, 150, 80);
        getContentPane().setLayout(null);
        getContentPane().add(lb_logo);
        MouseAdapter mouseListener = new MouseAdapter() {
            Point pressed;
            Point pressedLocation;
            public void mouseReleased(MouseEvent e) {
                pressed = null;
            }
            public void mousePressed(MouseEvent e) {
                pressed = e.getLocationOnScreen();
                pressedLocation = new Point(lb_logo.getX(), lb_logo.getY());
            }
            public void mouseDragged(MouseEvent e) {
                if (pressed != null) {
                    Point ponto = e.getLocationOnScreen();
                    lb_logo.setLocation(pressedLocation.x + ponto.x - pressed.x,
                            pressedLocation.y + ponto.y - pressed.y);
                }
            }
        };
        lb_logo.addMouseListener(mouseListener);
        lb_logo.addMouseMotionListener(mouseListener);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }
}

Na verdade eu não sei fazer isso usando o JLabel, eu usaria o JComponent e sobrescreveria o paintComponent.

1 curtida

alterei o código pelo que me enviou agora e funcionou perfeitamente para movimentar, sem nenhum bug. Estou a procura de alguma forma de redimensionar o objeto agora.
para adicionar a imagem no Jlabel eu uso o seguinte código:

ImageIcon im = new ImageIcon(“C:\logo.png”);
Image i = im.getImage().getScaledInstance(lb_logo.getWidth(), lb_logo.getHeight(), Image.SCALE_SMOOTH);
lb_logo.setIcon(new ImageIcon(i));

Vou deixar para vc, não tenho ideia de como resolver isso, mas consegui recriar o que tinha feito num projeto que perdi:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.plaf.basic.BasicInternalFrameUI;
public class DT extends JFrame {
    public DT() {
        JDesktopPane root = new JDesktopPane();
        getContentPane().add(root);
        
        JInternalFrame frame = new JInternalFrame("",true,false,false,false);
        frame.setBounds(50, 50, 300, 200);
        frame.setVisible(true);
        
        JPanel lb_logo = new JPanel();
        lb_logo.setBackground(Color.RED);
        lb_logo.setBounds(0, 0, 150, 300);
        
        BasicInternalFrameUI bi = (BasicInternalFrameUI) frame.getUI();
        
        // desejado
        // bi.setNorthPane(lb_logo);
        
        // indesejado começa
        bi.setNorthPane(null);
        frame.add(lb_logo);
        // indesejado temina
        
        root.add(frame);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }
}

A parte que está desejado, funciona tudo, movimento e redimensionamento de componentes, mas tem um problema que não consegui resolver, fica uma barra acima. A parte que está indesejado, funciona, mas terá que adaptar com que já foi feito. Não dá para remover a borda, mas dá para substituir usando o setBorder.

Essa é a forma mais simples, caso não tenha interesse, teria que alterar o MouseAdapter onde o press terá uma função diferente dependendo de onde for clicado.

1 curtida

Obrigado Diego, me ajudou bastante.
Este código como eu posso implementar com o outro ? pois você disse que esse esta funcionando o redimensionamento…

Acho que teria que adicionar aquele listener no label e alterar o setLocation para mover o frame interno:

                frame.setLocation(pressedLocation.x + ponto.x - pressed.x,
                        pressedLocation.y + ponto.y - pressed.y);

o pressedLocation (tentei trocar lá por lastLocation mas deu erro no GUJ e não consegui) também:

pressedLocation = new Point(frame.getX(), frame.getY());

Olha a alteração que fiz deu certo consegui colocar o redimensionamento , porém ele não redimensiona a imagem. hehe estou na luta.

MouseAdapter mouseListener = new MouseAdapter() {
Point pressed;
Point pressedLocation;
Point point;

        public void mouseReleased(MouseEvent e) {
            pressed = null;
        }

        public void mousePressed(MouseEvent e) {
            point = e.getPoint();

        }

        public void mouseMoved(MouseEvent e) {
            Point point = e.getPoint();
            Component component = e.getComponent();
            int width = component.getWidth() - point.x;
            int height = component.getHeight() - point.y;

            if (width <= 4 && height <= 4) {
                component.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
                resize = true;
            } else {
                component.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
                resize = false;
            }
        }

        public void mouseDragged(MouseEvent e) {
            Component component = e.getComponent();
            if (resize) {
                component.setSize(e.getX(), e.getY());
            } else {
                component.setLocation(component.getLocation().x + (e.getX() - point.x),
                        component.getLocation().y + (e.getY() - point.y));
            }
        }
    };
    lb_logo.addMouseListener(mouseListener);
    lb_logo.addMouseMotionListener(mouseListener);

Se usar o JComponent, ficaria:

class JImage extends JComponent {

  Image img;
  public JImage(String arquivo) {
    img = ImageIO.read(new File(arquivo)); 
  }
  public void paintComponent(Graphics g) {
    if (g != null) g.drawImage(img, 0, 0, getWidth(), getHeight(), null)
  }
}