Arquivos de Tag: Java

Varargs Java – Número de parâmetros variáveis no método

Disponível deste a versão 5 do Java, varargs permite fazer com que um método de uma classe receba parâmetros variáveis. Por exemplo, seu método pode receber 1 inteiro ou vários inteiros. Nas versões anteriores ao Java 5, você teria que criar um método que recebesse um array de inteiros ou então criar dois métodos:

class Varargs1 {
    public void metodoTeste(int a) { 
         //a implementação tratará um único int  
    }
 public void metodoTeste(int[] a) {  
        //a implementação tratará o array  
    }  
}

 

Com varargs a solução passou a ser mais elegante. Repare no exemplo abaixo que você utilizará o tipo acompanhado de reticiências (…) e depois o nome da variável, como mostra o exemplo:

public class Estatistica {
    public float media(int... numeros){
        float soma = 0;
        for(int num: numeros)
            soma += num;
        return soma/numeros.length;
    }
    public static void main(String[] args) {
        Estatistica est = new Estatistica();
        System.out.println( est.media(1,2,3) );
        System.out.println( est.media(0,1,2,3,4,5,6,7,8,9,10) );
        System.out.println( est.media(10,20,30) );
    }
}

ATENÇÃO: quando se combina o varargs com outros parâmetros num método, é imprescindível que a variável que use as reticiências fique como último parâmetro.

Exemplo retirado de: 
http://silveiraneto.net/2008/02/05/java-metodos-com-numero-variavel-de-parametros/

Anúncios

Criando um JDialog a partir de um simples JOptionPane

public class CreateDialogFromOptionPane {
   public static void main(final String[] args) {
      JFrame parent = new JFrame();
      JOptionPane optionPane = new JOptionPane(“Deseja continuar?”,
              JOptionPane.QUESTION_MESSAGE,  JOptionPane.YES_NO_OPTION);

      JDialog dialog = optionPane.createDialog(parent, “Título do JDialog”);
      dialog.setVisible(true);
   }
}

Retirado de: http://www.java2s.com/Tutorial/Java/CatalogJava.htm

Java: Encontrar a próxima data pelo dia da semana

Partindo de uma data específica deseja-se saber qual é a próxima Quarta-feira por exemplo.
Podemos então criar um método que utilizará a classe Calendar do Java. Este método receberá dois parâmetros: o primeiro é a data a partir da qual se deseja obter a próxima em um determinado dia da semana; o segundo parâmetro é o dia da semana. Este método retorna a nova data encontrada.

public Date nextWeekDay (Date dtReference, int dayOfWeek){  
  
         Calendar calendar = Calendar.getInstance();
         calendar.setTime(dtReference);  
  
         while ( calendar.get(Calendar.DAY_OF_WEEK) != dayOfWeek){  
                // incrementa em 1 dia
                calendar.add(Calendar.DAY_OF_MONTH,1);
         }  
  
         // ao sair do while, a data no calendar será a que queremos  
         return calendar.getTime();
}

Como desenhar um Gif animado usando Java

Pesquisando na web rapidamente encontrei o seguinte post: http://inthegarage.wordpress.com/2007/02/21/java-and-animated-gif/.
A solução apresentada é o uso do parâmetro ImageObserver na chamada do método graphics.drawImage. Parâmetro esse que geralmente passamos null. O fato é que quando uma imagem precisa ser atualizada (mudar o quadro do gif animado), o método imageUpdate é chamado, de modo a renovar a imagem, o gancho esta em ImageObserver imageUpdate. Veja o código abaixo:

public void paint(Graphics g) {
   g.drawImage(img,0,0,this);
}

public boolean imageUpdate( Image img, int flags, int x, int y, int w, int h ) {
   repaint();
   return true;
}

JTree dentro de um JComboBox

Esta é uma tradução de uma postagem no Santosh Kumar’s Weblog. Estava precisando de algo assim e após uma pesquisa encontrei esta solução. Resolvi então postar aqui os passos. O original está aqui.

JComboBox requer ComboBoxModel, mas temos TreeModel, porque não tentar criar um adaptador chamado TreeListModel que nós permita ver TreeModel como se fosse um ListModel?

class TreeListModel extends AbstractListModel implements ComboBoxModel{
    private TreeModel treeModel;
    private Object selectedObject; 

    public TreeListModel(TreeModel treeModel){
        this.treeModel = treeModel;
    } 

    public int getSize(){
        ????
    } 

    public Object getElementAt(int index){
        ????
    } 

    public void setSelectedItem(Object anObject){
        if((selectedObject!=null && !selectedObject.equals(anObject)) ||
                selectedObject==null && anObject!=null){
            selectedObject = anObject;
            fireContentsChanged(this, -1, -1);
        }
    } 

    public Object getSelectedItem() {
        return selectedObject;
    }
} 

Precisamos implementar getSize() e getElementAt(index),mas como?

– tamanho da lista (size) = total de nós da árvore

– elemento i na lista = linha i na árvore quanto completamento expandida

A resposta está em DefaultMutableTreeNode.PreorderEnumeration que na sua implementação assume que os nós são objetos TreeNode. Como queremos que a solução seja para qualquer TreeModel substituiremos o método enumeration() da interface TreeModel desta forma:

class ChildrenEnumeration implements Enumeration{
    TreeModel treeModel;
    Object node;
    int index = -1; 

    public ChildrenEnumeration(TreeModel treeModel, Object node){
        this.treeModel = treeModel;
        this.node = node;
    } 

    public boolean hasMoreElements(){
        return index<treeModel.getChildCount(node)-1;
    } 

    public Object nextElement(){
        return treeModel.getChild(node, ++index);
    }
} 

Agora copiamos DefaultMutableTreeNode.PreorderEnumeration e removemos os vestígios da interface TreeNode:

class PreorderEnumeration implements Enumeration{
    private TreeModel treeModel;
    protected Stack stack; 

    public PreorderEnumeration(TreeModel treeModel){
        this.treeModel = treeModel;
        Vector v = new Vector(1);
        v.addElement(treeModel.getRoot());
        stack = new Stack();
        stack.push(v.elements());
    } 

    public boolean hasMoreElements(){
        return (!stack.empty() &&
                ((Enumeration)stack.peek()).hasMoreElements());
    } 

    public Object nextElement(){
        Enumeration enumer = (Enumeration)stack.peek();
        Object node = enumer.nextElement();
        if(!enumer.hasMoreElements())
            stack.pop();
        Enumeration children = new ChildrenEnumeration(treeModel, node);
        if(children.hasMoreElements())
            stack.push(children);
        return node;
    }
} 

Agora completaremos os métodos deixados para trás em TreeListModel:

public int getSize(){
        int count = 0;
        Enumeration enumer = new PreorderEnumeration(treeModel);
        while(enumer.hasMoreElements()){
            enumer.nextElement();
            count++;
        }
        return count;
    } 

    public Object getElementAt(int index){
        Enumeration enumer = new PreorderEnumeration(treeModel);
        for(int i=0; i<index; i++)
            enumer.nextElement();
        return enumer.nextElement();
    } 

Nosso TreeListModel está completo. Vamos agora para parte do Renderer.

JComboBox requer ListCellRenderer mas temos TreeCellRenderer. Escreveremos então um adaptador para isso também.

public class TreeListCellRenderer extends JPanel implements ListCellRenderer{
    private static final JTree tree = new JTree();
    TreeModel treeModel;
    TreeCellRenderer treeRenderer; 

    public TreeListCellRenderer(TreeModel treeModel, TreeCellRenderer treeRenderer){
        this.treeModel = treeModel;
        this.treeRenderer = treeRenderer;
        setOpaque(false);
    } 

    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus){
        if(value==null){ //if selected value is null
            return this;
        } 

        boolean leaf = treeModel.isLeaf(value);
        Component comp = treeRenderer.getTreeCellRendererComponent(tree, value, isSelected, true, leaf, index, cellHasFocus); 

        return comp;
    }
}

No entanto, há um problema com a implementação acima: o renderer não esta sendo recuado de acordo com a profundidade do nó da árvore.

Como é que vamos recuar um renderer? A resposta é EmptyBorder cuja inserção esquerda é igual ao número de pixels reqd para recuo.

class IndentBorder extends EmptyBorder{
    int indent = UIManager.getInt("Tree.leftChildIndent"); 

    public IndentBorder(){
        super(0, 0, 0, 0);
    } 

    public void setDepth(int depth){
        left = indent*depth;
    }
} 

E TreeListCellRenderer é modificado para usar IndentBorder:

class TreeListCellRenderer extends JPanel implements ListCellRenderer{
    private static final JTree tree = new JTree();
    TreeModel treeModel;
    TreeCellRenderer treeRenderer;
    IndentBorder indentBorder = new IndentBorder(); 

    public TreeListCellRenderer(TreeModel treeModel, TreeCellRenderer treeRenderer){
        this.treeModel = treeModel;
        this.treeRenderer = treeRenderer;
        setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
        setBorder(indentBorder);
        setOpaque(false);
    } 

    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus){
        if(value==null){ //if selected value is null
            removeAll();
            return this;
        } 

        boolean leaf = treeModel.isLeaf(value);
        Component comp = treeRenderer.getTreeCellRendererComponent(tree, value, isSelected, true, leaf, index, cellHasFocus);
        removeAll();
        add(comp); 

        int depth = //somehow calculate depath
        indentBorder.setDepth(depth); 

        return this;
    }
}

Quase tudo está concluído, exceto o cálculo da profundidade de um nó.

Adicionamos uma variável membro chamada de ‘depth’ para a classe ChildrenEnumeration. Esta classe não faz qualquer outra coisa além de assegurar o valor da profundidade:

class ChildrenEnumeration implements Enumeration{
    .....
    int depth;
    .....
} 

A classe PreorderEnumeration é, então, modificada para calcular a profundidade e devolver a profundidade do elemento:

class PreorderEnumeration implements Enumeration{
    .....
    private int depth = 0; 

    ......

    public Object nextElement(){
        Enumeration enumer = (Enumeration)stack.peek();
        Object node = enumer.nextElement();
        depth = enumer instanceof ChildrenEnumeration
                ? ((ChildrenEnumeration)enumer).depth
                : 0;
        if(!enumer.hasMoreElements())
            stack.pop();
        ChildrenEnumeration children = new ChildrenEnumeration(treeModel, node);
        children.depth = depth+1;
        if(children.hasMoreElements()){
            stack.push(children);
        }
        return node;
    } 

    public int getDepth(){
        return depth;
    }
} 

Agora TreeListRenderer usa PreorderEnumeration para encontrar a profundidade do renderer:

        // compute the depth of value
        PreorderEnumeration enumer = new PreorderEnumeration(treeModel);
        for(int i = 0; i<=index; i++)
            enumer.nextElement();
        indentBorder.setDepth(enumer.getDepth()); 

Para utilizar nossa implementação:

 JComboBox comboBox = new JComboBox(new TreeListModel(treeModel));
 comboBox.setRenderer(new TreeListCellRenderer(treeModel, treeCellRenderer));