[Java] JTree file browser

Pagina: 1
Acties:

  • rene_404
  • Registratie: Maart 2001
  • Laatst online: 11-03-2007
Momenteel ben ik bezig met Java een file browser te maken, hiervoor maak ik gebruik van het JTree component. Ik ben al een heel eind gekomen, maar loop nu steeds vast.

Ipv. dat de bestanden op de hdd staan staan ze geindexeerd in een database:

Database layout:
code:
1
2
3
4
5
6
7
8
9
dirname:        filename:
        
D:/testmap  -   file1.pl
D:/testmap  -   file2.txt
D:/testmap  -   file3.txt 
D:/testmap/testscripts  -   file1.pl 
D:/testmap/testscripts  -   file2.txt 
D:/testmap/testscripts/map1 -   file4.txt 
D:/testmap/testscripts/map1/ab  -   file5.txt


Ik gebruik hiervoor de volgende code om de JTree op te bouwen:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
    // Build Tree
    Statement st = database1.createStatement();
    ResultSet rs = st.executeQuery("SELECT DISTINCT dirname FROM file;");

    while (rs.next()) {

      String path = rs.getString("dirname");
      File dir = new File(path);

           // Get COUNT
           Statement st1 = database1.createStatement();
           ResultSet rs1 = st1.executeQuery("SELECT COUNT (filename) FROM files WHERE dirname='" + path +  "';");
           rs1.next();
           int count = rs1.getInt(1) + 1;

           // Get Files for directory
           rs1 = st1.executeQuery("SELECT * FROM files WHERE dirname='" + path +  "';");
           rs1.next();

           String files[] = new String[count];

           for (int index = 1; index < count; index++) {
             files[index] = rs1.getString("dirname") + "/" + rs1.getString("filename");
             rs1.next();
           }

           rs1.close();
           st1.close();

           setDir(dbTree, dir, files);

    }
    rs.close();
    st.close();


  public void setFile(CheckTreeNode node, File f) {
         CheckTreeNode child = new CheckTreeNode(f.getName());
         node.add(child);
  }

  public void setDir(CheckTreeNode node, File dir, String file[]) {
         CheckTreeNode child = new CheckTreeNode(dir);
         node.add(child);

         for(int i = 1; i  < file.length; i++) {
             File f = new File(file[i]);
             setFile(child, f);
         }
  }


De JTree wordt nu netjes opgebouwd met de bestanden onder de map, dit gaat allemaal goed. Helaas gaat het niet goed als er submappen in een map aanwezig zijn. Dan blijven deze allemaal onder de root van de JTree hangen ipv. de goede map....

Iemand een idee wat ik over het hoofd zie?
Ik heb deze URL: http://www.rgagnon.com/javadetails/java-0324.html gebruikt als voorbeeld, hier gaat het wel goed.

huh, heb ik dat gedaan?


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 15:28

Robtimus

me Robtimus no like you

Je zou het pad moeten splitsen op de laatste \, en alles daarvoor is dan de parent.

Maar waarom doe je het met een database? java.io.File heeft daar mooie methods voor:
listRoots() (static), geeft een array met File's van de roots (dus C:\, D:\, onder UNIX /)
listFiles(FileFilter), geeft een array met files van alle "files" (dus ook dirs) die voldoen aan de accept van de gegeven filefilter. Dit is een implementatie van java.io.FileFilter, waarbij je alleen de accept hoeft te implementeren. De implementatie kan iets zijn als:
Java:
1
2
3
4
public boolean accept(File f)
{
    return f.isDirectory();
}
of
Java:
1
2
3
4
public boolean accept(File f)
{
    return f.isFile();
}
Je kan dan misschien ook je boom pas opbouwen als dat nodig is.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Ik zou persoonlijk gaan voor een treemodel en niet meteen die hele boom opbouwen (kan nogal groot worden)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class FileTreeModel implements TreeModel {
    private List<File> _fileList;

    public FileTreeModel(List<URL> fileList) {
        Assert.assertNotNull(fileList);

        _fileList = new LinkedList<File>();
        for (Iterator<URL> itt = fileList.iterator(); itt.hasNext();) {
            String fileName = itt.next().getFile();
            File file = new File(fileName);
            System.out.println("file: " + file + " exists: " + file.exists());
            _fileList.add(file);
        }
    }

    public Object getRoot() {
        return _fileList;
    }

    public int getChildCount(Object parent) {
        if (parent == _fileList) {
            return _fileList.size();
        } else {
            File file = (File) parent;
            if (file.isDirectory())
                return file.listFiles().length;
            else
                return 0;
        }
    }

    public boolean isLeaf(Object node) {
        return getChildCount(node) == 0;
    }

    public void addTreeModelListener(TreeModelListener l) {
        //TODO
    }

    public void removeTreeModelListener(TreeModelListener l) {
        //TODO
    }

    public Object getChild(Object parent, int index) {
        if (parent == _fileList) {
            return _fileList.get(index);
        } else {
            File file = (File) parent;

            if (file.isDirectory())
                return file.listFiles()[index];

            throw new IllegalArgumentException("file:" + file + " was no directory");
        }
    }

    public int getIndexOfChild(Object parent, Object child) {
        if (parent == _fileList) {
            return _fileList.indexOf(child);
        } else
            return -1;
    }

    public void valueForPathChanged(TreePath path, Object newValue) {
        //To change body of implemented methods use Options | File Templates.
    }
}

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 15:28

Robtimus

me Robtimus no like you

offtopic:
Alarmnummer zit al volledig in Java 1.5 ;)

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • rene_404
  • Registratie: Maart 2001
  • Laatst online: 11-03-2007
IceManX schreef op 21 mei 2004 @ 13:58:
Maar waarom doe je het met een database? java.io.File heeft daar mooie methods voor: ...
De bestanden staan niet lokaal, maar op een andere machine. De bedoeling is dat de gebruiker kan selecteren welke hij wil en deze dan wordt gekopieerd naar zijn eigen machine.

huh, heb ik dat gedaan?


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 15:28

Robtimus

me Robtimus no like you

Dan moet je van je paden de parent dir erafhalen, en achterhalen welke node erbij hoort.

Dus uit D:/testmap/testscripts/map1/ab moet je D:/testmap/testscripts/map1 filteren (niet moeilijk), en dan de bijbehorende node opzoeken (Map anyone?). Dit vereist dan wel dat je de dirs op volgorde uit de database haalt (ordering dus).

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

IceManX schreef op 21 mei 2004 @ 14:05:
offtopic:
Alarmnummer zit al volledig in Java 1.5 ;)
Dit is al weer een oud stuk code, check de forlus :) En verder is de 1.5 compiler mij nog iets te buggy doordat ik het regelmatig voor elkaar krijg dat die helemaal crashed. Voorlopig nog gewoon jdk1.4 + generics

  • kasper_vk
  • Registratie: Augustus 2002
  • Laatst online: 08-04-2025
offtopic:
[quote]Alarmnummer schreef op 21 mei 2004 @ 15:50:
[...]Voorlopig nog gewoon jdk1.4 + generics[/quote]
Generics in 1.4 ? Hoe doe je dat? :9~ Kan je dan de 1.5 compiler 'los' gebruiken ofzo? Nee, dus, ik moet ff leren lezen. Maar toch: hoe dan wel ? :?

[ Voor 14% gewijzigd door kasper_vk op 21-05-2004 18:32 ]

The most exciting phrase to hear in science, the one that heralds new discoveries, is not 'Eureka!' but 'That's funny...'


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

kasper_vk schreef op 21 mei 2004 @ 18:31:
offtopic:
[quote]Alarmnummer schreef op 21 mei 2004 @ 15:50:
[...]Voorlopig nog gewoon jdk1.4 + generics[/quote]
Generics in 1.4 ? Hoe doe je dat? :9~ Kan je dan de 1.5 compiler 'los' gebruiken ofzo? Nee, dus, ik moet ff leren lezen. Maar toch: hoe dan wel ? :?
http://www.thecortex.net/clover/generics.html heb je ook meteen ANT klaar voor generics.

  • rene_404
  • Registratie: Maart 2001
  • Laatst online: 11-03-2007
IceManX schreef op 21 mei 2004 @ 14:28:
Dan moet je van je paden de parent dir erafhalen, en achterhalen welke node erbij hoort.

Dus uit D:/testmap/testscripts/map1/ab moet je D:/testmap/testscripts/map1 filteren (niet moeilijk), en dan de bijbehorende node opzoeken (Map anyone?). Dit vereist dan wel dat je de dirs op volgorde uit de database haalt (ordering dus).
Sorry, Ik snap nog niet helemaal precies wat ik moet doen. Ik forceer dat de directory een File is (File dir = new File(path)) en daarom kan ik gemakkelijk het parent aanroepen met .getParent().

Tevens heb ik ook de paden opgedeeld in stukjes. (in een Vector):
code:
1
D:/testmap/testscripts/map1/ab --> D: - testmap - testscripts - map1 - ab

Ook heb ik bij de SQL statement gezegd dat hij ORDER BY ASC doet. Het stukje over het opzoeken van de bijhorende node snap ik nog niet helemaal.

huh, heb ik dat gedaan?


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 15:28

Robtimus

me Robtimus no like you

Je getParent() geeft je al de parent terug, dus dat is goed opgelost. Wel even checken op null he?

Je hebt een File. Daarmee creeer je een TreeNode. De parent node van die TreeNode moet zijn de TreeNode van de parent van de File. Om er zeker van te zijn dat die al bestaat moet je dus idd ASCENDING selecteren; zo wordt de parent altijd eerder uit de database gehaald, en bestaat de parent node dus als je die nodig hebt.

Nogmaals, je hebt een File. Mbv getParentFile() (levert een File ipv een String) krijg je de parent file. Hoe wil je daarmee nu de parent node vinden? Opnieuw creeeren is niet de juiste oplossing, dan krijg je dezelfde node meerdere keren in de tree.
Oplossing: gebruik een java.util.Map implementatie, die mapt van File naar TreeNode. Zodra je een nieuwe File creeert doe je dan het volgende:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// pseudocode
File file = new File(....);
TreeNode node = new TreeNode(...);
nodes.put(file, node);
File parent = file.getParentFile();
if (parent != null)
{
    // de map van File naar TreeNode
    TreeNode parentNode = nodes.get(parent);
    if (parentNode != null)
    {
        parentNode.add(node);
    }
}
Die Vector heb je dan ook niet meer nodig.

Het is zo wel van belang dat idd de parents ook voor de children worden gecreeerd, anders zal parentNode wel null kunnen worden; dan krijg je een dangling subtree.

[ Voor 9% gewijzigd door Robtimus op 22-05-2004 13:15 ]

More than meets the eye
There is no I in TEAM... but there is ME
system specs

Pagina: 1