2017-02-04 2 views
0

Ich habe eine Singleton-Musterklasse namens MyFileChooser, die sich anpasst, wenn JFileChooser FILES_ONLY oder DIRECTORIES_ONLY gemäß Konstruktorparameter ist.Anfügen von Handler für JFileChooser-Schaltflächen in benutzerdefinierten JFrame in Java

Ich wünsche das JFileChooser innen JFrame haben, so kann ich über und unter JFileChooser Rahmen zusätzliche Informationen hinzufügen, so wird die Struktur aussehen:

JFrame 
| JLabel 
| JFileChooser 
| JLabel 
// end of JFrame 

import javax.swing.JFrame; 
import javax.swing.JFileChooser; 

public class MyFileChooser { 
    private JFrame frame; 
    private boolean isFilesOnly; 
    private static final MyFileChooser instance_files = new MyFileChooser(true); 
    private static final MyFileChooser instance_dirs = new MyFileChooser(false); 

    private JFileChooser dynamicChooser; 

    private MyFileChooser(boolean filesOnly) { 
     this.frame = new JFrame(); 
     this.isFilesOnly = filesOnly; 
     this.dynamicChooser = new JFileChooser(); 
     this.frameSetup(); 
     this.chooserSetup(); 
    } 

    public MyFileChooser getInstance(boolean filesOnly) { 
     if (filesOnly) { 
      return MyFileChooser.instance_files; 
     } else { 
      return MyFileChooser.instance_dirs; 
     } 
    } 

    public void frameSetup() { 
     // jframe and labels setup code 
     this.frame.getContentPane().add(this.dynamicChooser); 
    } 

    public void chooserSetup() { 
     if (this.isFilesOnly) { 
      this.dynamicChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 
     } else { 
      this.dynamicChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 
     } 
     this.dynamicChooser.setMultiSelectionEnabled(true); 
     this.dynamicChooser.setDialogType(JFileChooser.CUSTOM_DIALOG); 
    } 

Das Problem ist, dass ich nicht Sie wissen, wie Sie den Handler für die Schaltflächen "Schließen" und "Öffnen" von JFileChooser anhängen. Das einzige, was ich gefunden habe ist:

public void handleSelectedFiles() { 
    int returnVal = this.dynamicChooser.showDialog(this.frame, "Open"); 
     if (returnVal == JFileChooser.APPROVE_OPTION) { 
      File[] files = this.dynamicChooser.getSelectedFiles(); 
      // do something 
     } 
} 

Aber es beide Instanzen öffnet, wenn diese Methode aufgerufen wird und auch ohne JFrame wickeln & JLabels von erforderliche Struktur. Also meine Frage ist, wie kann ich Knopf von "Öffnen" und "Schließen" von JFileChooser zum Anhängen von Handler (anders für Instanzen) oder wie Sie mit den ausgewählten Dateien auf andere Weise umgehen.

Antwort

2

Ihr erstes Problem ist hier

int returnVal = this.dynamicChooser.showDialog(this.frame, "Open"); 

Es ist rufen Sie die zugrunde liegenden JFileChooser ‚s showDialog Methode, so dass es sein eigenes Fenster konstruieren, ohne auf Ihr

Eine bessere Lösung ist ein JDialog auf Nachfrage und Nutzung erstellen es zum Container Ihre Dateiauswahl und andere Kontrollen

Etwas ein wenig mehr wie ...

public class MyFileChooser { 

    private final boolean isFilesOnly; 
    private static final MyFileChooser INSTANCE_FILES = new MyFileChooser(true); 
    private static final MyFileChooser INSTANCE_DIRS = new MyFileChooser(false); 

    private final JFileChooser dynamicChooser; 

    private MyFileChooser(boolean filesOnly) { 
     this.isFilesOnly = filesOnly; 
     this.dynamicChooser = new JFileChooser(); 
     dynamicChooser.setControlButtonsAreShown(false); 
     this.chooserSetup(); 
    } 

    public MyFileChooser getInstance(boolean filesOnly) { 
     if (filesOnly) { 
      return MyFileChooser.INSTANCE_FILES; 
     } else { 
      return MyFileChooser.INSTANCE_DIRS; 
     } 
    } 

    public void frameSetup(Container parent) { 
     // jframe setup code 
     parent.add(this.dynamicChooser); 
    } 

    public void chooserSetup() { 
     if (this.isFilesOnly) { 
      this.dynamicChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 
     } else { 
      this.dynamicChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 
     } 
     this.dynamicChooser.setMultiSelectionEnabled(true); 
     this.dynamicChooser.setDialogType(JFileChooser.CUSTOM_DIALOG); 
    } 

    public File[] showOpenDialog(Component parent, String title) { 
     JDialog dialog = new JDialog(parent == null ? null : SwingUtilities.getWindowAncestor(parent), title); 
     dialog.setModal(true); 
     frameSetup(dialog); 

     dialog.pack(); 
     dialog.setLocationRelativeTo(parent); 

     dialog.setVisible(true); 

     return dynamicChooser.getSelectedFiles(); 
    } 
} 

Die Absicht ist, die Aktionen von showDialog von JFileChooser nachzuahmen. In diesem Beispiel habe ich die "normalen" Steuerschaltflächen ausgeblendet, da ich davon ausgehe, dass Sie Ihre eigenen bereitstellen werden, durch die Sie die Rückgabedatei ändern können.

Jetzt, wenn Sie noch die Standardtastensteuerung verwenden möchten können Sie eine ActionListener zum JFileChooser

dynamicChooser.addActionListener(new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     String cmd = e.getActionCommand(); 
     //... 
    } 
}); 

Als ich Tests war, die Taste Rückkehr CancelSelection und wählen Taste Rückkehr ApproveSelection

Jetzt Abbrechen anhängen, weil mein Beispiel einen dynamischen Dialog verwendet, müssen Sie möglicherweise erstellen eine dynamische ActionListener, die das Zifferblatt steuern kann og, weil Sie nicht wollen, ActionListener s zum FileChooser, um das Hinzufügen ohne sie zu entfernen, so etwas wie ...

public File[] showOpenDialog(Component parent, String title) { 
    JDialog dialog = new JDialog(parent == null ? null : SwingUtilities.getWindowAncestor(parent), title); 
    dialog.setModal(true); 
    frameSetup(dialog); 

    ActionListener listener = new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      String cmd = e.getActionCommand(); 
      //.. 
      dialog.dispose(); 
     } 
    }; 
    dynamicChooser.addActionListener(listener); 

    dialog.pack(); 
    dialog.setLocationRelativeTo(parent); 

    dialog.setVisible(true); 
    dynamicChooser.removeActionListener(listener); 

    return dynamicChooser.getSelectedFiles(); 
} 

als Beispiel

Beobachtung

Weil ich jemanden kennen kickt mich zu zügeln, wenn ich nicht ...

Sington ist in Java sind knifflige Dinge und es gibt unzählige Threads zu diesem Thema, aber es ist allgemein anerkannt, dass der beste Ansatz (jetzt) ​​eine enum zu verwenden ist, die so alle Probleme bei der Synchronisierung der alten

löst stattdessen könnte man mit so etwas wie betrachten ..

public static enum MyFileChooser { 

    INSTANCE_FILES(true), 
    INSTANCE_DIRS(false); 

    private final boolean isFilesOnly; 

    private final JFileChooser dynamicChooser; 

    private MyFileChooser(boolean filesOnly) { 
     this.isFilesOnly = filesOnly; 
     this.dynamicChooser = new JFileChooser(); 
     //dynamicChooser.setControlButtonsAreShown(false); 
     this.chooserSetup(); 
    } 

    public void frameSetup(Container parent) { 
     // jframe setup code 
     parent.add(this.dynamicChooser); 
    } 

    public void chooserSetup() { 
     if (this.isFilesOnly) { 
      this.dynamicChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 
     } else { 
      this.dynamicChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 
     } 
     this.dynamicChooser.setMultiSelectionEnabled(true); 
     this.dynamicChooser.setDialogType(JFileChooser.CUSTOM_DIALOG); 
    } 

    public File[] showOpenDialog(Component parent, String title) { 
     JDialog dialog = new JDialog(parent == null ? (JDialog)null : SwingUtilities.getWindowAncestor(parent), title); 
     dialog.setModal(true); 
     frameSetup(dialog); 

     ActionListener listener = new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       String cmd = e.getActionCommand(); 
       //.. 
       dialog.dispose(); 
      } 
     }; 
     dynamicChooser.addActionListener(listener); 

     dialog.pack(); 
     dialog.setLocationRelativeTo(parent); 

     dialog.setVisible(true); 
     dynamicChooser.removeActionListener(listener); 

     return dynamicChooser.getSelectedFiles(); 
    } 
} 

die Sie einfach etwas mit nennen kann wie ...

File[] files = MyFileChooser.INSTANCE_FILES.showOpenDialog(null, "Open"); 

„ich erwähnt habe ich wünsche JLabels zwischen Chooser haben“

ich, dass Auslegen Kommentare nur eine Frage war gedacht hatte, eine der Tausenden von Beispielen für das Lesen, die verfügbar sind, anscheinend war ich falsch

So ein einfaches Update der frameSetup Methode löst dieses Problem ...

public void frameSetup(Container parent) { 
    // jframe setup code 
    parent.setLayout(new BorderLayout()); 
    parent.add(new JLabel("I'm on top"), BorderLayout.NORTH); 
    parent.add(this.dynamicChooser); 
    parent.add(new JLabel("I'm on bottom"), BorderLayout.SOUTH); 
} 

Simple Layout

Werfen Sie einen Blick bei How to Use BorderLayout um weitere Informationen zu

sicherzustellen, dass es richtig funktioniert, aktualisiere ich die showOpenDialog Methode

frameSetup(dialog.getContentPane()); 

statt nur zu verwenden, um die Instanz der JDialog vorbei, stellt dies sicher, dass wir die richtigen Behälter sind zu bewirken

+0

Vielen Dank für Ihre Antwort. Ich vergesse zu erwähnen, dass ich Standard-Buttons verwenden möchte (einfache Open-Get-Dateien, Close-Frame ausblenden). Sie haben jedoch aktualisiert :) Leider kann ich dies nicht testen, weil es mir Fehler "Verweis auf JDialog ist ambig" wirft, wenn ich versuche, die Klasse zu kompilieren. – t4dohx

+0

Ändern Sie "Eltern" == null? null: ... 'to 'Eltern == null? (JDialog) null: ... ' – MadProgrammer

+0

Das oben genannte löste das zweideutige Problem. Ehrlich gesagt, denke ich, dass Enum-Lösung ist ausgezeichnet, aber es zeigt nicht die JFrame und JLabels in meinem Projekt angefordert, nur die JFileChooser-Fenster. – t4dohx