Java2D - Draw usando o mouse?

Salve galera…Seguinte, estou tentando criar uma linha usando o mouse. Ate consigo criar, mas quero que enquanto o mouse estiver como pressed (mousePressed), va exibindo a linha ate seu ponto final…Pesquisei muito, vi bastante exemplo por ai no google, mas ainda naum consegui fazer.
Quem puder ajudar, ai vai meu codigo.

public class DrawLine extends JPanelDesktopWork{
    private JPanelDesktopWork jdw; //painel q exibe o desenho, eu pego o Graphics dele.  
    private Point2D start, end;        
    
    public DrawLine(JPanelDesktopWork jdw){        
        this.jdw = jdw;
        
        jdw.addMouseMotionListener(new MouseAdapter() {
            public void mouseDragged(MouseEvent e){
                end = new Point2D.Double(e.getX(), e.getY());
                repaint();
            }
        });
        
        jdw.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e){
                start = new Point2D.Double(e.getX(), e.getY());
                end = start;
            }
            
            public void mouseReleased(MouseEvent e){                
                createLine();
                start = null;
                end = null;
            }
        });
    }
       
    
    public void createLine(){       
        Graphics2D g2d = (Graphics2D)this.jdw.getGraphics(); //aqui onde pego o Graphics.
        Line2D line = new Line2D.Float(start,end);  
        g2d.draw(line);     
        repaint();  
    }
    
}

Voce precisa do evento MouseDragged da interface MouseMotionListener para ter os eventos arrastando.

Fernando,

Algo não fazia sentido no teu codigo.

Se ele herda de um JPanel, por que voce instancia outro dentro da classe para desenhar nele.
Esse outro é apenas virtual nao está atrelado em nenhum componente. Onde será desenhado?

Então fiz umas mudanças:

[code]
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JPanel;

public class DrawLine extends JPanel{

private Point2D start, end;           
   
public DrawLine(){           
    addMouseMotionListener(new MouseAdapter() {   
        public void mouseDragged(MouseEvent e){   
            end = new Point2D.Double(e.getX(), e.getY());   
            createLine();   
        }   
    });   
       
    addMouseListener(new MouseAdapter() {   
        public void mousePressed(MouseEvent e){   
            start = new Point2D.Double(e.getX(), e.getY());   
            end = start;   
        }   
           
        public void mouseReleased(MouseEvent e){                   
            createLine();   
            start = null;   
            end = null;   
        } 
    });   
}   
     
   
public void createLine(){         
    Graphics2D g2d = (Graphics2D)getGraphics(); //aqui onde pego o Graphics.   
    Line2D line = new Line2D.Float(start,end);     
    g2d.draw(line);   
}          

}[/code]

E criei um pequeno proejto de teste que coloquei em anexo.

Nao tenho esse tal de JDeskTopPane então usei um simples JPanel.

Nao sei se é bem isso que você quer, o certo era ir continuando
a linha e não manter o start fixo, mas segui seu codigo.

Qualquer coisa fale.

Acrescentei só uma linha no último método e
beleza, desenhou como uma caneta:

public void createLine(){         
        Graphics2D g2d = (Graphics2D)getGraphics(); //aqui onde pego o Graphics.   
        Line2D line = new Line2D.Float(start,end);     
        g2d.draw(line);
        start = end;
    } 

Opa Joao…eh o seguinte, eu instancio pq eh como se fosse uma area de trabalho, e eu usando super naum estava conseguindo pegar o graphics setado nele…

algo do tipo.

public class DesktopWork extends JPanel{ //aqui eh onde vai receber os desenhos, como se fosse uma area de trabalho
     public DesktoWork(){
     }
     public void paintComponent(Graphics g){
         Graphics2D g2d = (Graphics2D)g;
     }
}

public class DrawLine extends DesktopWork{ //aqui a classe q desenho linhas
     private DesktoWork dw; //aqui o jpanel q recebe o desenho eh instanciado
     
     public DrawLine(DesktopWork dw){
             this.dw = dw;
     }
    
     public void criaLinha(){
         Graphics2D g2d = (Graphics2D)this.dw.getGraphics(); //aqui eu pego o graphics q foi definido no panel DesktopWork q recebera a linha
 
         Graphics2D g2 = (Graphics2D)super.getGraphics(); //usando super naum funciona, ainda naum sei o pq mas to na pesquisa
        //aqui tento desenhar a linha
        g2.draw(linha); //pegando da super da erro         
     }
}

Joao, veja os comentarios…Se puder ajudar, agradeço. !

obrigado

Desculpa cara mas ainda não faz sentido.

Se o teu DesktopWork é um JPanel, ele tem o Graphics dele. No momento que voce o instanciou na tua GUI, ele vai responder ao repaint.

O repaint dispara o paint e pronto, voce faz um paint sobrescrito que faça o teu processo de desenho. Isso já é automatico, você nao precisa ficar capturando Graphis.

Se quiser ajuda poste o código total e tento ajudar. Assim, tentando imaginar por que voce fez isso é muito dificil de entender.

Peguei o teu DesktopWork e coloquei no meu projeto. Deu na mesma.

Ou seja, usando no extends do DrawLine o teu DesktopWork , ou usando o JPanel do java, dá na mesma.

Ou seja não é necessário teu DesktopWork para pegar o Graphics2D, isso ja esta automatico no JPanel.

Em anexo o projeto usando o teu DesktopWork.

Não amigo, você está entendo errado.

Faça o seguinte passos(no primeiro código que você postou):

Copie o código que está em createline()

Apagueo método createline().

Sobrescreva o método paintComponent(Graphics g)

Cole o código que você copiou dentro desse método.

No código que você colou, subistitua this.jdw.getGraphics() por g.

Nos lugares onde você chamava create line, chame repaint() agora.

Acrescente o método mouse dragged nos seus listenner e pronto.

Tente rodar. Se funcionar ótimo, se não, poste todo o código que você alterou aqui.

A explicação agora: você, assim como 90% das pessoas que programam em java, acha que o objeto graphics é um papel onde você desenha seu componente e tudo que nele existe. Também acha que cada componente só tem um objeto graphics e que tudo que você desenhar uma vez, vai ficar lá pra sempre até você mandar tirar. Ledo engano.

A verdade: o objeto graphics, na verdade, é mais como um pincel(ou caneta, como diz o vinigodoy). E toda vez que você usa o getGraphic, você pega um novo pincel pra desenhar no componente. Contudo, as mudança não são impressas em tempo real. Você precisa avisar ao swing que fez um desenho e que o componente precisa ser atualizado(é aqui que as coisas ficam complicadas). Pra isso que serve o método repaint(). O problema, é que toda vez que você chama repaint, você apaga tudo que você desenhou antes. Então, pra desenhar algo, você precisa garantir que a cada repaint ele seja redesenhado. Pra isso que serve o paint component. É nesse método que você precisa colocar tudo que você quer que seja desenhado. Se tiver mais dúvidas, posta aí.

Um exemplo simples:

public class DrawLine extends JPanel {
    private Point2D start, end;

    public DrawLine() {

        addMouseMotionListener(new MouseAdapter() {
            public void mouseDragged(MouseEvent e) {
                end = new Point2D.Double(e.getX(), e.getY());
                repaint();
            }
        });

        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                start = new Point2D.Double(e.getX(), e.getY());
                end = start;
            }
        });
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g.create();
        Line2D line = new Line2D.Float(start, end);
        g2d.draw(line);
        g2d.dispose();
    }
    
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setContentPane(new DrawLine());
        frame.setSize(400, 400);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

João, ElissonAndrade…Entendi bem o q querem dizer, mas vou tentar dizer aqui meu cenário como está. E assim q possivel posto o código, mas desde já agradeço a ajuda de vcs.

É assim. No meu JFrame principal, eu tenho um JTabbedPane controla os JPanels de desenho (classe DesktopWork), a medida q vou adicionando novos projetos(novas abas de JTabbedPane) vaum sendo add novos JPanel(DesktopWork) de desenhos.
Entaum para desenhar por exemplo na aba do JTabbedPane eu clico nela, pego seu indice clico na ferramenta “Line” entaum passo o JPanel de desenho para a classe DrawLine, assim eu sei em qual aba do JTabbedPane esta sendo desenhada.

vejam o codigo.

//frame principal
public class PrincipalFrame extends javax.swing.JFrame {
    private JTabbedPane jtp = new JTabbedPane();
    private ArrayList<DesktopWork> lDw = new ArrayList<DesktopWork>();
    private DesktopWork dw;

    public PrincipalFrame() {
        initComponents();
        this.setLocationRelativeTo(null);
    }
    
    public void criaNovoProjeto(){
        public void criaProjetos(){
        dw = new DesktopWork();
        jtp.addTab("tab", dw);
        lDw.add(dw);
        this.setLayout(new BorderLayout());
        this.add(tools, BorderLayout.NORTH);
        this.add(jtp, BorderLayout.CENTER);        
    }

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        int i = this.jtp.getSelectedIndex(); //aqui eu pego a tab q ta ativa
        DrawLine dl = new DrawLine(dw); //aqui eu mando o jpanel q ta ativo para a classe DrawLine, para poder desenhar a linha na tab ativa.
        dl.criaLinha();
    }

   private void btnNovoActionPerformed(java.awt.event.ActionEvent evt) {
          criaNovoProjeto();
   }
}


// DesktopWork
public class DesktopWork extends JPanel{ //aqui eh onde vai receber os desenhos, como se fosse uma area de trabalho  
     public DesktoWork(){  
     }  
     public void paintComponent(Graphics g){  
         Graphics2D g2d = (Graphics2D)g;  
     }  
}  


// aqui a classe DrawLine
public class DrawLine extends DesktopWork{ //aqui a classe q desenho linhas  
     private DesktopWork dw; //aqui o jpanel q recebe o desenho eh instanciado  
       
     public DrawLine(DesktopWork dw){  
             this.dw = dw;  
     }  
      
     public void criaLinha(){  
         Graphics2D g2d = (Graphics2D)this.dw.getGraphics(); //aqui eu pego o graphics q foi definido no panel DesktopWork q recebera a linha  
         Line2D line = new Line2D.Double(20,20,100,100); 
         Graphics2D g2 = (Graphics2D)super.getGraphics(); //usando super naum funciona, ainda naum sei o pq mas to na pesquisa  
        //aqui tento desenhar a linha  
        g2d.draw(line); //pegando da super da erro           
     }  
}  

Eh mais ou menos isso ae, o codigo real eu to sem aqui pq ta no meu note em casa, mas eh esse esquema ae q to seguindo…Num sei se ta correto, qquer ajuda sempre bem vinda.

obrigado.

Então cara, é preciso que você entenda:, você não pode desenhar no componente por fora, só por dentro. Nenhum código de desenho pode estar fora da classe DestopWork, só pode estar dentro, por isso que getGraphics não funciona.

Entenda novamente: os componentes não são papéis em branco onde você desenha o que quer. Se quer que um componente seja desenhado de forma diferente, você precisa alterar o componente.