Ändern Sie die Vorschausymbole der gezogenen Dateien, wenn die Quelle das Dateisystem des Betriebssystems oder eine andeJava

Java-Forum
Anonymous
 Ändern Sie die Vorschausymbole der gezogenen Dateien, wenn die Quelle das Dateisystem des Betriebssystems oder eine ande

Post by Anonymous »

Einführung
Beim Ziehen von Elementen aus einer anderen Anwendung in den DnD-Knoten in JavaFX Das Betriebssystem oder die Quellanwendung übernimmt die visuelle Anzeige der gezogenen Elemente, da es die Quelle der gezogenen Datei(en) ist.
Dies ist bei dieser App der Fall: Der Benutzer hat die Möglichkeit, bestimmte Kategorien von Dateien per Drag-and-Drop zu verschieben, und diese Dateien werden nur aufgrund ihrer Erweiterungen akzeptiert (

Code: Select all

.png
, .jpeg usw. für Bilder).
Der Code
Die Schnittstelle DragAndDropBehavior verfügt über eine einzelne Methode handleDroppedFiles(List files), die die Dateien nach dem Ablegen verarbeitet.

Code: Select all

import java.io.File;
import java.util.List;

public interface DragAndDropBehavior {
void handleDroppedFiles(List files);
}
Die BaseDropController-Klasse implementiert DragAndDropBehavior. Seine Methode hasAllowedExtension(File f, String... extensions) gibt nur dann true zurück, wenn die Erweiterung der Datei mit einer der angegebenen Erweiterungen übereinstimmt. Die Methode notifyError(String message) gibt eine Fehlermeldung aus, wenn ein Problem auftritt.

Code: Select all

import java.io.File;

public abstract class BaseDropController implements DragAndDropBehavior {
protected boolean hasAllowedExtension(File f, String... extensions) {
var name = f.getName().toLowerCase();
for (var ext : extensions)
if (name.endsWith(ext))
return true;

return false;
}
protected void notifyError(String message) {
System.err.println(message);
}
}
Der ImageDropController erweitert den BaseDropController und implementiert so die Methode handleDroppedFiles(List files) aus der DragAndDropBehavior-Schnittstelle. handleDroppedFiles ist einfach ein Handler, der verwendet wird, wenn Dateien gelöscht werden.

Code: Select all

import java.io.File;
import java.util.List;

public class ImageDropController extends BaseDropController {
@Override
public void handleDroppedFiles(List files) {
var image = files.stream().filter(f -> hasAllowedExtension(f, ".png", ".jpg", ".jpeg", ".webp")).findFirst();
image.ifPresentOrElse(
file -> {
System.out.println("Dropped file: " + file.getAbsoluteFile());
},
() -> notifyError("No image file found.")
);
}
}
Das DragAndDropPane erweitert StackPane. Es stellt den Bereich dar, in den Dateien per Drag & Drop verschoben werden sollen. ObjectPropertyclaimedExtensions und ObjectPropertyonFilesDropped geben beide die akzeptierten Erweiterungen und den Handler für die Dateien an, wenn sie gelöscht werden. Beide werden von ihrem jeweiligen Setter basierend auf der Art der Dateien festgelegt, die per Drag-and-Drop verschoben werden sollen.

Code: Select all

import javafx.beans.property.*;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.*;
import javafx.scene.layout.StackPane;

import java.io.File;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;

public final class DragAndDropPane extends StackPane {
private final ObjectProperty acceptedExtensions = new SimpleObjectProperty();
private final ObjectProperty onFilesDropped = new SimpleObjectProperty();
private final BooleanProperty highlight = new SimpleBooleanProperty(false);

public DragAndDropPane() {
getStyleClass().add("drop-pane");

var label = new Label("Drop files here");
setAlignment(label, Pos.CENTER);
getChildren().add(label);

setOnDragOver(e -> {
if (e.getGestureSource() != this && e.getDragboard().hasFiles()) {
if (acceptsAny(e.getDragboard().getFiles())) {
e.acceptTransferModes(TransferMode.MOVE);
highlight.set(true);
}
}
e.consume();
});

setOnDragExited(e -> {
highlight.set(false);
e.consume();
});

setOnDragDropped(e -> {
var dragBoard = e.getDragboard();
boolean success = false;
if (dragBoard.hasFiles() && acceptsAny(dragBoard.getFiles())) {
var handler = getOnFilesDropped();
if (handler != null)
handler.accept(dragBoard.getFiles());
success = true;
}
e.setDropCompleted(success);
e.consume();
});

highlight.addListener((_, _, hi) ->
pseudoClassStateChanged(javafx.css.PseudoClass.getPseudoClass("active"), hi));
}

private boolean acceptsAny(List files) {
var extensions = getAcceptedExtensions();
if (extensions == null || extensions.isEmpty())
return true;
return files.stream().anyMatch(file ->
extensions.stream().anyMatch(extension -> file.getName().toLowerCase().endsWith(extension.toLowerCase()))
);
}

public void setAcceptedExtensions(Set extensions) {
acceptedExtensions.set(extensions);
}

public void setOnFilesDropped(Consumer c) {
onFilesDropped.set(c);
}

public Set getAcceptedExtensions() {
return acceptedExtensions.get();
}

public ObjectProperty acceptedExtensionsProperty() {
return acceptedExtensions;
}

public Consumer getOnFilesDropped() {
return onFilesDropped.get();
}

public ObjectProperty onFilesDroppedProperty() {
return onFilesDropped;
}
}
Die ImageDropView enthält einfach den ziehbaren Bereich und den Vorschaubereich für abgelegte Dateien. Es lädt die entsprechende FXML-Datei (

Code: Select all

ImageDropView
in diesem Fall) und bindet die Elemente an seine Felder. Anschließend wird der ImageDropController verwendet, um mit drop.setOnFilesDropped(controller::handleDroppedFiles) den Handler festzulegen, wenn Dateien im DragAndDropPane abgelegt werden.

Code: Select all

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.layout.StackPane;

import java.io.IOException;
import java.util.Set;

public final class ImageDropView {
private final Parent root;
@FXML
private DragAndDropPane drop;
@FXML
private StackPane preview;

private final ImageDropController controller = new ImageDropController();

public ImageDropView() {
try {
var loader = new FXMLLoader(getClass().getResource("ImageDropView.fxml"));
loader.setController(this);
this.root = loader.load();
} catch (IOException e) {
throw new RuntimeException(e);
}
drop.setAcceptedExtensions(Set.of(".png", ".jpg", ".jpeg", ".webp"));
drop.setOnFilesDropped(controller::handleDroppedFiles);
}

public Parent getRoot() {
return root;
}
}

Code: Select all











Die DropViewFactory-Klasse erstellt das Stammelement des angegebenen MediaType und gibt es zurück.

Code: Select all

import javafx.scene.Parent;

public final class DropViewFactory {
public static Parent create(MediaType type) {
return switch (type) {
case IMAGE -> new ImageDropView().getRoot();
case VIDEO -> new VideoDropView().getRoot();
};
}
}

Code: Select all

public enum MediaType {IMAGE, VIDEO}
Dies sind die Klassen Main Controller bzw. Main

Code: Select all

import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Modality;
import javafx.stage.Stage;

public class MainController {
@FXML
private BorderPane root;

public void openImageDialog() {
open(MediaType.IMAGE, "Import Image");
}

public void openVideoDialog() {
open(MediaType.VIDEO, "Import Video");
}

private void open(MediaType type, String title) {
var stage = new Stage();
stage.setTitle(title);
stage.initModality(Modality.APPLICATION_MODAL);
stage.setScene(new Scene(DropViewFactory.create(type), 900, 600));
stage.show();
}
}

Code: Select all

import javafx.application.Application;
import javafx.stage.Stage;
import test.MainController;

public class Main extends Application {
@Override
public void start(Stage primaryStage) {
MainController mainController = new MainController();
mainController.openImageDialog();
}
}
Was ich tun möchte
Wenn die Datei(en) auf das DragAndDropPane gezogen werden, legt das System das Symbol der Datei(en) fest. Wenn beispielsweise vier Dateien gezogen werden, zeigt das System das Formular mit reduzierter Deckkraft an. Ich möchte die Symbole durch ein einzelnes Symbol ersetzen, das die Anzahl der Elemente anzeigt, die in der unteren rechten Ecke gezogen werden.
In diesen beiden ähnlichen Fragen (Beitrag 1, Beitrag 2) wollen beide dasselbe, aber beide haben ein ziehbares Element, das aus der JavaFX-Anwendung stammt. Außerdem funktioniert es in den setDragView-Dokumenten nur, wenn die Quelle des Elements aus der App stammt.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post