Árvore Binária Gráfica

2 respostas
S

Galera, sou estudante de Computação e me deparei com um trabalho que está me tirando o sono. Meu professor de Estrutura de Dados está nos ensinando Árvores Binárias e pediu que nós criássemos um programa que exiba a construção passo a passo da árvore de forma gráfica. Eu escolhi como linguagem o Java por sua portabilidade e por já ter estudado também. Só que nunca havia estudado a biblioteca gráfica AWT. Então, estou meio perdido. Depois de muita pesquisa, consegui criar a janela, que é super simples quando se tem uma IDE. Sei que muita gente prefere o Eclipse, e tem seus motivos, mas estou usando o NetBeans por me familiarizar mais com ele. Nada contra o Eclipse! Já criei a classe No, que representa cada nó da árvore, e a classe principal. Também comecei a criar a classe Arvore. O problema está em como vou fazer para que os nós sejam exibidos na árvore. Todo esse trabalho foi feito com muita pesquisa. E já pesquisei bastante para resolver esse problema, mas não consegui encontrar nada. Preciso de ajuda! Como meu código está muito grande, criei uma versão menor para apresentar a vocês que foca mais no que eu pretendo. Abaixo seguem os códigos.

Classe Principal:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package teste;

import javax.swing.JFrame;

/**
 *
 * @author Sergio
 */
public class Teste {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        f.setTitle("Teste");
        f.setSize(800, 600);
        f.setLocationRelativeTo(null);
        
        No n = new No(12);
        f.add(new Arvore());
        
    }
}

Classe No:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package teste;

import java.awt.BasicStroke;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

/**
 *
 * @author Sergio
 */
public class No extends JPanel{
    
    public No(){
        val = 0;
        alt = 0;
        pai = null;
        filDir = null;
        filEsq = null;
    }
    
    public No(int v){
        val = v;
        alt = 0;
        pai = null;
        filDir = null;
        filEsq = null;
    }
    
    public void setVal(int val){
        this.val = val;
    }
    
    public int getVal(){
        return val;
    }
    
    public void setAlt(int alt){
        this.alt = alt;
    }
    
    public int getAlt(){
        return alt;
    }
    
    public void setPai(No pai){
        this.pai = pai;
    }
    
    public No getPai(){
        return pai;
    }
    
    public void setFilDir(No filDir){
        this.filDir = filDir;
    }
    
    public No getFilDir(){
        return filDir;
    }
    
    public void setFilEsq(No filEsq){
        this.filEsq = filEsq;
    }
    
    public No getFilEsq(){
        return filEsq;
    }
    
    public void setPosX(int posX){
        this.posX = posX;
    }
    
    public int getPosX(){
        return posX;
    }
    
    public void setPosY(int posY){
        this.posY = posY;
    }
    
    public int getPosY(){
        return posY;
    }
    
    public void paint(Graphics g){
        Graphics2D g2d = (Graphics2D) g;
        
        Font a = new Font("Arial",Font.BOLD,16);
        
        if (filDir != null){
            g2d.drawLine(posX + (tam / 2), posY + (tam / 2), filDir.posX + (tam / 2), filDir.posY + (tam / 2));
        }
        
        if (filEsq != null){
            g2d.drawLine(posX + (tam / 2), posY + (tam / 2), filEsq.posX + (tam / 2), filEsq.posY + (tam / 2));
        }
        
        g2d.setStroke(new BasicStroke(3));
        g2d.drawOval(posX, posY, tam, tam);
        //tenta centralizar o texto no centro do circulo.
        g2d.setFont(a);
        g2d.drawString(String.valueOf(val),
                posX + ((tam / 2) - 4 * (String.valueOf(val).length())), 
                posY + ((tam / 2) + 4));
    }
    
    //atributos privados.
    private int val;
    private int alt;
    private No pai;
    private No filDir;
    private No filEsq;
    //variaveis do no grafico.
    private int tam = 50;
    private int posX;
    private int posY;
}

Classe Arvore:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package teste;

import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

/**
 *
 * @author Sergio
 */
public class Arvore extends JPanel{
    
    public Arvore(){
        raiz = null;
    }
    
    public Arvore(No raiz){
        this.raiz = raiz;
    }
    
    public void setRaiz(No raiz){
        this.raiz = raiz;
    }
    
    public No getRaiz(){
        return raiz;
    }
    
    public void paint(Graphics g){
        Graphics2D g2d = (Graphics2D) g;
        
        
    }
    
    
    private No raiz;    
}

Pelo que entendi, tenho que exibir um JPanel(No) em outro JPanel(Arvore). Só não sei como faz. A minha classe No está funcionando. Se rodarem o código abaixo, é criado um nó no JFrame.

Classe Principal com No instanciado:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package teste;

import javax.swing.JFrame;

/**
 *
 * @author Sergio
 */
public class Teste {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        f.setTitle("Teste");
        f.setSize(800, 600);
        f.setLocationRelativeTo(null);
        
        No n = new No(12);
        f.add(n);
        
        
    }
}

Desde já, agradecido!

2 Respostas

T

Não sei se é uma boa ideia ficar misturando Swing com AWT (mais que o necessário, porque em alguns casos é inevitável). Se entendi seu problema, você quer desenhar os nós de uma árvore em um JPanel (que é Swing), certo? Mas a sua dificuldade é calcular os pontos dos nós (a posição deles em relação ao pai) ou o desenho propriamente dito?

Se seu problema é o desenho, leia este tópico: http://www.guj.com.br/java/118828-exemplo-de-java2d—simulador-de-automatos. Tem umas noções de desenho legais que você pode aplicar ao seu problema. Tem também o fonte da aplicação, pra você baixar e estudar.

Se seu problema é o posicionamento, e seus nós não guardam a posição em que estão (ou seja, todas as vezes que a tela é atualizada - um novo nó é adicionado, por exemplo, você então está recalculando a posição de cada um deles a todo momento, certo? Neste link tem um exemplo que deve te ajudar: http://www.uta.fi/~jl/pguibook/other.html (veja a parte Binary tree for Java).

Uma observação: eu não vejo necessidade de os nós serem JPanel. Você pode criar, dentro deles, um Ellipse2D (Se estiver usando Java2D), e, no JPanel Pai, chamar um método draw para este Ellipse2D. É claro, depende da sua necessidade.

Abraço.

S

TerraSkilll:
Não sei se é uma boa ideia ficar misturando Swing com AWT (mais que o necessário, porque em alguns casos é inevitável). Se entendi seu problema, você quer desenhar os nós de uma árvore em um JPanel (que é Swing), certo? Mas a sua dificuldade é calcular os pontos dos nós (a posição deles em relação ao pai) ou o desenho propriamente dito?

Se seu problema é o desenho, leia este tópico: http://www.guj.com.br/java/118828-exemplo-de-java2d—simulador-de-automatos. Tem umas noções de desenho legais que você pode aplicar ao seu problema. Tem também o fonte da aplicação, pra você baixar e estudar.

Se seu problema é o posicionamento, e seus nós não guardam a posição em que estão (ou seja, todas as vezes que a tela é atualizada - um novo nó é adicionado, por exemplo, você então está recalculando a posição de cada um deles a todo momento, certo? Neste link tem um exemplo que deve te ajudar: http://www.uta.fi/~jl/pguibook/other.html (veja a parte Binary tree for Java).

Uma observação: eu não vejo necessidade de os nós serem JPanel. Você pode criar, dentro deles, um Ellipse2D (Se estiver usando Java2D), e, no JPanel Pai, chamar um método draw para este Ellipse2D. É claro, depende da sua necessidade.

Abraço.

Muito obrigado pela resposta. Mas, na verdade minha dúvida é como eu apresento o Nó dentro da Árvore. Como eu disse, sou novato em programação gráfica Java, então ainda estou meio confuso sobre o que é AWT e o que é Swing. Darei uma olhada no material que você indicou e também peguei alguns materiais sobre Swing.

Criado 1 de outubro de 2012
Ultima resposta 2 de out. de 2012
Respostas 2
Participantes 2