Exibição de imagens com eventos de mouse

Olá,

O programa a seguir exibe uma imagem de um arquivo png que pode ser arrastada no painel.

Problemas:

  • Se vc clicar em qualquer lugar do painel e arrastar o mouse, a imagem irá se teleportar para onde o mouse está.
  • Como adicionar mais imagens para que todas possam ser movimentadas livremente pelo painel, arrastando o mouse.
import java.awt.Graphics;  
import java.awt.Image;  
import java.awt.Toolkit;  
import java.awt.event.MouseEvent;  
import java.awt.event.MouseMotionListener;  
import javax.swing.ImageIcon;
import javax.swing.JPanel;  
      
public class Painel extends JPanel  
{  
    Toolkit toolkit = Toolkit.getDefaultToolkit();    
    Image image = toolkit.getImage(getClass().getResource("imagemPequena.png"));
    ImageIcon icon = new ImageIcon(image); // linha necessaria para ter retorno
    // correto dos metodos getWidth e getHeight da classe Image. Porque e necessario?
    // se comentar essa linha os metodos get listados acima retornam 0
    
    int x; // posicao x da imagem no painel
    int y; // posicao y da imagem no painel     
    int w; // coordenada x do centro da imagem
    int h; // coordenada y do centro da imagem
  
    @Override  
    protected void paintComponent(Graphics g)
    {  
        super.paintComponent(g);  
        g.drawImage(image, x, y, null);  
    }

    public Painel()
    {
        x = 0; // posicao inicial da imagem em x
        y = 0; // posicao inicial da imagem em y
        w = image.getWidth(null)/2; // coordenada x do centro da imagem
        h = image.getHeight(null)/2; // coordenada y do centro da imagem

        addMouseMotionListener(new Handler1()); // adicionando Handler
    }  
       
    class Handler1 implements MouseMotionListener
    {
        @Override
        public void mouseDragged(MouseEvent event)
        {  
            // pega as coordenadas do mouse e centraliza a imagem no mouse quando for arrastar  
            x = event.getX() - w;
            y = event.getY() - h;
            repaint();
        }
        
        @Override  
        public void mouseMoved(MouseEvent me)
        {  
        }
    }
}
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;

// Classe Main
public class Main
{
    public static void main( String[] args )
    {
        JFrame application = new JFrame( "Programa" );
        
        Painel painel = new Painel();
        
        application.add( painel, BorderLayout.CENTER );
        
        application.add( new JLabel( "Mensagem de fundo" ), BorderLayout.SOUTH );
        
        application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        application.setSize( 600, 400 );
        application.setVisible( true );
    }
}

Obrigado a quem se interessar em me ajudar.

Ten ha uma lsita de Image invés de uma unica.

E sobre o ImageIcon ali, carregue a imagem através da classe ImageIO que retorna um BufferedImage, esta contém os métodos getWidth e getHeight que funcionam corretamente,

Obrigado por responder.

Ainda continuo com os problemas iniciais.
Ao arrastar o mouse em um local que a imagem não está, não deveria acontecer nada, no entanto a imagem teleporta para o mouse.

Uma solução que pensei, ao invés de desenhar diretamente a imagem no JPanel, eu a colocaria no JLabel e depois colocaria este JLabel no JPanel.

Qual a vantagem que vi nisso? Poder setar evento no JLabel para que eu saiba se o mouse está em cima do JLabel para autorizar o movimento de arrastar a imagem e com isso eliminaria o problema inicial de teleporte de imagens, quando se arrasta o mouse fora da área da imagem.

Qual o problema que vi nisso? Será que é realmente necessário eu adicionar minhas imagens em vários JLabels para depois colocá-las no JPanel, para poder mover JLabels pelo JPanel que é o painel central?

Será que é possível desenhar as imagens diretamente no JPanel controlando eventos isolados para cada uma? Afinal eu quero adicionar várias imagens no painel e poder movê-las com o mouse livremente arrastando elas.

Valeu.

Neste código serão carregadas 3 imagens de arquivos png no JPanel.

Dúvida:
Como poder arrastar livremente qualquer uma das imagens carregadas no JPanel?

import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class Painel extends JPanel
{
    Point[] locations = new Point[3];
    BufferedImage[] images = new BufferedImage[3];
    
    public Painel()
    {
        // Posicoes iniciais das imagens
        locations[0] = new Point(0, 0);
        locations[1] = new Point(200, 0);
        locations[2] = new Point(0, 160);

        try
        {
            //Carregando imagens
            
            URL url = this.getClass().getResource("imagemPequena0.png");
            BufferedImage img = ImageIO.read(url);
            
            images[0] = img;
            url = this.getClass().getResource("imagemPequena1.png");
            img = ImageIO.read(url);
            images[1] = img;
            url = this.getClass().getResource("imagemPequena2.png");
            img = ImageIO.read(url);
            images[2] = img;
        }
        catch (IOException e)
        {
        }

        addMouseMotionListener(new Handler1()); // adicionando Handler
    }
    
    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        
        // Desenhando imagens de acordo com as posicoes setadas
        for(int i = 0; i < images.length; i++)
        {
            BufferedImage bi = images[i];
            Point p = locations[i];
            g.drawImage(bi, p.x, p.y, null);
        }
    }

    class Handler1 implements MouseMotionListener
    {
        @Override
        public void mouseDragged(MouseEvent event)
        {
        }
        
        @Override
        public void mouseMoved(MouseEvent me)
        {
        }
    }
}
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;

// Classe Main
public class Main
{
    public static void main( String[] args )
    {
        JFrame application = new JFrame( "Programa" );
        
        Painel painel = new Painel();
        
        application.add( painel, BorderLayout.CENTER );
        
        application.add( new JLabel( "Mensagem de fundo" ), BorderLayout.SOUTH );
        
        application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        application.setSize( 600, 400 );
        application.setVisible( true );
    }
}

Obrigado por ter lido.





Guarde a posição das imagens e interaja com a correta baseada no ACTION_DOWN do MouseEvent.

Estou pesquisando sobre o ACTION_DOWN e só encontrei referências para o desenvolvimento para Android ou seja em dispositivo touch screen.
Vc poderia indicar algo para eu ler ou enviar um exemplo?
Talvez esteja falando do mouseClicked do MouseListener. É isso?

O problema maior que enfrento é:
Quem dispara o evento é o JPanel, não são as imagens. Se cada imagem disparasse seu próprio evento e o JPanel recebesse as novas posições e redesenhasse o painel, seria uma solução para mim.

Obrigado pela ajuda.

Desculpe, eu quis dizer o MouseMotionListener e comparar com MOUSE_PRESSED, a idéia é a mesma.

E o JPanel mesmo que vai continuar recebendo os eventos, as imagens você que vai desenhar.

[quote=Marky.Vasconcelos]Desculpe, eu quis dizer o MouseMotionListener e comparar com MOUSE_PRESSED, a idéia é a mesma.

E o JPanel mesmo que vai continuar recebendo os eventos, as imagens você que vai desenhar.[/quote]

Trabalhando na solução.

Obrigado pela ajuda.

Não sei se vc achou solução cara, mas pra quem não achou aí abaixo vai um código que estou desenvolvendo. Talvez ajude mais alguém.

Estou com um problema apenas. A imagem adicionada fica piscando quando movimentada. O que eu poderia fazer?

[code]import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Mesas extends JPanel {
JLabel bg, objeto;

public Mesas() { //Painel

    setLayout(null);
    objeto = new JLabel();
    objeto.setBounds(new Rectangle(0, 0, 300, 284));
    objeto.addMouseMotionListener(new MouseAdapter() { //movimenta o objeto
        @Override
        public void mouseDragged(MouseEvent e) {
            moveLabel(e.getX(),e.getY());
        }
    });
    add(objeto);
    bg = new JLabel(new ImageIcon(this.getClass().getResource("/bg.jpg")));
    bg.setBounds(0,-10,2000,1500);
    add(bg);
}
public void addMesas(String url) { //adiciona um objeto do tipo image
    
    objeto.setIcon(new ImageIcon(this.getClass().getResource(url)));
}
public void moveLabel(int x, int y) {
        objeto.setLocation(x,y);
        objeto.repaint();
}

}[/code]