Dificuldade com DrawLine, estou simplesmente tentando ligar um ponto ao outro

12 respostas
Jauns

Senhor(es)(as), procurei no forum porém não tive a felicidade de achar algo pra me ajudar… Estou tentando algo simples, porém não sei onde estou errando na minha chamada, estou tentando traçar uma reta, com o DrawLine, porém, naum sei o pq esta gerando este o erro.

public void paint(Graphics g)
	{

		int x=Integer.parseInt(jtX.getText());
		int y=Integer.parseInt(jtY.getText());
		int xx=Integer.parseInt(jtXX.getText());
		int yy=Integer.parseInt(jtYY.getText());

		g.drawLine(x,y,xx,yy);    // DA ERRO NA HORA DA CHAMADA
		jfF.repaint();
	}


	public void actionPerformed(ActionEvent evento) {

		if (evento.getActionCommand().equals("Desenhar")) {

			Graphics g = null;
			paint(g);

		}
	}

Se alguma alma caridosa ou não poder me ajudar, desde já agradeço.

Abaixo segue o código completo.

package arvore;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;


public class DLinha extends JFrame implements ActionListener {

	public JFrame jfF;
	public JButton jbInicio;
	public JLabel jlX,jlXX,jlY,jlYY;
	public JTextField jtX,jtXX,jtY,jtYY;

	public DLinha()
	{
		jfF = new JFrame("");
		jfF.setBounds(0,0,700,700);
		jfF.setLayout(null);

		jbInicio = new JButton("Desenhar");
		jbInicio.setBounds(600,5,90,25);
		jfF.add(jbInicio);
		jbInicio.setActionCommand("Desenhar");
		jbInicio.addActionListener(this);

		jlX= new JLabel("Posição X");
		jlX.setBounds(10,5,60,25);
		jfF.add(jlX);

		jtX= new JTextField();
		jtX.setBounds(75,5,50,25);
		jfF.add(jtX);

		jlY= new JLabel("Posição Y");
		jlY.setBounds(135,5,60,25);
		jfF.add(jlY);

		jtY= new JTextField();
		jtY.setBounds(200,5,50,25);
		jfF.add(jtY);

		jlXX= new JLabel("Posição XX");
		jlXX.setBounds(255,5,65,25);
		jfF.add(jlXX);

		jtXX= new JTextField();
		jtXX.setBounds(325,5,50,25);
		jfF.add(jtXX);

		jlYY= new JLabel("Posição YY");
		jlYY.setBounds(380,5,65,25);
		jfF.add(jlYY);

		jtYY= new JTextField();
		jtYY.setBounds(445,5,50,25);
		jfF.add(jtYY);

		jfF.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		jfF.setVisible(true);

	}

	public void paint(Graphics g)
	{

		int x=Integer.parseInt(jtX.getText());
		int y=Integer.parseInt(jtY.getText());
		int xx=Integer.parseInt(jtXX.getText());
		int yy=Integer.parseInt(jtYY.getText());

		g.drawLine(x,y,xx,yy);    // DA ERRO NA HORA DA CHAMADA
		jfF.repaint();
	}


	public void actionPerformed(ActionEvent evento) {

		if (evento.getActionCommand().equals("Desenhar")) {

			Graphics g = null;
			paint(g);

		}
	}

	public static void main (String[] arg)
	{
	DLinha dl=new DLinha();
	}
}

12 Respostas

ViniGodoy
  1. Você está sobrescrevendo um JFrame ou JPanel? Se for a segunda opção, vc deve sobrescrever o método paintComponent, não o paint;
  2. Que erro está dando? Desculpe, mas minha bola de cristal ficou no bolso da outra calça… :lol:
  3. Evite desenhar usando o Graphics recebido no parâmetro diretamente. Faça uma cópia usando o método create(), faça seu desenho, e ao final libere a cópia chamando dispose();
  4. Dá uma olhada nesse post:
    http://www.guj.com.br/posts/list/56063.java#294345
  5. Não chame o repaint de dentro do paint! O repaint vai chamar o paint, e vc cairá num loop infinito!!!
Jauns

[list]ViniGodoy [/list]

Desculpa a falha de não postar o erro.

Exception in thread “AWT-EventQueue-0” java.lang.NullPointerException

at arvore.DLinha.paint(DLinha.java:75)

at arvore.DLinha.actionPerformed(DLinha.java:85)

at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)

at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)

at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)

at javax.swing.DefaultButtonModel.setPressed(Unknown Source)

at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)

at java.awt.Component.processMouseEvent(Unknown Source)

at javax.swing.JComponent.processMouseEvent(Unknown Source)

at java.awt.Component.processEvent(Unknown Source)

at java.awt.Container.processEvent(Unknown Source)

at java.awt.Component.dispatchEventImpl(Unknown Source)

at java.awt.Container.dispatchEventImpl(Unknown Source)

at java.awt.Component.dispatchEvent(Unknown Source)

at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)

at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)

at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)

at java.awt.Container.dispatchEventImpl(Unknown Source)

at java.awt.Window.dispatchEventImpl(Unknown Source)

at java.awt.Component.dispatchEvent(Unknown Source)

at java.awt.EventQueue.dispatchEvent(Unknown Source)

at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)

at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)

at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)

at java.awt.EventDispatchThread.pumpEvents(Unknown Source)

at java.awt.EventDispatchThread.pumpEvents(Unknown Source)

at java.awt.EventDispatchThread.run(Unknown Source)
ViniGodoy

No seu ActionPerformed, você está chamando o método paint passando null no Graphics.
E ai é óbvio, ele não vai poder chamar drawLine num objeto nulo.

Você não deve chamar o método paint diretamente. No lugar, chame somente o repaint(). Ele se encarregará em chamar o paint, passando o contexto gráfico correto.

Também me parece que você nunca leu, ou leu muito pouco, sobre Java2D antes de usa-lo. Eu também não gosto de ler manuais, mas na programação não tem jeito, é necessário faze-lo. Então, dá uma boooa lida nessas páginas aqui, antes de se aventurar em voos mais altos:
http://java.sun.com/products/jfc/tsc/articles/painting/index.html#swing
http://java.sun.com/j2se/1.5.0/docs/guide/2d/spec/j2d-bookTOC.html

Jauns

[list]ViniGodoy [/list]

Este eh o primeiro codigo q tento em 2D, em relação a parte Grafica, estou aprendendo na curiosidade, muito bem vindo todos artigos indicados por vc, realmente não tinha lido nada sobre 2D, pensei que seria facil, pelo contrario, estou vendo que não é, esta fugindo muito do meu conhecimento.

A inteção desse codigo, eh para imprimir uma ARVORE_BINARIA, materia q estou estudando em ESTRUTURA DE DADOS,

Java com interface grafica so vou ver no proximo semestre.

Obrigado pelas dicas, vou continuar tentando resolver este problema.

ViniGodoy

Oi,

Eu imaginei. A idéia não foi ofende-lo, me desculpe se soou assim. O Java2D é muito simples de se usar, mas existem alguns conceitos que devem ser aprendidos antes de você começar, principalmente se você quiser interoperar com componentes do Swing.

Um exemplo de aplicação sem esse tipo de interoperabilidade seria você fazer um jogo, onde toda interface gráfica é desenhada na tela. Nesse caso, é mais fácil.

Pro seu caso, eu recomendo que você crie uma extensão de JComponent, e então faça a pintura nesse novo componente (não esqueça de definir a propriedade Opaque desse componente para true). Assim você poderá posicionar o local de pintura de maneira adequada, com o seu próprio Matisse ou Visual Editor.

Jauns

# ViniGodoy

Estou tentando usar JComponent como vc indicou... Só que o repaint() quado chamo ele não gera a linha... Se não for pedir muito, tem como vc comentar no codigo onde estou errando desta vez?

import java.awt.Color;

import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;


public class Teste extends JComponent implements ActionListener {
	public JButton jbInicio;
	public Teste() {

		this.setOpaque(true);
		
		final JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		frame.getContentPane().setLayout(new FlowLayout());

		frame.setSize(700,700);

		JButton jbInicio = new JButton("Desenhar");
		jbInicio.setBounds(600,5,90,25);
		frame.add(jbInicio);
		jbInicio.setActionCommand("Desenhar");
		jbInicio.addActionListener(this);

		frame.setVisible(true);
		frame.repaint();
	}

	protected void paintComponent(Graphics g) {
		System.out.println("TESTANDO CHAMADA");
		
		super.paintComponent(g);
		
		g.setColor(Color.ORANGE);
		
		g.drawLine(0,0,400,400);

	}

	public static void main(final String[] argv) {
		Teste tt=new Teste();

	}
	public void actionPerformed(ActionEvent evento) {

		if (evento.getActionCommand().equals("Desenhar")) {
			System.out.println("TESTANDO Botão");
			repaint();

		}
	}
}
ViniGodoy

Faltou adicionar o seu JComponent no seu JFrame.

ViniGodoy

Ok, vai aí um exemplo para você:

package lines;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class LineFrame extends JFrame {
    private JPanel jContentPane = null;
    private JPanel pnlTxt = null;
    private JTextField txtX1 = null;
    private JTextField txtY1 = null;
    private JTextField txtX2 = null;
    private JTextField txtY2 = null;
    private JButton btnDesenhar = null;
    private LinePanel linePanel = null;

    public LineFrame() {
        super();
        initialize();
    }

    private void initialize() {
        this.setSize(465, 324);
        this.setContentPane(getJContentPane());
        this.setTitle("Desenha linhas");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
    }

    private JPanel getJContentPane() {
        if (jContentPane == null) {
            jContentPane = new JPanel(new BorderLayout());
            jContentPane.add(getPnlTxt(), BorderLayout.NORTH);
            
            //Inserimos o painel desenhador de linhas no centro.
            jContentPane.add(getLinePanel(), BorderLayout.CENTER);
        }
        return jContentPane;
    }

    private JPanel getPnlTxt() {
        if (pnlTxt == null) {                       
            pnlTxt = new JPanel(new FlowLayout());
            pnlTxt.add(new JLabel("Desenhar linha de: ("));
            pnlTxt.add(getTxtX1());
            pnlTxt.add(new JLabel(","));
            pnlTxt.add(getTxtY1());
            pnlTxt.add(new JLabel(") até ("));
            pnlTxt.add(getTxtX2());
            pnlTxt.add(new JLabel(","));
            pnlTxt.add(getTxtY2());
            pnlTxt.add(new JLabel(")"));
            pnlTxt.add(getBtnDesenhar());
        }
        return pnlTxt;
    }

    private JTextField getTxtX1() {
        if (txtX1 == null) {
            txtX1 = new JTextField();
            txtX1.setPreferredSize(new Dimension(30, 20));
        }
        return txtX1;
    }

    private JTextField getTxtY1() {
        if (txtY1 == null) {
            txtY1 = new JTextField();
            txtY1.setPreferredSize(new Dimension(30, 20));
        }
        return txtY1;
    }

    private JTextField getTxtX2() {
        if (txtX2 == null) {
            txtX2 = new JTextField();
            txtX2.setPreferredSize(new Dimension(30, 20));
        }
        return txtX2;
    }

    private JTextField getTxtY2() {
        if (txtY2 == null) {
            txtY2 = new JTextField();
            txtY2.setPreferredSize(new Dimension(30, 20));
        }
        return txtY2;
    }

    private JButton getBtnDesenhar() {
        if (btnDesenhar == null) {
            btnDesenhar = new JButton();
            btnDesenhar.setText("Desenhar");
            btnDesenhar.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent e) {
                    onDesenhar();
                }
            });
        }
        return btnDesenhar;
    }

    private LinePanel getLinePanel() {
        if (linePanel == null) {
            linePanel = new LinePanel();
        }
        return linePanel;
    }

    /**
     * Simplesmente parseamos o conteúdo dos JTextFields e chamamos o método em
     * nosso componente desenhador de linhas.
     */
    private void onDesenhar() {
        try {
            getLinePanel().setLinePos(Integer.parseInt(getTxtX1().getText()),
                    Integer.parseInt(getTxtY1().getText()), Integer
                            .parseInt(getTxtX2().getText()), Integer
                            .parseInt(getTxtY2().getText()));
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(this, "Coordenadas inválidas!");
        }
    }

    /** Iniciamos o programa */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new LineFrame().setVisible(true);
            }
        });
    }
}

E para o painel que desenha as linhas:

package lines;

import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JComponent;

/**
 * Esta é a classe que desenha a linha.
 */
public class LinePanel extends JComponent {
    //Guardamos o local onde a linha será desenhada.
    //Precisamos saber essas coordenadas pq precisaremos redesenhar a linha
    //sempre que a janela tornar-se invisível e visivel novamente, ou sempre 
    //que um comando de repaint for dado.
    
    //O Java2D não irá guardar o conteúdo da janela para nós.
    private int x1;
    private int x2;
    private int y1;
    private int y2;

    public LinePanel() {
        super();
        //Indica que nosso componente não é transparente.
        //Isso permite que o swing otimize a pintura.
        setOpaque(true);
    }

    /**
     * Altera o local onde a linha será desenhada.
     * @param x1 Posição x1 da linha
     * @param y1 Posição y1 da linha
     * @param x2 Posição x2 da linha
     * @param y2 Posição y2 da linha
     */
    public void setLinePos(int x1, int y1, int x2, int y2) {
        this.x1 = x1;
        this.x2 = x2;
        this.y1 = y1;
        this.y2 = y2;
        //Como o desenho mudou, vamos solicitar ao Swing para repintar
        //esse componente.
        repaint();
    }

    /**
     * Faz o desenho da linha.
     */
    @Override
    protected void paintComponent(Graphics g) {
        //Tiramos a cópia do contexto gráfico, pois o Java2D exige que não
        //alteremos o estado do g recebido no parâmetro.
        Graphics2D g2d = (Graphics2D) g.create();
        
        //Desenhamos a linha
        g2d.drawLine(x1, y1, x2, y2);
        
        //Como já terminamos de usar a cópia, podemos libera-la.
        g2d.dispose();
    }
}

Qualquer dúvida é só perguntar.

ViniGodoy

PS: Se a idéia é só impressionar os professores, dá uma olhada nessa biblioteca aqui:
http://www.prefuse.org/

Jauns

ViniGodoy

O que venho descobrindo é que o java é muito fascinante, qto mais estuda, mais se percebe que não se sabe nada. E o aprendizado da parte gráfica e 2D é um desafio pessoal, e nao para impressionar professor, e sim vontade de aprender mesmo.

Muito obrigado por sua ajuda, com calma vou estudar os codigos que vc postou.

ViniGodoy

Então aprenda de uma forma mais divertida:
http://www.cokeandcode.com/node/6
http://fivedots.coe.psu.ac.th/~ad/jg/

Jauns

ViniGodoy:
Então aprenda de uma forma mais divertida:

Cara, vou guardar a sete chaves este material que vc esta indicado.

Criado 19 de setembro de 2008
Ultima resposta 19 de set. de 2008
Respostas 12
Participantes 2