# JFileChooser mit Zusatzfunktionen



## Kwintai (7. Nov 2011)

Hallo Leute,

ich suche eine Möglichkeit im JFileChooser nicht nur neue Ordner anzulegen, sondern auch neue Dateien. Oder per Copy&Paste eine Kopie einer exitierenden Datei anzulegen.
Am besten auch noch über ein Rechtsklick-Menu.
Bei vielen FileChoosern aus andern Programmen kenn ich diese Funktionen, aber beim JFileChooser geht das nicht von Haus aus.

Vielen Dank schon mal für eure Hilfe.


----------



## Guybrush Threepwood (8. Nov 2011)

Du musst eine Klasse schreiben, die von JFileChooser erbt, und dann das Kontext-Menü entsprechend erweitern. Siehe z. B. Context Menu File Chooser Java code example

Man kommt nicht so ganz leicht an das Kontext-Menü heran, aber es gibt ein paar Tricks, wie es doch geht.


----------



## Kwintai (8. Nov 2011)

JFileChooser zu extenden war mir schon fast klar. Allerdings lässt sich der Code auf deiner Beispiel Seite nicht compilieren.

Man muss doch irgendwie an das schon bestehende RightClick Menu ran kommen und diesem dann noch zusätzliche JMenuItems hinzufügen können.


----------



## GUI-Programmer (8. Nov 2011)

Ich weis nicht genau, wie sich dein Vorhaben umsetzen lässt, aber grundsätlich kann man jede Komponente des JFileChoosers ändern:

```
private JTextField txtfldDirectory;
private JFileChooser chooser;
//...
//Initialisieren des Textfeldes:
initializeTextField(chooser);
//Danch zum Beispiel:
txtfldDirectory.setText("Der neue Text");
txtfldDirectory.setEditable(false);
//...

private void initializeTextField(Component component) {
	if (component instanceof JTextField) {
		JTextField txtfld = (JTextField)component;
		txtfldDirectory = txtfld;
	}
	else if (component instanceof Container) {
		Container container = (Container)component;
		for (int i = 0; i < container.getComponentCount(); i++) {
			Component child = container.getComponent(i);
			initializeTextField(child);
		}
	}
}
```

Falls es mehrere Komponenten gibt, musst du halt suchen!!!


----------



## Guybrush Threepwood (8. Nov 2011)

Kwintai hat gesagt.:


> JFileChooser zu extenden war mir schon fast klar. Allerdings lässt sich der Code auf deiner Beispiel Seite nicht compilieren.
> 
> Man muss doch irgendwie an das schon bestehende RightClick Menu ran kommen und diesem dann noch zusätzliche JMenuItems hinzufügen können.



Ich habe das früher auch mal gemacht und es hat eigentlich ganz gut geklappt. Man kann eine GlassPane über den Chooser legen und rechte Mausklicks abfangen. Ich weiß nicht, ob es mit der aktuellen Java-Version noch geht. Im Netz gibt es dazu viele Beispiele, z. B. von Filthy Rich Clients: ContextMenuFileChooser.java - filthy-rich-clients - filthy-rich-clients - Google Project Hosting


----------



## Kwintai (9. Nov 2011)

Ich habe Java 7 drauf. Nun habe ich den Code ein wenig angepasst und auf Java 7 Niveau gebracht.
Er sieht nun so aus und wird auch anständig compiliert. Ich habe nun nur noch das Problem, dass ich ein leeres, graues JFrame sehe, welches in etwa die Form des JFileChoosers hat, aber dort kein Inhalt zu sehen ist. Es ist einfach nur flächig grau. Wenn ich rechts klicke bekomme ich das Menu zu sehen, aber nur den Eintrag der direkt unter der Maus steht. Irgendwie scheint noch ein repaint() zu fehlen, aber ich weiss nicht wohin, falls es überhaupt ein repaint() Problem ist.
Meine Änderungen belaufen sich darauf, dass ich aus der RightClickGlassPane eine richtige innere Klasse gemacht habe und diese extends Component. Dann habe ich die zwei Methodenaufrufe geändert:
1. redispatchMouseEvent(e, repaint) >>> processMouseEvent(e)
2. doDispatch(e) >>> dispatchEvent(e)

Kann mir nun wer weiterhelfen?
Hier mal der Code:


```
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.io.File;

import javax.swing.AbstractAction;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JPopupMenu;

public class ContextMenuFileChooser extends JFileChooser {
	private static final long serialVersionUID = 1L;
	protected Component right_click_pane;

	public ContextMenuFileChooser() {
                super();

                JPopupMenu popup = new JPopupMenu();
                popup.add(new DeleteAction(this));
                popup.add(new NewFolderAction(this));
                popup.setLightWeightPopupEnabled(false);

                right_click_pane = new RightClickGlassPane(this, popup);
                setFileSelectionMode(FILES_AND_DIRECTORIES);
        }

	protected JDialog createDialog(Component parent) {
		JDialog dialog = super.createDialog(parent);

		// create the right click glass pane.
		dialog.setGlassPane(right_click_pane);
		right_click_pane.setVisible(true);

		return dialog;
	}

	public static void main(String[] args) {
		final JFileChooser jfc = new ContextMenuFileChooser();
		jfc.showOpenDialog(null);
		System.exit(0);
	}

	public static void p(String str) {
		System.out.println(str);
	}

}

class RightClickGlassPane extends Component {
	private static final long serialVersionUID = 1L;
	JFileChooser fc;
	JPopupMenu popup;
	
	public RightClickGlassPane(JFileChooser fc, JPopupMenu popup) {
		this.fc = fc;
		this.popup = popup;
	}
	
    protected void redispatchMouseEvent(MouseEvent e, boolean repaint) {
            Component component = this.getComponentAt(e.getPoint());
            if (component == null) {
                    return;
            }
            String chooser_class = "javax.swing.plaf.metal.MetalFileChooserUI$5";
            if (component.getClass().getName().equals(chooser_class)) {
                    super.processMouseEvent(e);
            } else {
                    dispatchEvent(e);
            }
    }
}

class DeleteAction extends AbstractAction {
	private static final long serialVersionUID = 1L;
	protected JFileChooser chooser;

	public DeleteAction(JFileChooser chooser) {
		super("Delete");
		this.chooser = chooser;
	}

	public void actionPerformed(ActionEvent evt) {
		File file = chooser.getSelectedFile();
		if (file != null) {
			file.delete();
			chooser.rescanCurrentDirectory();
		}
	}
}

class NewFolderAction extends AbstractAction {
	private static final long serialVersionUID = 1L;
	protected JFileChooser chooser;

	public NewFolderAction(JFileChooser chooser) {
		super("New Folder");
		this.chooser = chooser;
	}

	public void actionPerformed(ActionEvent evt) {
		File cwd = chooser.getCurrentDirectory();
		if (cwd != null) {
			File new_dir = new File(cwd, "New Folder");
			new_dir.mkdir();
			chooser.rescanCurrentDirectory();
		}
	}
}
```


----------



## Kwintai (9. Nov 2011)

Ich habe noch ein wenig am Code gebastelt und awt.Component mal auf swing.JComponent durchweg geändert und siehe da, ich sehe den JFileChooser. Allerdings funktioniert das rechtsklick PopupMenu noch nciht richtig. Die neuen Action Klassen wie Delete, die ich oben dem PopupMenu adde, werden bei einem rechtsklick nicht angezeigt. Es öffnet sich nur das normale Menu ohne die neuen Einträge.
Jemand ne Idee?


----------



## Kwintai (11. Nov 2011)

ich habe nochmal die methoden des filechoosers durchgeschaut und dort gibt es eine methode names setComponentPopupMenu(JPopupMenu popup), welche ganz bequem ohne extra glasspane oder sonst irgendwelchen gedöns, ein popup menu per rechtskllick editieren lässt.

hier der code:

```
JFileChooser chooser = new JFileChooser();
JPopupMenu popup = new JPopupMenu();
popup.add(new YOUR_ABSTRACTACTION_CLASS(chooser));
chooser .setComponentPopupMenu(popup);
```


----------



## Guybrush Threepwood (11. Nov 2011)

Cool! Danke für den Tipp!


----------

