Reactie plaatsen 
 
Waardering:
  • 0 stemmen - gemiddelde waardering is 0
  • 1
  • 2
  • 3
  • 4
  • 5
Dialoogvensters voor bestandskeuze
Auteur Bericht
Elco Offline
Ep2 Volunteer
****

Berichten: 1.237
Lid sinds: 04-2006
Reputatie: 29
Bericht: #1
Dialoogvensters voor bestandskeuze
Bestand dialoog vensters
Even een tutorial over een nog vaak gevraagd, weinig begrepen, maar eigenlijk zeer eenvoudig onderdeel van een programma: een dialoog venster om bestanden te selecteren :)

Met behulp van een mooi dialoogvenster kan je op een eenvoudige manier bestanden laten kiezen door je gebruikers. Swing voorziet hiervoor een mooi exemplaar. In deze tutorial zal je leren hoe je deze kan gebruiken, zodat ook jouw programma's die extra professionele toets krijgen :)

Algemeen
We vallen meteen met de deur in huis door eens te bekijken hoe zo'n dialoogvenster er uitziet. Dit is afhankelijk van je gebruikte Look and Feel, maar ze bieden wel allemaal dezelfde functionaliteiten. Hier zijn enkele voorbeelden van hoe ze eruit zien:
   
   
Om zulke mooie dialogen te verkrijgen, moet je zeer weinig doen. Er is een component in Swing, genaamd JFileChooser, die dit alles voor je verzorgt. Het aanmaken verloopt zeer eenvoudig:
Code:
JFileChooser fc = new JFileChooser();
Dat is het! Nu moet je enkel nog het commando geven om de dialoog te tonen. Hiervoor kun je 1 van de volgende 3 methoden gebruiken:
Code:
int showDialog(Component parent, String approveButtonText)
int  showOpenDialog(Component parent)
int  showSaveDialog(Component parent)
Zoals je ziet geef je hieraan als 'parent' een component mee. Dit is een component van waaruit je je dialoog wenst op te roepen. Meestal is dit een venster (JFrame). Je hoeft hiervoor geen waarde door te geven, je kan gewoon null gebruiken ook, maar het heeft als voordeel dat je venster onbruikbaar wordt tot de gebruiker iets gekozen heeft en/of een bevestigingsknop gedrukt heeft op je dialoogvenster. Het OpenDialog dient voor wanneer je gebruiker een document wenst te openen. In de titel van je dialoogvenster zal dan een verwijzing staan naar 'openen', net als op de knop voor het bevestigen. (Analoog voor SaveDialog) Wat die tekst precies is zal afhangen van de gebruikte L&F, dus indien je hiermee niet tevreden bent, kun je zelf de bevestigingstekst instellen met de eerste van de 3 methoden. Je hebt reeds gezien hoe het resultaat eruit ziet bij de eerste 2 figuren in deze tutorial.;)

Indien de gebruiker iets gekozen heeft of je dialoog geannuleerd heeft keert de methode terug en kun je kijken wat de teruggestuurde int is. Deze geeft aan wat de gebruiker deed, en er zijn 3 mogelijke waarden:
  • JFileChooser.CANCEL_OPTION
  • JFileChooser.APPROVE_OPTION
  • JFileCHooser.ERROR_OPTION

Op basis hiervan kun je dan controleren of een gebruiker iets heeft gekozen of gewoon geannuleerd heeft en zelfs of er een fout was opgetreden om een of andere reden:
Code:
int result = fc.showOpenDialog(null);
switch(result) {
   case(JFileChooser.CANCEL_OPTION)  ...
   case(JFileChooser.APPROVE_OPTION) ...
   case(JFileCHooser.ERROR_OPTION ) ...
};

Indien de gebruiker de APPROVE gekozen had, kun je met
Code:
fc.getSelectedFile();
opvragen wat het gekozen bestand/directory was.

We kunnen nu een mooie dialoog presenteren naar de gebruiker toe, maar vaak wil je nog een aantal zaken instellen. In wat volgt zullen we aantonen wat je nog meer kunt aan belangrijke functionaliteiten en hoe je dit doet.

Enkel directories selecteren
Dit kan zeer eenvoudig door volgende instelling te doen:
Code:
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

Instellen van de directory
Je kunt in de constructor van de filechooser opgeven wat z'n pad is waarin hij zich voor het eerst toont. Maar je kan het ook achteraf nog instellen indien je de lege constructor gebruikt hebt, of wanneer je hem ergens anders wenst te herbruiken. Dit doe je heel eenvoudig als volgt:
Code:
fc.setCurrentDirectory(file_dir);
Waarin file_dir een File-object is dat een directory voorstelt.

Filteren op types
Je kan ervoor kiezen om enkele bestandstypes te filteren, zodat bijvoorbeeld enkel het bestandstpe van jouw toepassing kan gekozen worden.
Je maakt hiervoor een eigen klasse aan, waarin je overerft van javax.swing.filechooser.FileFilter. Deze moet 2 methoden bevatten: accept en getDescription. Accept zal een bestand krijgen van je FileChooser en je filter zal dan met true of false (een boolean dus) terugsturen of het mag weergegeven worden als keuze of niet. GetDescription zal gebruikt worden om een tekstvoorstelling weer te geven zoals hier:
   
De code hiervoor ziet er als volgt uit:
Code:
class HTMLFilter extends FileFilter {
    public boolean accept(java.io.File file) {
        String filename = file.getName();
        return filename.endsWith(".html");
    }
    public String getDescription() {
        return "Webpagina's (*.html)";
    }
}
en je stelt deze filter in via:
Code:
fc.addChoosableFileFilter(new HTMLFilter());

Opvragen van het icoon van een bestand
Je kan je filechooser ook gebruiken als truuk om aan het icoon van een bepaald type bestand te geraken. Hiervoor gebruik je volgende code:
Code:
JFileChooser fc = new JFileChooser();
    
File file = new File("document.txt");
    
Icon icon = fc.getIcon(file);
Merk hierbij op dat je zelf geen showDialog moet gebruiken. Je kan dus eigenlijk de filechooser misbruiken om enkel aan die iconen te geraken ;) De geleverde iconen hangen ook wel af van de gebruikte L&F, dus test dit best eerst eens uit op de meest gangbare L&F's of minstens toch bij die die je wellicht zal laten gebruiken of die je vermeld als compatible met je GUI.

Voorbeeld
Een voorbeeld waarin zo goed als al deze functionaliteiten worden uiteengezet is het volgende:
Code:
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


public class FileChooserDemo extends JFrame implements ActionListener{

    private JTextField textfield;
    private JButton save;
    private JButton open;
    
    private JFileChooser fc;
    
    public FileChooserDemo() {
        super("Demo filechooser");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        initGUI();
        
        this.setSize(200,140);
        this.setVisible(true);
    }
    
    private void initGUI() {
        textfield = new JTextField();
        
        fc = new JFileChooser();
        fc.addChoosableFileFilter(new HTMLFilter());
        
        save = new JButton("Save...");
        save.addActionListener(this);
        open = new JButton("Open...");
        open.addActionListener(this);
        
        JPanel paneel = new JPanel(new GridLayout(3,1));
        paneel.add(save);
        paneel.add(open);
        paneel.add(textfield);
        
        this.setContentPane(paneel);
    }
    
    public static void main(String[] args) {
        new FileChooserDemo();
    }

    public void actionPerformed(ActionEvent ae) {
        Object source = ae.getSource();
        
        int ret=0;
        if(source == save) {
            ret = fc.showSaveDialog(this);
        }else if(source == open) {
            ret = fc.showOpenDialog(this);
        }else {
            return;
        }
        
        if(ret==JFileChooser.APPROVE_OPTION) {
            textfield.setText(fc.getSelectedFile().toString());
        }
        else {
            textfield.setText("U annuleerde");
        }
        
    }

}

class HTMLFilter extends FileFilter {
    public boolean accept(java.io.File file) {
        String filename = file.getName();
        return filename.endsWith(".html");
    }
    public String getDescription() {
        return "Webpagina's (*.html)";
    }
}
Het bestand is ook te downloaden als bijlage:

.txt  FileChooserDemo.txt (Grootte: 1,73 KB / Aantal keer gedownload: 8)
(Even hernoemen naar .java en dan compileren :))

Als er nog verdere functies willen benadrukt of uitgelegd worden, zeg het gerust en ik plaats ze er nog bij of ik vul de reeds gegeven uitleg graag nog aan met verdere uitleg :)
(Dit bericht is het laatst bewerkt op 16-08-2006 om 21:03:25 door Elco.)
16-08-2006 21:01:59
De website van deze gebruiker bezoeken Alle berichten van deze gebruiker zoeken Reageren op dit bericht
Aries-Belgium Offline
Open Source Promotor

Berichten: 8.654
Lid sinds: 04-2006
Reputatie: 310
Bericht: #2
RE: Dialoogvensters voor bestandskeuze
Heel makkelijk te proberen. Cool :b:

[Afbeelding: 2wqbwas.gif]
"I like my women how I like my toast, hot and consumable with butter"
16-08-2006 21:07:40
Alle berichten van deze gebruiker zoeken Reageren op dit bericht
Elco Offline
Ep2 Volunteer
****

Berichten: 1.237
Lid sinds: 04-2006
Reputatie: 29
Bericht: #3
RE: Dialoogvensters voor bestandskeuze
Idd, met enkele lijnen code heb je meteen een heel venster met voorgeprogrammeerde code ter beschikking, echt weer een krachtig voorbeeld van OOP en z'n herbruikbaarheid :)
16-08-2006 21:16:34
De website van deze gebruiker bezoeken Alle berichten van deze gebruiker zoeken Reageren op dit bericht
incyi Offline
Junior Member
**

Berichten: 26
Lid sinds: 01-2007
Reputatie: 0
Bericht: #4
RE: Dialoogvensters voor bestandskeuze
WOOOOW Ik wist niet eens dat dat zoo eenvoudig is ?

Ik probeer het zo snel mogelijk uit.
26-01-2007 19:19:51
Alle berichten van deze gebruiker zoeken Reageren op dit bericht
Mano Offline
Senior Member
****

Berichten: 697
Lid sinds: 11-2006
Reputatie: 17
Bericht: #5
RE: Dialoogvensters voor bestandskeuze
Een paar vraagjes :
1) wat als ik nu wil filteren op meerdere types? bv html en txt? ik heb et kunnen oplossen door 2 classes te maken, voor iedere extentie dus een, en ze alle2 toe tevoegen addChoosableFileFilter. Dit lijkt mij nogal omslachtig als je veel filters hebt. Moet het toch zo of is er een beter manier?

2) hij geeft geen mappen meer weer als je filtert? niet echt handig :) hoe zorg ik ervoor dat dit wel gebeurt? ik had ergens het volgende gelezen : "fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);" maar dit verandert niets.

3) ik gebruik jou methode ook voor een savedialog, met dezelfde filter, maar als ik zelf geen extensie handmatig achtervoeg, dan slaagt hij niet met een extensie op. Hoe zorg ik ervoor dat als ik in mijn filefilter bv Text files aanduid dat er dan automatisch .txt achter de filename geplaatst wordt?

Voor de rest toptut hoor! :beer:

[Afbeelding: 886nw6.gif]
(Dit bericht is het laatst bewerkt op 17-10-2007 om 19:12:58 door Mano.)
17-10-2007 14:24:21
Alle berichten van deze gebruiker zoeken Reageren op dit bericht
Elco Offline
Ep2 Volunteer
****

Berichten: 1.237
Lid sinds: 04-2006
Reputatie: 29
Bericht: #6
RE: Dialoogvensters voor bestandskeuze
Na bijna 1000 views toch al 3 mensen die reageren op de tut! Dat is een rendement van 0,3%! :D

Maar serieus nu :)

1) Dat was inderdaad mss niet volledig duidelijk uit m'n voorbeeld. Je kan het in feite eenvoudig oplossen met 1 klasse, die je voor alle extenties gebruikt. Ipv de HTMLFilter uit m'n voorbeeld kan je ook een soort generieke filter maken. Zolang je maar zorgt dat alle verwachte methoden erin zitten. Dan krijg je bijvoorbeeld zoiets:
Code:
class GeneriekeFilter extends FileFilter {
    private String extension;
    private String description;

    public GeneriekeFilter(String extension, String description){
        this.extension = extension;
        this.description = description;
    }
    public boolean accept(java.io.File file) {
        String filename = file.getName();
        return filename.endsWith(extension);
    }
    public String getDescription() {
        return description;
    }
}
En dan kan je de verschillende filters eenvoudig toevoegen als volgt:
Code:
fc.addChoosableFileFilter(new GeneriekeFilter(".html", "Webpagina's"));
fc.addChoosableFileFilter(new GeneriekeFilter(".xml","XML pagina's"));
...
Dan spaar je heel wat werk uit om allemaal verschillende klassen te moeten maken. :)

2) setFileSelectionMode is om in te stellen wat er kan geselecteerd worden (als je bijvoorbeeld ook een map als locatie wil kunnen opgeven ipv een bestand, voor een installatieprogramma bijvoorbeeld). Wil je de directories ook laten zien, dan moet je de accept van de filter als volgt aanpassen:
Code:
public boolean accept(java.io.File file) {
        if (file.isDirectory()) {
        return true;
        }
        String filename = file.getName();
        return filename.endsWith(extension);
    }

3) Het is idd niet mogelijk om zelf de extentie er automatisch achter te laten zetten... Zie hiervoor bv ook: http://bugs.sun.com/bugdatabase/view_bug...id=4150661
Wat je wel kan doen is bijvoorbeeld opvragen wat de gekozen extentie was en die er eventueel nog achterplakken bij de bestandsnaam als die niet eindigt op de extentie.
Voeg hiervoor de volgende methode toe aan de GeneriekeFilter:
Code:
...
public String getExtension(){
    return extension;
}
...
Dan krijg je zoiets:
Code:
... //toon filechooser en stop naam bv in string 'filename'
GeneriekeFilter filter = (GeneriekeFilter)fc.getFileFilter();    //vraagt gekozen filefilter op
if (filter!=null) {
    if (!filename.endsWith(filter.getExtension())
        filename = filename + filter.getExtension();
}

Voor alle duidelijkheid de totale filter ziet er dan normaal ongeveer zo uit:
Code:
class GeneriekeFilter extends FileFilter {
    private String extension;
    private String description;

    public GeneriekeFilter(String extension, String description){
        this.extension = extension;
        this.description = description;
    }

    public boolean accept(java.io.File file) {
        if (file.isDirectory()) {
        return true;
        }
        String filename = file.getName();
        return filename.endsWith(extension);
    }

    public String getDescription() {
        return description;
    }

    public String getExtension(){
        return extension;
    }
}

Ik heb dit allemaal uit het hoofd geschreven, dus vergeef me eventuele syntax fouten, maar het principe zou normaal goed moeten zijn. Veel succes er alvast mee! :)

C#.Net Developer
19-10-2007 17:48:56
De website van deze gebruiker bezoeken Alle berichten van deze gebruiker zoeken Reageren op dit bericht
Jasper Offline
Ep2 Admin
******

Berichten: 15.056
Lid sinds: 04-2006
Reputatie: 223
Bericht: #7
RE: Dialoogvensters voor bestandskeuze
Elco schreef:Na bijna 1000 views toch al 3 mensen die reageren op de tut! Dat is een rendement van 0,3%!
Gelukkig heeft elke tutorial een bezoekersrendement van VEEL hoger :) Tutorials hebben altijd veel hits vanuit de zoekmachines.

Om de zeven minuten denkt de vrouw dat de man alleen maar aan seks denkt.
20-10-2007 11:57:36
De website van deze gebruiker bezoeken Alle berichten van deze gebruiker zoeken Reageren op dit bericht
libia Offline
..
***

Berichten: 150
Lid sinds: 10-2007
Reputatie: 22
Bericht: #8
RE: Dialoogvensters voor bestandskeuze
er staat trouwens (volgensmij) nergens uitgelegd hoe je de style kunt veranderen, dit lijkt mij juist wel interessant..
20-10-2007 15:15:36
Alle berichten van deze gebruiker zoeken Reageren op dit bericht
Cuve Afwezig
Netlog Web Developer
*****

Berichten: 5.377
Lid sinds: 04-2006
Reputatie: 151
Bericht: #9
RE: Dialoogvensters voor bestandskeuze
Dat hangt volgens mij af van je gebruikte Look en Feel van je project die je vooraf instelde en kun je dat niet zomaar wijzigen.

20-10-2007 15:27:11
De website van deze gebruiker bezoeken Alle berichten van deze gebruiker zoeken Reageren op dit bericht
libia Offline
..
***

Berichten: 150
Lid sinds: 10-2007
Reputatie: 22
Bericht: #10
RE: Dialoogvensters voor bestandskeuze
en hoe stel je je look en feel van je project in? :$
20-10-2007 15:39:38
Alle berichten van deze gebruiker zoeken Reageren op dit bericht
MichielV Offline
ep2'er
****

Berichten: 2.322
Lid sinds: 07-2006
Reputatie: 110
Bericht: #11
RE: Dialoogvensters voor bestandskeuze
20-10-2007 15:49:41
Alle berichten van deze gebruiker zoeken Reageren op dit bericht
Mano Offline
Senior Member
****

Berichten: 697
Lid sinds: 11-2006
Reputatie: 17
Bericht: #12
RE: Dialoogvensters voor bestandskeuze
Je hebt mij geweldig goed geholpen Elco!! :D Dank je wel! ++

[Afbeelding: 886nw6.gif]
20-10-2007 20:17:24
Alle berichten van deze gebruiker zoeken Reageren op dit bericht
Reactie plaatsen 


Ga naar locatie:


Contact opnemen | Ep2 | Naar boven | Naar inhoud | Archiefmodus | RSS-syndicatie