IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaFX Discussion :

afficher un damier d'images avec une liaison bind sur chaque image


Sujet :

JavaFX

  1. #1
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2021
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2021
    Messages : 12
    Points : 4
    Points
    4
    Par défaut afficher un damier d'images avec une liaison bind sur chaque image
    Bonjour la communauté,
    J'essaye de me perfectionner en JavaFx, mais j'avoue, je bloque, je n'arrive pas à trouver de solutions pour l'instant !

    Voilà je vous explique mon problème, je voudrais faire une mosaïque d'images, dont les images sont affichées à l'écran sous forme de damier, ce qui me préoccupe, c'est que je charge et j'affiche ces images une par une, ce qui est lent.

    Je voudrais grâce à un tableau d'images contenu dans la mémoire, lier les propriétés de chaque image à l'affichage afin que lorsqu'en mémoire une image du tableau d'image est changée, il y a une répercussion automatique sur les images affichées en utilisant la fonction bind.

    J'ai vu un exemple de code qui marche avec une seule image, sur le net :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    package essai_affichage;
     
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.util.Collections;
    import javafx.application.Application;
    import javafx.beans.binding.Bindings;
    import javafx.beans.property.ObjectProperty;
    import javafx.beans.property.SimpleObjectProperty;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    import javafx.scene.image.Image;
    import javafx.scene.image.ImageView;
    import javafx.scene.layout.HBox;
    import javafx.stage.Stage;
     
     
    public class main extends Application {
     
        @Override
        public void start(Stage primaryStage) throws InterruptedException, FileNotFoundException {    
     
            ImageView imageView = new ImageView();
            Button imageButton = new Button("Click Me");
     
            ObservableList<Image> imagesList = FXCollections.observableArrayList();
            FileInputStream inputstream = new FileInputStream("/home/village/Téléchargements/red.jpg");
            imagesList.add(new Image(inputstream));
            inputstream = new FileInputStream("/home/village/Téléchargements/blue.jpg");
            imagesList.add(new Image(inputstream));
            inputstream = new FileInputStream("/home/village/Téléchargements/green.jpg");
            imagesList.add(new Image(inputstream));
     
            ObjectProperty<Image> imageObjectProperty = new SimpleObjectProperty<>();
            imageObjectProperty.bind(Bindings.valueAt(imagesList,0));
     
            imageView.setFitHeight(100);
            imageView.setFitWidth(100);
            imageView.imageProperty().bind(imageObjectProperty);
     
            Group root = new Group();
            Scene scene = new Scene(root);
     
            HBox box = new HBox();
            box.getChildren().add(imageView);
            box.getChildren().add(imageButton);
            root.getChildren().add(box);
            primaryStage.setScene(scene);
            primaryStage.show();
     
            imageButton.setOnAction(event -> {
                Collections.rotate(imagesList,1);
            });
        }
        public static void main(String[] args) {
            launch(args);
        }
    }
    Sur ce code il y a une collection d'images, et un bind sur le premier élément de la collection, lorsqu'on appuie sur le bouton, la collection effectue une rotation de ses valeurs, et la première image de la collection affichée change.

    Ce que je cherche à faire est une collection des propriétés de chaque image et les lier aux propriété des images affichées, afin de réaliser un damier d'images sur l'écran qui changera si les images de la collection changent, de façon automatique. Est il possible de faire cela en java fx ?

    Merci pour votre aide éventuelle !

  2. #2
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    1. Damier : GridPane (mais ça sera un peu plus complique de gérer les changements d'image) ; le plus simple seront sans doute FlowPane ou TilePane
    2. Les images se chargent une par une : la classe Image a un constructeur qui prend un argument permettant d'indiquer que l'image doit se charger en tache de fond. Vu que dans le code présenté les images sont dans des fichiers, on peut utiliser cette variante du constructeur (avec file.toURI().toURL().toExternalForm() ou un truc du genre).
    3. il faut savoir quand le contenu de la liste change : ObservableList<Image> peut-être ?


    Du coup le bind semble être complètement inutile en fait (du moins a priori).
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  3. #3
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2021
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2021
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    C'est ce que je faisais avant dans mon programme, mais charger une vingtaine d'images par page crée un ralentissement assez important sur l'affichage. Du coup je pensais à charger ces images dans un tableau en tache de fond qui sera automatiquement par un tableau de property affiché à l'écran en respectant le rafraichissement graphique.

    Un peu comme on lie une barre graphique de progression avec une propriété qui évolue au fur à mesure de la progression de la lecture d'éléments dans une tache de fond ( 0 à 100% ).

    En fait je voudrais faire un tableau de simpleObjectProperty et le lier à la fois à ma collection d'images et à la fois à une succession d'imageview affichées c'est possible en javafx ça ?

  4. #4
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2021
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2021
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    Est il possible de faire un tableau de properties
    un tableau de SimpleObjectProperty ?

  5. #5
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2021
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2021
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    Image(String url, boolean backgroundLoading)
    Construct a new Image with the specified parameters.

    Il y a bien une option pour charger une image en background, pas encore essayé cela et la répercussion sur une vingtaine d'images chargées en même temps

  6. #6
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Voici un squelette sur lequel tu peux tenter de broder. Parmi les choses expérimentées lors du devel : charger tout un tas d'Image a leur taille réelle puis demander a ImageView de les afficher sous forme d’aperçu ne fonctionne pas bien. Non seulement l'affichage est ultra moche (la propriété smoothing de ImageView n'a jamais été capable de fonctionner correctement), mais en plus les performances de défilement sont exécrables.

    Ce qui marche c'est : créer les aperçus quand on charge les images, les aperçus sont alors visuellement OK et en plus les performances de défilement sont préservées.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    package test.tile;
     
    import javafx.application.Application;
    import javafx.application.Platform;
    import javafx.concurrent.Service;
    import javafx.concurrent.Task;
    import javafx.geometry.Orientation;
    import javafx.scene.Scene;
    import javafx.scene.control.ButtonType;
    import javafx.scene.control.Dialog;
    import javafx.scene.control.ScrollPane;
    import javafx.scene.control.Tooltip;
    import javafx.scene.image.Image;
    import javafx.scene.image.ImageView;
    import javafx.scene.layout.FlowPane;
    import javafx.stage.Modality;
    import javafx.stage.Stage;
    import javafx.stage.Window;
     
    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.Collections;
    import java.util.List;
    import java.util.Optional;
     
    public final class Main extends Application {
        private static final String STORAGE = // chemin des images
        private static final int THUMBNAIL_WIDTH = 100;
        private static final int THUMBNAIL_HEIGHT = 100;
        private static final boolean THUMBNAIL_SMOOTH = true;
        private static final boolean THUMBNAIL_PRESERVE_RATIO = true;
        private FlowPane flowPane;
        private Service<List<ImageData>> loader;
     
        @Override
        public void start(final Stage stage) throws Exception {
            flowPane = new FlowPane();
            flowPane.setOrientation(Orientation.HORIZONTAL);
            flowPane.setHgap(5);
            flowPane.setVgap(5);
    //        IntStream.range(0, 100)
    //                .forEach(index -> flowPane.getChildren().add(new Button(String.valueOf(index))));
            final var scrollPane = new ScrollPane(flowPane);
            scrollPane.setFitToWidth(true);
            final var scene = new Scene(scrollPane);
            stage.setTitle("Test");
            stage.setWidth(800);
            stage.setHeight(600);
            stage.setScene(scene);
            stage.show();
            Platform.runLater(this::loadImagesAsync);
        }
     
        private void loadImagesAsync() {
            Optional.ofNullable(loader)
                    .ifPresent(Service::cancel);
            loader = null;
            flowPane.getChildren().clear();
            final var service = new Service<List<ImageData>>() {
     
                @Override
                protected Task<List<ImageData>> createTask() {
                    return new Task<>() {
                        @Override
                        protected List<ImageData> call() throws Exception {
                            final var storagePath = Paths.get(STORAGE);
                            List<ImageData> imageList = Collections.emptyList();
                            try (final var stream = Files.list(storagePath)) {
                                imageList = stream.filter(Files::isRegularFile)
                                        .map(path -> {
                                            final var filename = path.getFileName().toString();
                                            long size = 0;
                                            try {
                                                size = Files.size(path);
                                            } catch (IOException ioe) {
                                                // @todo Log warning.
                                            }
                                            final var fileURL = path.toUri().toString();
                                            final var thumbnail = new Image(fileURL, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, THUMBNAIL_PRESERVE_RATIO, THUMBNAIL_SMOOTH, true);
                                            return new ImageData(filename, fileURL, size, thumbnail);
                                        })
                                        .toList();
                            }
                            return imageList;
                        }
                    };
                }
            };
            service.setOnSucceeded(event -> {
                System.out.println("Service succeeded");
                final var imageList = (List<ImageData>) event.getSource().getValue();
                imageList.stream()
                        .map(this::createThumbnail)
                        .forEach(flowPane.getChildren()::add);
            });
            service.setOnCancelled(event -> System.out.println("Service cancelled"));
            service.setOnFailed(event -> System.out.println("Service failed"));
            loader = service;
            loader.start();
        }
     
        private ImageView createThumbnail(final ImageData imageData) {
            final var imageView = new ImageView();
            imageView.setImage(imageData.thumbnail());
            imageView.setUserData(imageData);
            imageView.setOnMouseClicked(event -> showImage((ImageData) imageView.getUserData(), imageView.getScene().getWindow()));
            final var tooltip = new Tooltip();
            tooltip.setText(imageData.filename());
            Tooltip.install(imageView, tooltip);
            return imageView;
        }
     
        private void showImage(final ImageData imageData, final Window parent) {
            final var fileURL = imageData.fileURL();
            final var image = new Image(fileURL, true);
            final var imageView = new ImageView(image);
            final var scrollPane = new ScrollPane(imageView);
            final var dialog = new Dialog<>();
            dialog.initOwner(parent);
            dialog.initModality(Modality.APPLICATION_MODAL);
            dialog.setTitle(imageData.fileURL());
            dialog.setResizable(true);
            dialog.getDialogPane().getButtonTypes().setAll(ButtonType.OK);
            dialog.getDialogPane().setContent(scrollPane);
            dialog.show();
            Platform.runLater(() -> {
                dialog.setWidth(800);
                dialog.setHeight(600);
            });
        }
     
        private record ImageData(String filename, String fileURL, long size, Image thumbnail) {
        }
    }
    Nom : Untitled.jpg
Affichages : 28
Taille : 239,9 Ko
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  7. #7
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2021
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2021
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    Merci beaucoup, je vais regarder cela !

Discussions similaires

  1. Problème avec une liaison entre table
    Par dominou73 dans le forum Hibernate
    Réponses: 7
    Dernier message: 29/10/2007, 15h29
  2. Réponses: 15
    Dernier message: 10/05/2007, 13h36
  3. Tableau avec une liaison fichier xml
    Par loizic dans le forum InfoPath
    Réponses: 1
    Dernier message: 25/04/2007, 08h21
  4. Comment configurer un BindingSource avec une liaison
    Par Alexandre` dans le forum Accès aux données
    Réponses: 3
    Dernier message: 18/10/2006, 14h34
  5. Comment créer un lien hypertexte avec une liaison OLE Excel ?
    Par vieuxsinge dans le forum API, COM et SDKs
    Réponses: 1
    Dernier message: 08/12/2005, 17h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo