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 :

binder Property d'une ObservableList à un RadioButton dans une TableView


Sujet :

JavaFX

  1. #1
    Membre à l'essai
    Homme Profil pro
    Auditeur informatique
    Inscrit en
    Mai 2018
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Auditeur informatique

    Informations forums :
    Inscription : Mai 2018
    Messages : 18
    Points : 16
    Points
    16
    Par défaut binder Property d'une ObservableList à un RadioButton dans une TableView
    Bonjour à tous,

    J'ai une TableView comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    //Colonne -> Checkbox / risque par défaut
            ColumnIsDefaultRisk.setCellValueFactory(cellData -> cellData.getValue().isDefaultRiskProperty());
            ColumnIsDefaultRisk.setCellFactory(column -> new RadioButtonCell(toggleGroup,this));
            ColumnIsDefaultRisk.setEditable(true);
    Elle posséde une CellFactory comme ceci:
    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
    package utils;
     
    import Model.databaseModels.Risk;
    import controllers.risks.ModifyRisksAvailableController;
    import javafx.beans.value.ObservableValue;
    import javafx.scene.control.RadioButton;
    import javafx.scene.control.TableCell;
    import javafx.scene.control.ToggleGroup;
     
    public class RadioButtonCell extends TableCell<Risk, Boolean> {
     
        ToggleGroup toggleGroup;
        ModifyRisksAvailableController modifyRisksAvailableController;
     
        public RadioButtonCell(ToggleGroup group, ModifyRisksAvailableController modifyRisksAvailableController){
            toggleGroup = group;
            this.modifyRisksAvailableController = modifyRisksAvailableController;
        }
     
        @Override
        public void startEdit() {
            if (!isEmpty()) {
                super.startEdit();
            }
        }
     
        @Override
        protected void updateItem(Boolean item, boolean empty){
            super.updateItem(item, empty);
     
            System.out.println(item);
     
            if(!empty && item != null){
     
                RadioButton radioButton = new RadioButton();
                radioButton.setToggleGroup(this.toggleGroup);
                radioButton.setSelected(item);
                setGraphic(radioButton);
     
            }else{
                setGraphic(null);
            }
     
        }
    }
    J'aimerais réussir à binder ma propriété donné dans la CellValueFactory, de type BooleanProperty, à la Property de mes RadioButtons. Cependant je n'arrive pas à récupérer cette Property dans ma CellFactory car celle-ci renvoi un item de type Boolean.

    Merci beaucoup pour vos réponses.

  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
    Bonjour, je pense qu'il y a quelques soucis dans ton approche donc on va les prendre un par un :


    1)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ColumnIsDefaultRisk.setCellValueFactory(cellData -> cellData.getValue().isDefaultRiskProperty());
    Je rappelle qu'en Java la première lettre des instance doit être une minuscule, ce sont les classes qui commencent par des capitales :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    columnIsDefaultRisk.setCellValueFactory(cellData -> cellData.getValue().isDefaultRiskProperty());
    2) Je chipote un peu et donc ce point est optionnel, mais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ColumnIsDefaultRisk.setCellValueFactory(cellData -> cellData.getValue().isDefaultRiskProperty());
    Le convertisseur retourne la propriété isDefaultRisk qui devrait être de type ObjectProperty<Boolean> puisque la table n’accepte pas les type BooleanProperty. Et donc je suppose que tu as quelques chose dans le style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // Getter
    public boolean getIsDefaultRisk();
     
    // Setter
    public void setIsDefaultRisk(boolean value);
     
    // Accessor
    public ObjectProperty<Boolean> isDefaultRiskProperty();
    Cette propriété / méthode ne suit pas la convention de nommage JavaFX et des beans, en effet on devrait avoir une propriété nommée defaultRisk et le code suivant a la place:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // Getter (les getter booléen commencent par is)
    public boolean isDefaultRisk();
     
    // Setter
    public void setDefaultRisk(boolean value);
     
    // Accessor
    public ObjectProperty<Boolean> defaultRiskProperty();
    Comme je disais ce point est optionnel et on peut trouver des contre-exemples même dans l'API Java car de nombreux programmeurs y ont contribue et tous n'ont pas toujours correctement suivit les règles.

    3) tu as un memory leak dans ton RadioButtonCell. En effet tu crées sans arrêt des RadioButton que tu rajoutes dans un ToggleGroup ceux-ci restent donc en mémoire et leur nombre continuent d'augmenter tant que la liste est en cours d'utilisation. Il faudrait que la cellule utilise un seul RadioButton et qu'elle le réutilise quand la valeur a afficher n'est pas null.

    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
    public final class RadioButtonCell extends TableCell<Risk, Boolean> {
     
       private final RadioButton radioButton = new RadioButton();
     
        @Override
        protected void updateItem(Boolean item, boolean empty){
            super.updateItem(item, empty)
            Node graphic = null;
            if(!empty && item != null){
                radioButton.setSelected(item);
                graphic = radioButton;
            }
            setGraphic(graphic);
        }
    }
    ou si on fait du lazy loading :

    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
    public final class RadioButtonCell extends TableCell<Risk, Boolean> {
     
       private RadioButton radioButton = null;
     
        @Override
        protected void updateItem(Boolean item, boolean empty){
            super.updateItem(item, empty)
            Node graphic = null;
            if(!empty && item != null){
                if (radiobutton == null) {
                    radioButton = new RadioButton();
                }
                radioButton.setSelected(item);
                graphic = radioButton;
            }
            setGraphic(graphic);
        }
    }
    4) Ce qui amène au point suivant : une cellule est réutilisée des qu'on défile vers le haut / le bas dans la table / la liste / l'arbre, donc je vois pas trop le besoin d'avoir un ToggleGroup a portée de main puisque des qu'un défilement a lieu la cellule peut être affectée a une autre ligne et donc il n'y aura plus vraiment correspondance avec l'objet de la ligne courante. D'ailleurs pourquoi avoir un ToggleGroup ? Tu souhaites que lorsqu'on clique sur une ligne ça invalide de suite toutes les autres lignes ? Il serait appréciable d'avoir un peu plus d'info sur le sujet ça peut influer sur la suite.

    5) Pas besoin de faire de binding... parce que tu l'as deja fait en fait ! Le simple faire de retourner une valeur ObjectProperty<Boolean> dans ton convertisseur de valeur fait que la cellule de type TableCell<Risk, Boolean> sera mise a jour automatiquement lorsque la valeur booléenne contenue dans la propriété de l'objet change et la méthode updateItem(Boolean item, boolean empty) sera ré-invoquée pour toi par l'API Cell avec la nouvelle valeur. Par contre maintenant la question est : j'imagine que tu veux mettre a jour la valeur dans l'objet quand on coche / décoche la case ?
    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
    Membre à l'essai
    Homme Profil pro
    Auditeur informatique
    Inscrit en
    Mai 2018
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Auditeur informatique

    Informations forums :
    Inscription : Mai 2018
    Messages : 18
    Points : 16
    Points
    16
    Par défaut
    Bonjour, Merci pour ta réponse.

    Pour répondre aux différents points:
    1) Oui effectivement, je ne conaissais pas l'existence de cette convention. J'en prend note et je modifie cela

    2) Ma classe Risk est composé comme ceci:
    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
    package fr.breakoutsoftware.tradingmanager.Models.Models;
     
    import javafx.beans.property.*;
     
    public class Risk extends DatabaseModel{
     
        /**
         * Valeur du risque
         */
        final DoubleProperty riskValueProperty;
     
        /**
         *
         */
        final BooleanProperty isDefaultRiskProperty;
     
        public Risk(int id, Double riskValue, Boolean isDefaultRisk){
     
            super(id);
            riskValueProperty = new SimpleDoubleProperty(riskValue);
            isDefaultRiskProperty = new SimpleBooleanProperty(isDefaultRisk);
     
        }
     
     
        /*
            Properties
         */
        public DoubleProperty riskValueProperty(){
            return riskValueProperty;
        }
     
        public BooleanProperty isDefaultRiskProperty(){
            return isDefaultRiskProperty;
        }
     
        /*
            Getter
         */
     
        public Double getRiskValue(){
            return riskValueProperty.get();
        }
     
        public Boolean getIsDefaultRisk(){
            return isDefaultRiskProperty.get();
        }
     
        /*
            SETTERS
         */
     
        public void setIsDefaultRiskProperty(Boolean bool){
     
            isDefaultRiskProperty.set(bool);
     
        }
     
        /**
         *
         * @return
         */
        @Override
        public String toString(){
     
            return String.valueOf(getRiskValue());
     
        }
     
    }
    isDefaultProperty() retourne un BooleanProperty;

    3) Effectivement j'avais bien remarqué cette fuite car j'avais essayé d'afficher la taille de mon ToggleGroup, et celui-ci augmentait de maniére exponentielle à chaque fois que updateItem() était apellé. Je comprend beaucoup mieux mainteant pourquoi.

    4) Exactement. Le toggleGroup me permet de faire en sorte que seulement un radioButton soit cochable. Cette column permet de choisir le risque par défaut ... et il doit n'y en avoir que un. Doit le fait que je mette un toggleGroup.

    5) D'accoooorddd je comprend pourquoi quand j'ai regardé dans le code des classes déjà définie par javafx (TextFieldTableCell par exemple), je ne voyais pas de trace de bindings. Je ne savais pas que le faite que la Property change, cela allait déclencher la methode updateItem().
    Oui mon but finale est d'avoir mon ObervableList<Risk> (celle injecté dans ma TableView), dans le même état que la TableView. Et pour l'instant ce n'est pas le cas car lorsque je coche un radioButton la valeur du risque changé dans mon ObservableList ne change pas. Pour vérifier j'ai bien créer un extracteur.

  4. #4
    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
    Apres quelques test :
    • De part le concept de la cellule ToggleGroup est peu voir pas utilisable ici.
    • Il est possible d'utiliser BooleanProperty dans une TableView
    • C'est même ce qu'il faut faire si on veut utiliser les cellules builtin dans JavaFX telles que CheckBoxTableCell qui assure directement la propagation de l’édition (ça ne fonctionne pas avec ObjectProperty<Boolean>).
    • Et de toutes manières au niveau UI c'est une case a cocher et non pas un bouton radio qu'il faut mettre pour ceci.
    • Si on écoute les propriétés des risques, on peut alors forcer le fait qu'un seul risque est actif a la fois.
    • Il faut cependant mettre en place un sémaphore pour éviter des propagations de propriétés en cascade.


    Voici un exemple tres simple (je me suis pas embêté a créer tous les getters et setters) démontrant la chose :


    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
    package test.table.radio;
     
    import javafx.beans.property.*;
     
    public final class Risk {
        private final StringProperty name = new SimpleStringProperty(this, "name");
        private final ObjectProperty<Double> riskValue = new SimpleObjectProperty<Double>(this, "riskValue", 0d);
        private final BooleanProperty defaultRisk = new SimpleBooleanProperty (this, "defaultRisk", false);
     
        public Risk(final String name, final double riskValue, final boolean defaultRisk) {
            nameProperty().set(name);
            riskValueProperty().set(riskValue);
            defaultRiskProperty().set(defaultRisk);
        }
     
        public StringProperty nameProperty() {
            return name;
        }
     
        public ObjectProperty<Double> riskValueProperty() {
            return riskValue;
        }
     
        public BooleanProperty defaultRiskProperty() {
            return defaultRisk;
        }
    }

    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
    136
    137
    138
    139
    140
    141
    142
    package test.table.radio;
     
    import javafx.application.Application;
    import javafx.application.Platform;
    import javafx.beans.Observable;
    import javafx.beans.binding.Bindings;
    import javafx.beans.binding.StringBinding;
    import javafx.beans.value.ChangeListener;
    import javafx.collections.FXCollections;
    import javafx.collections.ListChangeListener;
    import javafx.scene.Scene;
    import javafx.scene.control.*;
    import javafx.scene.control.cell.CheckBoxTableCell;
    import javafx.stage.Stage;
    import javafx.util.Pair;
     
    import java.util.Objects;
    import java.util.stream.Collectors;
    import java.util.stream.IntStream;
     
    public final class Main extends Application {
        public static void main(String... args) {
            launch(args);
        }
     
        private boolean defaultRiskAdjusting = false;
     
        @Override
        public void start(final Stage stage) throws Exception {
            final int maxRisks = 50;
            final var risks = IntStream.range(0, maxRisks)
                    .mapToObj(index -> new Risk(String.format("risk %d", index + 1), 10 * Math.random(), false))
                    .collect(Collectors.toUnmodifiableList());
            ///////////
            final var nameColumn = new TableColumn<Risk, String>("Name");
            nameColumn.setCellValueFactory(feature -> feature.getValue().nameProperty());
            final var riskValueColumn = new TableColumn<Risk, Double>("Risk Value");
            riskValueColumn.setCellValueFactory(feature -> feature.getValue().riskValueProperty());
            final var defaultRiskColumn = new TableColumn<Risk, Boolean>("Default Risk");
            defaultRiskColumn.setEditable(true);
            defaultRiskColumn.setCellValueFactory(feature -> feature.getValue().defaultRiskProperty());
            defaultRiskColumn.setCellFactory(CheckBoxTableCell.forTableColumn(defaultRiskColumn));
            final var tableView = new TableView<Risk>();
            tableView.setEditable(true);
            tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
            tableView.getColumns().setAll(nameColumn, riskValueColumn, defaultRiskColumn);
            tableView.getItems().setAll(risks);
            final var listenersToRemoveLater = risks.stream()
                    .map(risk -> {
                        final ChangeListener<Boolean> changeListener = (observable, oldValue, newValue) -> {
                            System.out.printf("%s %b -> %b%n", risk.nameProperty().get(), oldValue, newValue);
                            if (!defaultRiskAdjusting && newValue) {
                                defaultRiskAdjusting = true;
                                try {
                                    risks.stream()
                                            .filter(r -> r != risk)
                                            .forEach(r -> r.defaultRiskProperty().set(false));
                                } finally {
                                    defaultRiskAdjusting = false;
                                }
                            }
                        };
                        risk.defaultRiskProperty().addListener(changeListener);
                        return new Pair<>(risk, changeListener);
                    })
                    .collect(Collectors.toUnmodifiableList());
            ///////////
            final var listView = new ListView<Risk>();
            listView.getItems().setAll(risks);
            listView.setCellFactory(lv -> new ListCell<>() {
                @Override
                protected void updateItem(final Risk item, final boolean empty) {
                    super.updateItem(item, empty);
                    if (!empty && Objects.nonNull(item)) {
                        textProperty().bind(Bindings.format("%s - %b", item.nameProperty(), item.defaultRiskProperty()));
                        styleProperty().bind(new StringBinding() {
                            {
                                bind(item.defaultRiskProperty());
                            }
     
                            @Override
                            public void dispose() {
                                super.dispose();
                                unbind(item.defaultRiskProperty());
                            }
     
                            @Override
                            protected String computeValue() {
                                return (item.defaultRiskProperty().get()) ? "-fx-font-weight: bold;" : null;
                            }
                        });
                    } else {
                        textProperty().unbind();
                        setText(null);
                        styleProperty().unbind();
                        setStyle(null);
                    }
                }
            });
            ///////////
            final var textArea = new TextArea();
            FXCollections.observableList(risks, risk -> new Observable[]{risk.defaultRiskProperty()})
                    .addListener((ListChangeListener<Risk>) change -> {
                        while (change.next()) {
                            String changeLabel = "?"; // NOI18N.
                            if (change.wasReplaced()) {
                                changeLabel = "replaced"; // NOI18N.
                            } else if (change.wasAdded()) {
                                changeLabel = "added"; // NOI18N.
                            } else if (change.wasRemoved()) {
                                changeLabel = "removed"; // NOI18N.
                            } else if (change.wasPermutated()) {
                                changeLabel = "permutated"; // NOI18N.
                            } else if (change.wasUpdated()) {
                                changeLabel = "updated"; // NOI18N.
                            }
                            final var pattern = String.format("Element %s was %s%n", "%d", changeLabel); // NOI18N.
                            final var builder = new StringBuilder(textArea.getText());
                            if (change.wasAdded() || change.wasReplaced() || change.wasUpdated()) {
                                for (int index = change.getFrom(); index < change.getTo(); index++) {
                                    builder.append(String.format(pattern, index));
                                }
                            } else {
                                for (int index = change.getFrom(); index <= change.getTo(); index++) {
                                    builder.append(String.format(pattern, index));
                                }
                            }
                            final String text = builder.toString();
                            textArea.setText(text);
                        }
                    });
            ///////////
            final var root = new SplitPane(tableView, listView, textArea);
            final var scene = new Scene(root);
            stage.setWidth(800);
            stage.setHeight(600);
            stage.setTitle("Test");
            stage.setScene(scene);
            stage.show();
            Platform.runLater(() -> root.setDividerPositions(0.33d, 0.66d));
        }
    }
    Si je conserve une liste de tous les listeners ajoutes c'est bien sur pour permettre de les retirer plus tard lorsqu'on nettoie notre UI quand on la detruit (pour éviter les fuites mémoires).

    Peut mieux faire sans doute mais c'est deja un bon debut je pense.
    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

  5. #5
    Membre à l'essai
    Homme Profil pro
    Auditeur informatique
    Inscrit en
    Mai 2018
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Auditeur informatique

    Informations forums :
    Inscription : Mai 2018
    Messages : 18
    Points : 16
    Points
    16
    Par défaut
    Bonjour,

    Je suis d'accord qu'un ToggleGroup ne peut être utilisé ici, cependant enlever les radioButtons pour des CheckBox ne me parait pas pertinent puisque le principe d'un radioButton est de montrer à l'utilisateur que uniquement une case peut être cochée.

    Effectivement j'avais remarqué ce déclenchement de listener en casquade, c'est pour cela que j'étais passé au radioButton + ToggleGroup. Et vu que je ne connaissais pas l'existence du "sémaphore", je ne savais pas comment éviter que mon listener soit déclencher.

    Pour ce qui est du code, j'ai compris en général cependant je ne voit pas ou est le système qui empêche de créé une boucle infinie sur les listener ? Pouvez-moi me donner plus de détails ?

    Merci beaucoup.

  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
    Un radio button ca permet, en général, de choisir entre plusieurs options qui sont présentées sur la même ligne ou si elles sont présentées verticalement dans le même espace. Ici on a une table et donc la présentation est complexe et avec des divisions entre chaque ligne. Après rien ne t'empêche de tenter de mettre un radio bouton avec une cellule customisée ici.

    Outre l'aspect ergonomie je n'ai pas retenu cette solution car :

    • Il y a déjà un composant prêt à l'emploi qui fait pareil avec le support de l'édition déjà fonctionnel.
    • Il doit être possible de modifier l'apparence de ce composant via CSS pour lui donner une apparence de bouton radio (hé vi)
    • Dans mon implémentation simple il y avait un soucis lors de la seconde sélection ultérieure (ainsi que les suivantes) : la dé-sélection du radio précédemment sélectionné interfère avec le clic de la souris et il faut donc cliquer 2 fois pour activer la ligne. Je n'ai pas vu l'interêt de perdre plusieurs heures à chercher à corriger ce soucis.


    Pour le reste il s'agit simplement de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    private boolean defaultRiskAdjusting = false;
     
    [...]
     
    defaultRiskAdjusting = true;
    try {
          risks.stream()
                 .filter(r -> r != risk)
                 .forEach(r -> r.defaultRiskProperty().set(false));
    } finally {
         defaultRiskAdjusting = false;
    }
    Une manière alternative de faire, trop lourde à mon gout, serait de désenregistrer le listener avant d'invoquer r.defaultRiskProperty().set(false) et de le ré-enregistrer après.
    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
    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
    A noter qu'en y réfléchissant à tête reposée le sémaphore n'est peut-être pas nécessaire puisqu'on effectue la propagation uniquement quand la valeur est true et que notre but est justement de mettre toute les autres à false.
    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

  8. #8
    Membre à l'essai
    Homme Profil pro
    Auditeur informatique
    Inscrit en
    Mai 2018
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Auditeur informatique

    Informations forums :
    Inscription : Mai 2018
    Messages : 18
    Points : 16
    Points
    16
    Par défaut
    Effectivement, je n'avais pas pensé a styliser le bouton. C'est ce que je vais faire. Je n'aime pas trop ce ToggleGroup qui grossi trop à mon goût.
    Oui c'est ce que j'avais fait pour éviter les loop, de modifier la valeur que si c'était égale à true, mais cela ne changeait rien ^^

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. radiobutton dans une listbox
    Par ola-oz dans le forum C#
    Réponses: 8
    Dernier message: 25/08/2010, 14h46
  2. Réponses: 5
    Dernier message: 12/10/2009, 17h03
  3. position d'un radioButton dans une groupBox
    Par isoman dans le forum Windows Forms
    Réponses: 5
    Dernier message: 15/12/2008, 12h15
  4. Problème avec RadioButton dans une DataList
    Par luimême dans le forum ASP.NET
    Réponses: 1
    Dernier message: 13/11/2007, 10h54
  5. [VB.NET]Gestion de radioButton dans une GroupBox
    Par Yeti_in dans le forum Windows Forms
    Réponses: 1
    Dernier message: 24/05/2006, 09h06

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