Estou com um problema, estou querendo uma implementar uma JTree para selecionar uma pasta de destino para transferir alguns arquivos, mas apenas estou conseguindo fazer isso especificando a unidade do sistema que quero utilizar, estou criando um modelo próprio, mas como seria esse modelo para apresentar todas unidades do sistema, e outra coisa eu apenas estou conseguindo fazer com que apareça o nome completo do endereço da pasta no JTree, exemplo: C:\pasta1\pasta2, gostaria que a mesma só apresentasse o nome da pasta na árvore, exemplo pasta2, vlw estou no aguardo qualquer duvida só chamar!
JTree com todas as unidades do sistema [Resolvido]
20 Respostas
Clique aqui, Talvez te ajude ^^
JoatanGuj obrigado pela resposta mas eu acho que você esqueceu de linkar ali.
JoatanGuj, o primeiro exemplo que você me mandou eu compilei e só apareceu a root na janela, já o segundo é algo assim que quero só que o meu problema seria fazer isso com as unidades do sistema fazer com que elas apareçam, no meu caso as 3, com seus devidos subdiretorios, obrigado de qualquer forma, vou vou tentar dar uma mechida no segundo exemplo para ver se consigo meu objetivo.
Ai vai o modelo que eu implementei para ver se ajuda, fico no aguardo! vlw!
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.event.EventListenerList;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
public class TreeModel implements javax.swing.tree.TreeModel {
private File root;
@SuppressWarnings("serial")
private static final Object LEAF = new Serializable() { };
@SuppressWarnings("rawtypes")
private Map map;
protected EventListenerList listeners;
@SuppressWarnings("rawtypes")
public TreeModel(File root) {
map = new HashMap();
listeners = new EventListenerList();
this.root = root;
}
@Override
public Object getRoot() {
return root;
}
@Override
public Object getChild(Object parent, int index) {
return children(parent).get(index);
}
@Override
public int getChildCount(Object parent) {
@SuppressWarnings("rawtypes")
List children = children(parent);
if (children == null)
return 0;
return children.size();
}
@Override
public boolean isLeaf(Object node) {
return map.get(node) == LEAF;
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
}
@Override
public int getIndexOfChild(Object parent, Object child) {
return children(parent).indexOf(child);
}
@Override
public void addTreeModelListener(TreeModelListener l) {
listeners.add(TreeModelListener.class, l);
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
listeners.remove(TreeModelListener.class, l);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private List children(Object node){
File file = null;
if (node instanceof File)
file = (File) node;
Object value = map.get(file);
if (value == LEAF)
return null;
List children = (List) value;
if (children == null) {
File[] files = file.listFiles();
if (files != null) {
int length = 0;
for (File f : files) {
if (f.isDirectory())
length++;
}
children = new ArrayList(length);
for (File f : files) {
if (f.isDirectory())
children.add(f);
if (f.listFiles() == null) // atualizacao sugerida pelo InSeOfKn
map.put(f, LEAF);//
}
} else
children = new ArrayList(0);
map.put(file, children);
}
return children;
}
}
Mais ninguem?
Tenta nessa implementação, alterar para somente os diretórios serem incluídos, e os diretórios sem subdiretórios serem elementos apenas, e não um nó!
Vou tentar modificar aqui e se conseguir algo retorno!
Sugestão aceita e atualizada no código acima, mas o problema é adicionar as unidades do sistema, e o nome das pastas ao ficarem com o endereço completo, mesmo assim vlw continuo no aguardo.
obs: suponho que o nome deve ser retornado pelo toString() da Classe File, não sei se isso ajuda, mesmo assim não encontrei uma solução.
Ok! mas oque ocorreu???
ahh, busque editar mensagens somente quando a erro no que foi escrito, assim facilita a vida dos próximos que postarem! e as mensagens apos a sua continuam com nexo! (minha opinião)
Até!
apenas sumiu o nó na tree e considerou como arquivo
vlw! ate+
ops! a mensagem saiu apos a sua!!
mas em relação ao nome acho que uma alteração nessa parte
@Override
public Object getChild(Object parent, int index) {
return children(parent).get(index);
}
para algo que retorne o nome que você queira resolve o problema do nome (para não perder o retorno de um File crie outro método semelhante que retorne o File)
mas em relação ao discos não sei exatamente onde mexer!
Até!
fiz isso até funcionou mas quando clica nos nós acontece isso:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at kmm.view.TreeModel.children(TreeModel.java:85)
at kmm.view.TreeModel.getChildCount(TreeModel.java:44)
at javax.swing.tree.VariableHeightLayoutCache$TreeStateNode.expand(VariableHeightLayoutCache.java:1478)
at javax.swing.tree.VariableHeightLayoutCache$TreeStateNode.expand(VariableHeightLayoutCache.java:1287)
at javax.swing.tree.VariableHeightLayoutCache.ensurePathIsExpanded(VariableHeightLayoutCache.java:983)
at javax.swing.tree.VariableHeightLayoutCache.setExpandedState(VariableHeightLayoutCache.java:181)
at javax.swing.plaf.basic.BasicTreeUI.updateExpandedDescendants(BasicTreeUI.java:1695)
at javax.swing.plaf.basic.BasicTreeUI$Handler.treeExpanded(BasicTreeUI.java:3783)
at javax.swing.JTree.fireTreeExpanded(JTree.java:2754)
at javax.swing.JTree.setExpandedState(JTree.java:3614)
at javax.swing.JTree.expandPath(JTree.java:2202)
at javax.swing.plaf.basic.BasicTreeUI.toggleExpandState(BasicTreeUI.java:2264)
at javax.swing.plaf.basic.BasicTreeUI.handleExpandControlClick(BasicTreeUI.java:2251)
at javax.swing.plaf.basic.BasicTreeUI.checkForClickInExpandControl(BasicTreeUI.java:2209)
at javax.swing.plaf.basic.BasicTreeUI$Handler.handleSelection(BasicTreeUI.java:3578)
at javax.swing.plaf.basic.BasicTreeUI$Handler.mousePressed(BasicTreeUI.java:3526)
at java.awt.Component.processMouseEvent(Component.java:6501)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6269)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4860)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4489)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2713)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:680)
at java.awt.EventQueue$4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:121)
at java.awt.WaitDispatchSupport$2.run(WaitDispatchSupport.java:182)
at java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:221)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.WaitDispatchSupport.enter(WaitDispatchSupport.java:219)
at java.awt.Dialog.show(Dialog.java:1072)
at java.awt.Component.show(Component.java:1650)
at java.awt.Component.setVisible(Component.java:1602)
at java.awt.Window.setVisible(Window.java:1013)
at java.awt.Dialog.setVisible(Dialog.java:1003)
at kmm.view.DirectoryTree.open(PopUpWindow.java:168)
at kmm.view.PopUpWindow.getRepository(PopUpWindow.java:77)
at kmm.view.MainWindow$4.actionPerformed(MainWindow.java:259)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
at java.awt.Component.processMouseEvent(Component.java:6504)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6269)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4860)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2713)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:680)
at java.awt.EventQueue$4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
mas valeu a tentativa ate+
continuando os testes
Opa vlw, vou analizar ai respondo se conseguir alguma coisa Vlw desde já!!!
Bem voltei para postar aqui a minha solução, que acabou se tornando uma alternativa melhor para o meu caso, ai vai minha solução : DirectoryTreeDialog
Classe onde eu coloquei os botoes ok cancelar a Jtree e a combo seletora de disco
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileFilter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.EventListenerList;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreePath;
@SuppressWarnings("serial")
public class DirectoryTreeDialog extends JDialog {
private File path;
private JComboBox<File> cb;
private JButton ok, cancel;
private JTree tree;
public DirectoryTreeDialog(String title) {
super((Frame) null, title);
initialize();
}
private void initialize() {
this.setLayout(new BorderLayout());
this.setModal(true);
this.setSize(250, 360);
this.add(combo(), BorderLayout.PAGE_START);
this.add(tree());
this.add(buttons(), BorderLayout.PAGE_END);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setAlwaysOnTop(true);
}
private JScrollPane tree() {
TreeModel model = new TreeModel(cb.getItemAt(0));
tree = new JTree(model);
tree.setCellRenderer(new FolderCellRender());
tree.setBorder(BorderFactory.createRaisedBevelBorder());
tree.setRootVisible(false);
JScrollPane pane = new JScrollPane(tree);
pane.setPreferredSize(new Dimension(280, 300));
pane.setBorder(BorderFactory.createBevelBorder(1));
return pane;
}
private JPanel buttons() {
JPanel panel = new JPanel();
ok = new JButton("Ok");
cancel = new JButton("Cancelar");
panel.add(ok);
panel.add(cancel);
setAction();
return panel;
}
private JPanel combo() {
JPanel p = new JPanel();
cb = new JComboBox<>();
cb.setPreferredSize(new Dimension(60, 20));
for (File f : File.listRoots()) {
cb.addItem(f);
}
cb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tree.setModel(new TreeModel(((File) cb.getSelectedItem())));
}
});
p.add(new JLabel("Selecionar Unidade:"));
p.add(cb, BorderLayout.LINE_END);
return p;
}
private void setAction() {
ok.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String aux = tree.getSelectionModel().getSelectionPath()
.toString();
String[] array = aux.split(", ");
aux = array[array.length - 1].replaceAll("]", "");
path = new File(aux);
dispose();
}
});
cancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
}
public File open() {
this.setVisible(true);
return path;
}
}
Aqui o meu modelo que só adiciona diretórios a minha Jtree e que considera como "folhas" os diretórios que não possuem subdiretórios, evitando o mais do lado da pasta
class TreeModel implements javax.swing.tree.TreeModel {
private File root;
@SuppressWarnings("serial")
private static final Object LEAF = new Serializable() {
};
@SuppressWarnings("rawtypes")
private Map map;
protected EventListenerList listeners;
@SuppressWarnings("rawtypes")
public TreeModel(File root) {
map = new HashMap();
listeners = new EventListenerList();
this.root = root;
}
@Override
public Object getRoot() {
return root;
}
@Override
public Object getChild(Object parent, int index) {
return children(parent).get(index);
}
@Override
public int getChildCount(Object parent) {
@SuppressWarnings("rawtypes")
List children = children(parent);
if (children == null)
return 0;
return children.size();
}
@Override
public boolean isLeaf(Object node) {
boolean is = true;
if (((File) node).listFiles() != null) {
block: for (File f : ((File) node).listFiles()) {
if (f.isDirectory())
is = false;
break block;
}
}
return is;
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
}
@Override
public int getIndexOfChild(Object parent, Object child) {
return children(parent).indexOf(child);
}
@Override
public void addTreeModelListener(TreeModelListener l) {
listeners.add(TreeModelListener.class, l);
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
listeners.remove(TreeModelListener.class, l);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private List children(Object node) {
File file = null;
if (node instanceof File)
file = (File) node;
Object value = map.get(file);
if (value == LEAF)
return null;
List children = (List) value;
if (children == null) {
File[] files = file.listFiles();
if (files != null) {
int length = 0;
for (File f : files) {
if (f.isDirectory())
length++;
}
children = new ArrayList(length);
for (File f : files) {
if (f.isDirectory()) {
children.add(f);
if (f.listFiles() == null)
map.put(f, LEAF);
}
}
} else
children = new ArrayList(0);
map.put(file, children);
}
return children;
}
}
aqui onde eu defini o icone do Leaf igual ao do close para ficar com aparência de pasta que é o que realmente representa e não uma folha, e sobreescrevi o método SetText() para não ficar o endereço completo do arquivo na Jtree.
@SuppressWarnings("serial")
class FolderCellRender extends DefaultTreeCellRenderer {
public FolderCellRender() {
super();
this.setLeafIcon(this.getClosedIcon());
}
@Override
public void setText(String text) {
String[] str = text.split("\\\\");
super.setText(str[str.length - 1]);
}
}
Bom isso não é exatamente o que o nome do tópico sugere mas é o que melhor se adequou a minha necessidade, e como mais alguém pode ter uma necessidade similar resolvi postar aqui.
Obrigado pela ajuda vlw até mais
Acabei implementando um modelo que já faça tudo e bem genérico para possíveis adaptações!
de uma olhada no tópico que abri para disponibilizar o modelo!
Gostei da sua solução! ta merecendo ir para uma biblioteca Swing!
Problema Resolvido! edit sua primeira mensagem e acrescente no titulo um [RESOLVIDO]. Facilita a vida de quem esta procurando solução e economiza o tempo de que esta colaborando!
Até!
Não seria uma boa retirar os supresswarnings(“rawtypes”) e usar os generics para especificar os tipos dos mapas e listas? Ia evitar muitos casts e deixar o código mais limpo e seguro.
Hum é uma boa ViniGody, Farei isso vlw por mais essa dica até a próxima. problema resolvido 
Abraço a todos
Segui ai o jar do JDiretoryTreeDialog para o Classpath
obs: Resolvi um bug que descobri na minha jtree e postei um novo jar abaixo
Opa voltei aqui para reportar um bug que ja resolvi e postar novamente o jar para Classepath, o bug era uma simples falha no if do metodo isleaf() do meu modelo da Jtree, resolvido, entao vamos ao jar