Exibir apenas Diretórios em uma JTree

Pessoal,
Estou com um pequeno grande problema.

Aí vai…

Já tenho uma JTree que mostra os arquivos de meu HD, onde mostra todos os seus filhos(diretórios e arquivos).

Quando expando um diretório da minha JTree, todos seus filhos são mostrados.

Preciso que só os diretórios sejam exibidos.

Estou trabalhando com JSplitPane, onde na esquerda tenho minha JTree e na direito tenho minha JTable.

Quando clico em um diretório da minha JTree, apenas os arquivos são mostrados na JTable. (isto está funcionando)

O que preciso é que quando eu expando minha JTree, apenas sejam exibidos os filhos que sejam diretórios na minha JTree.

Deu pra entender?

Estou utilizando o Java 6.

OBS: No código que estarei postando utilizo também outra JTable(abaixo) para colocar os arquivos que irei selecionar na Minha JTable de cima. (ainda não está pronto).

OBS2: Outras dúvidas (se alguém puder ajudar eu agradeço muito)
Antes… só para ajudar no entendimento: Todos os meus componentes são adicionados em um JPanel (panelGeral)

1 - Não estou conseguindo Colocar o meu splitPane do mesmo tamanho do panelGeral (eu já consegui colocar o panelGeral do mesmo tamanho do frame, que este é obtido pegando a resolução que o usuário está utilizando na máquina, através do comando Toolkit.getDefaultToolkit().getScreenSize());

2 - Não estou conseguindo deixar a minha JTable (do split) não editével. Por causa disso não consigo acionar o meu evento de mouseClicked (que está configurado para doubleClick). O que aconteçe é que quando damos um duplo clique em uma célula da JTable, a mesma fica editável para modificação do conteúdo;

3 - Queria também proibir o redimensionamento da divisória do meu split;

4 - No momento o tamanho da largura do meu JTree(split) fica do tamanho da maior String da árvore. Queria a divisória não redimensionável.

Pessoal, sei que é muita dúvida, mas se alguém souber de alguma, já vai ser ótimo.

Abaixo o código:

FileTreePanel.java

package teste;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileFilter;

import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

public class FileTreePanel {

	private JTree fileTree;

	private FileSystemModel fileSystemModel;

	private JTable jtable;

	private JScrollPane tableScroll;

	private DefaultTableModel tableModel;

	private File file;

	private File[] arquivos;

	private String[] colunas;

	private int[] columnWidth = {300,150,300, 450};

	private FileTablePanel fileListPanel;

	public JSplitPane getExplorer(String directory) {

		fileSystemModel = new FileSystemModel(new File(directory));
		fileTree = new JTree(fileSystemModel);
		fileTree.setEditable(false);

		colunas = new String []{"Nome","Tamanho", "Tipo", ""};

		tableModel = new DefaultTableModel(null, colunas);

		jtable = new JTable(tableModel);

		configurarJTable(jtable);

		fileTree.addTreeSelectionListener(new TreeSelectionListener() {
			public void valueChanged(TreeSelectionEvent event) {

				file = (File) fileTree.getLastSelectedPathComponent();

				tableModel.setRowCount(0); //Apaga os dados da tabela menos a coluna
				jtable.setModel(tableModel);

				//se for diretório, adiciona os arquivos no painel da direita
				if(file.isDirectory())
					adicionaLinhaTabela(file);

				//fileTree.setShowsRootHandles(true);

				jtable.addMouseListener(new MouseListener() {

					public void mouseClicked(MouseEvent e) {
						if(e.getClickCount() == 2 && e.getButton() == e.BUTTON1)
							fileListPanel.adicionaLinhaTabela(jtable, jtable.getSelectedRow(), arquivos);
					}

					public void mouseEntered(MouseEvent e) {
						// TODO Auto-generated method stub

					}

					public void mouseExited(MouseEvent e) {
						// TODO Auto-generated method stub

					}

					public void mousePressed(MouseEvent e) {
						// TODO Auto-generated method stub

					}

					public void mouseReleased(MouseEvent e) {
						// TODO Auto-generated method stub

					}

				});
			}
		});
		
		JScrollPane treeScroll = new JScrollPane(fileTree);
				
		/**
		 * @param 	Monta o Explorer:
		 * 			Esquerda: Árvore de Diretórios
		 * 			Direita: Exibição dos Arquivos do Diretório Selecionado
		 */
		JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
											  true,
											  treeScroll,
											  tableScroll);
		
		splitPane.setOneTouchExpandable(true);

		return splitPane;
	}

	public void configurarJTable(JTable table) {

		tableScroll = new JScrollPane(table);

		alinhaTabela(table);
		tamanhoTabela(table);
		//ordenaColuna(table);
	}

	public JTable getTabela() {
		return jtable;
	}

	public String retornaKbytes(File dados) {
		long size = (dados.length() / 1024) + 1;
		return size + "KB";
	}

	public void adicionaLinhaTabela(File diretorio) {

		//pega a quantidade de arquivos do diretório
		arquivos = new File[
		                        diretorio.listFiles(new FileFilter() {

								public boolean accept(File file) {
									if(file.isFile())
										return true;
									return false;
								}

		                        }).length
		                        ];

		//adiciona no array dados, os arquivos do diretorio
		arquivos = diretorio.listFiles(new FileFilter() {

			public boolean accept(File file) {
				if(file.isFile())
					return true;
				return false;
			}

		});

		//adiciona o conteúdo do array dados, na jtable
		for(int i = 0 ; i &lt arquivos.length ; i++)
			tableModel.addRow(new String [] {arquivos[i].getName(), retornaKbytes(arquivos[i]), "teste", ""});
	}

	public void alinhaTabela(JTable table) {
		DefaultTableCellRenderer esquerda = new DefaultTableCellRenderer();
		DefaultTableCellRenderer centralizado = new DefaultTableCellRenderer();
		DefaultTableCellRenderer direita = new DefaultTableCellRenderer();

		esquerda.setHorizontalAlignment(SwingConstants.LEFT);
		centralizado.setHorizontalAlignment(SwingConstants.CENTER);
		direita.setHorizontalAlignment(SwingConstants.RIGHT);

		table.getColumnModel().getColumn(1).setCellRenderer(direita);
		table.getColumnModel().getColumn(2).setCellRenderer(centralizado);
	}

	public void tamanhoTabela(JTable table) {
		//table.getColumnModel().getColumn(0).setPreferredWidth((int)Math.round(width * 0.35));
		table.getColumnModel().getColumn(0).setPreferredWidth(columnWidth[0]);
		table.getColumnModel().getColumn(1).setPreferredWidth(columnWidth[1]);
		table.getColumnModel().getColumn(2).setPreferredWidth(columnWidth[2]);
		table.getColumnModel().getColumn(3).setPreferredWidth(columnWidth[3]);
	}
}

FileSystemModel.java

package teste;

//FileSystemModel.java
//TreeModel implementation using File objects as tree nodes.
import java.io.File;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

public class FileSystemModel implements TreeModel {

// hierarchy root
private File root;

// TreeModelListeners
private Vector listeners = new Vector();

// FileSystemModel constructor
public FileSystemModel( File rootDirectory ) 
{
  root = rootDirectory;
}   

// get hierarchy root (root directory)
public Object getRoot() 
{
   return root;
}

// get parent's child at given index
public Object getChild( Object parent, int index ) 
{      
   // get parent File object
   File directory = ( File ) parent;
   
   // get list of files in parent directory
   String[] children = directory.list();
   
   // return File at given index and override toString
   // method to return only the File's name
   return new TreeFile( directory, children[ index ] );
}

// get parent's number of children
public int getChildCount( Object parent ) 
{
   // get parent File object
   File file = ( File ) parent;
   
   // get number of files in directory
   if ( file.isDirectory() ) {
      
      String[] fileList = file.list();
      
      if ( fileList != null )
         return file.list().length;
   }
   
   return 0; // childCount is 0 for files
}

// return true if node is a file, false if it is a directory
public boolean isLeaf( Object node ) 
{
   File file = ( File ) node;
   return file.isFile();
}

// get numeric index of given child node
public int getIndexOfChild( Object parent, Object child ) 
{
   // get parent File object
   File directory = ( File ) parent;
   
   // get child File object
   File file = ( File ) child;
   
   // get File list in directory
   String[] children = directory.list();
   
   // search File list for given child
   for ( int i = 0; i &lt children.length; i++ ) {
      
      if ( file.getName().equals( children[ i ] ) ) {
         
         // return matching File's index
         return i;
      }
   }
   
   return -1; // indicate child index not found

} // end method getIndexOfChild

// invoked by delegate if value of Object at given
// TreePath changes
public void valueForPathChanged( TreePath path,
   Object value ) 
{
   // get File object that was changed
   File oldFile = ( File ) path.getLastPathComponent();
   
   // get parent directory of changed File
   String fileParentPath = oldFile.getParent();
   
   // get value of newFileName entered by user
   String newFileName = ( String ) value;
   
   // create File object with newFileName for 
   // renaming oldFile
   File targetFile = new File( 
      fileParentPath, newFileName );
  
   // rename oldFile to targetFile
   oldFile.renameTo( targetFile );
   
   // get File object for parent directory
   File parent = new File( fileParentPath );
   
   // create int array for renamed File's index
   int[] changedChildrenIndices = 
      { getIndexOfChild( parent, targetFile) };
      
   // create Object array containing only renamed File
   Object[] changedChildren = { targetFile };
      
   // notify TreeModelListeners of node change
   fireTreeNodesChanged( path.getParentPath(), 
      changedChildrenIndices, changedChildren );      

} // end method valueForPathChanged

// notify TreeModelListeners that children of parent at
// given TreePath with given indices were changed
private void fireTreeNodesChanged( TreePath parentPath, 
   int[] indices, Object[] children )
{
   // create TreeModelEvent to indicate node change
   TreeModelEvent event = new TreeModelEvent( this,
      parentPath, indices, children );
      
   Iterator iterator = listeners.iterator();      
   TreeModelListener listener = null;         
   
   // send TreeModelEvent to each listener 
   while ( iterator.hasNext() ) {
      listener = ( TreeModelListener ) iterator.next();
      listener.treeNodesChanged( event );
   }      
} // end method fireTreeNodesChanged

// add given TreeModelListener 
public void addTreeModelListener( 
   TreeModelListener listener ) 
{
   listeners.add( listener );
}

// remove given TreeModelListener
public void removeTreeModelListener(
   TreeModelListener listener ) 
{
   listeners.remove( listener );
}
   
// TreeFile is a File subclass that overrides method
// toString to return only the File name. 
private class TreeFile extends File {

   // TreeFile constructor
   public TreeFile( File parent, String child )
   {
      super( parent, child );
   }

   // override method toString to return only the File name
   // and not the full path
   public String toString()
   {
      return getName();
   }
} // end inner class TreeFile
}

Main.java

package teste;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;

public class Teste extends JFrame {

	private JPanel panelGeral, panelLogo;
	private JLabel labelLogo;
	
	
	
	private JSplitPane splitExplorer;
	private JScrollPane scrollFileTable;
	
	private Dimension dimensionFrame;

	public Teste() {

		super("Teste");
		
		dimensionFrame = new Dimension();
		dimensionFrame.setSize(Toolkit.getDefaultToolkit().getScreenSize());
		
		this.setSize(dimensionFrame);

		//Montando o Explorer
		FileTreePanel fileTreePanel = new FileTreePanel();
		splitExplorer = new JSplitPane();
		splitExplorer = fileTreePanel.getExplorer("/"); //Raiz do Explorer

		//Painel dos Arquivos Selecionados
		FileTablePanel fileTablePanel = new FileTablePanel();
		scrollFileTable = new JScrollPane();
		scrollFileTable = fileTablePanel.retornaFileTablePanel();

		//Adicionando todos os Painéis em um só Geral
		panelGeral = new JPanel();
		panelGeral.setBackground(Color.cyan);
		panelGeral.add(splitExplorer);
		panelGeral.add(scrollFileTable);

		//Adicionando o Panel Geral no Frame
		this.getContentPane().add(panelGeral);

		panelGeral.setLayout(null);

		Insets insets = panelGeral.getInsets();
		
		Dimension size = splitExplorer.getPreferredSize();
								splitExplorer.setBounds(insets.left,
								insets.top,
								size.width,
								size.height);

		size = scrollFileTable.getPreferredSize();
		scrollFileTable.setBounds(insets.left,
								  splitExplorer.getHeight() + insets.top,
								  size.width,
								  size.height);

		this.setVisible(true);

		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent arg0) {
				System.exit(0);
			}
		});
	}
	public static void main(String[] args) {
		Teste teste = new Teste();
	}
}

Testei aqui e está tudo funcionando. Coloquei tudo na mesma package para facilitar.

Preciso muito destas soluções. Qualquer colaboração é bem vinda.

Obrigado,
Daniel Brasil

  1. BorderLayout é adequado para esse tipo de problema.

panelGeral.setLayout( new BorderLayout() ); panelGeral.getContentPane().add( splitExplorer, BorderLayout.CENTER );

  1. http://forum.java.sun.com/thread.jspa?threadID=614387&messageID=3406045

  2. 4.[?] http://forum.java.sun.com/thread.jspa?threadID=539243&messageID=2614071

Valeu pela dica LIPE.

Consegui algumas soluções bem simples:

[quote]
1 - Não estou conseguindo Colocar o meu splitPane do mesmo tamanho do panelGeral (eu já consegui colocar o panelGeral do mesmo tamanho do frame, que este é obtido pegando a resolução que o usuário está utilizando na máquina, através do comando Toolkit.getDefaultToolkit().getScreenSize()); [/quote]

Quanto ao posicionamento do meu divisor, fiz o seguinte:

onde width é a largura do meu split(que é da mesma largura do meu frame). Então peguei o width do frame e dividi por 4. Assim o divisor estará sempre ocupando 1/4 da largura. Simples né :slight_smile:

Em relação à edição da célula, o link que vc me deu me ajudou bastante. Ficou assim:

[code]jtable = new JTable(tableModel){

		 public boolean isCellEditable(int row, int column) {
		     return false;
		 }
	};[/code]

Setei o divisor do meu split para zero, assim ele fica não redimensionavel: