Exibição de imagens com eventos de mouse

8 respostas
J

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.

8 Respostas

M

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,

J

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.

J

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.





M

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

J

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.

M

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.

J

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.

Trabalhando na solução.

Obrigado pela ajuda.

P

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?

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();
    }
}
Criado 19 de setembro de 2013
Ultima resposta 14 de jan. de 2015
Respostas 8
Participantes 3