जब उपयोगकर्ता इसे हटा देता है तो मैं तालिकादृश्य में स्ट्राइकथ्रू होने के लिए एक पंक्ति को अपडेट करना चाहता हूं। मैं javafx के लिए कुछ नया हूं और बिना किसी किस्मत के खोज रहा हूं।

        donationsTable.setRowFactory(tv -> {
            TableRow<Donation> row = new TableRow<Donation>() {
                // to force updateItem called
                @Override
                protected boolean isItemChanged(Donation d,
                        Donation d2) {
                    return true;
                }
                
                @Override
                public void updateItem(Donation d, boolean empty) {
                    super.updateItem(d, empty) ;
                    if (d == null) {
                        setStyle("");
                    } else if (d.getAction().equals(Donation.DELETE_DONATION)) {
                        setStyle("delete-row");
                    } else if (d.getAction().equals(Donation.NEW_DONATION)) {
                        setStyle("-fx-font-weight: bold;");
                    } else {
                        setStyle("");
                    }           
                }
            };
            row.setOnMouseClicked(event -> {
                    deleteDonation.setDisable(false);
            });
            return row;
        });

बोल्ड नए दान के लिए काम करता है, लेकिन मैं स्ट्राइकथ्रू काम नहीं कर सकता। मैंने देखा कि इसे पाठ पर सेट करने की आवश्यकता है, न कि पंक्ति की, इसलिए मेरी सीएसएस है:

.delete-row .text {
    -fx-strikethrough: true;
}

हालांकि, मुझे एक चेतावनी मिल रही है: चेतावनी सीएसएस त्रुटि पार्सिंग '* {डिलीट-पंक्ति}: अपेक्षित कॉलन [१,१२] पर मुझे केवल सीएसएस की एक बहुत ही बुनियादी समझ है। मैंने अन्य उत्तरों में यही देखा है, लेकिन मुझे समझ में नहीं आता कि यह मेरे लिए क्यों काम नहीं कर रहा है।

किसी भी प्रकार की मदद की बेहद सराहना की जाती है।

James_D के सुझाव के आधार पर, मैंने अपडेट बदल दिया है:


        public void updateItem(Donation d, boolean empty) {
                    super.updateItem(d, empty) ;
                    
                    PseudoClass delete = PseudoClass.getPseudoClass("delete-row");
                    pseudoClassStateChanged(delete, d != null && d.getAction().equals(Donation.DELETE_DONATION));

                    PseudoClass add = PseudoClass.getPseudoClass("add-row");
                    pseudoClassStateChanged(add, d != null && d.getAction().equals(Donation.NEW_DONATION));

                }

सीएसएस है

.table-row-cell:delete-row .text {
    -fx-strikethrough: true;
}

.table-row-cell:add-row {
    -fx-font-weight: bold;
}

स्ट्राइकथ्रू अभी भी काम नहीं कर रहा है और बोल्ड ने काम करना बंद कर दिया है।

1
Chris Whitcomb 12 अक्टूबर 2020, 13:42

2 जवाब

सबसे बढ़िया उत्तर

setStyle विधि एक इनलाइन शैली को Node पर सेट करेगी; यह शैली CSS नियम के रूप में है। बोल्ड केस के साथ आप यही करते हैं:

if (d.getAction().equals(Donation.NEW_DONATION)) {
    setStyle("-fx-font-weight: bold;");
}

एक नोड के लिए कक्षाओं की सूची में एक सीएसएस वर्ग जोड़ने के लिए, नोड के सीएसएस वर्गों की सूची प्राप्त करें getStyleClass(), और उसमें हेरफेर करें।

आपको यहां थोड़ा सावधान रहना होगा, क्योंकि सूची में एक ही मूल्य की कई प्रतियां हो सकती हैं, और इसके अतिरिक्त आपका इस पर कोई नियंत्रण नहीं है कि कितनी बार updateItem() को कॉल किया जाता है और जिसके साथ Donation एक पैरामीटर के रूप में . सबसे अच्छा विकल्प यह है कि delete-row कक्षा के सभी उदाहरणों को हटा दिया जाए और सही परिस्थितियों में एक को वापस जोड़ा जाए:

@Override
public void updateItem(Donation d, boolean empty) {
    super.updateItem(d, empty) ;

    getStyleClass().removeAll(Collections.singleton("delete-row"));

    if (d == null) {
        setStyle("");
    } else if (d.getAction().equals(Donation.DELETE_DONATION)) {
        setStyle("");
        getStyleClass().add("delete-row");
    } else if (d.getAction().equals(Donation.NEW_DONATION)) {
        setStyle("-fx-font-weight: bold;");
    } else {
        setStyle("");
    }           
}

एक अन्य विकल्प इसके बजाय CSS स्यूडोक्लास का उपयोग करना है:

@Override
public void updateItem(Donation d, boolean empty) {
    super.updateItem(d, empty) ;

    PseudoClass delete = PseudoClass.getPseudoClass("delete-row");
    pseudoClassStateChanged(delete, d != null && d.getAction().equals(Donation.DELETE_DONATION));

    if (d != null && d.getAction().equals(Donation.NEW_DONATION)) {
        setStyle("-fx-font-weight: bold;");
    } else {
        setStyle("");
    }           
}

साथ

.table-row-cell:delete-row .text {
    -fx-strikethrough: true;
}

स्थिरता के लिए, मैं शायद इस परिदृश्य में NEW_DONATION शैली को छद्म वर्ग के रूप में भी दोबारा प्रतिक्रिया दूंगा।

स्यूडोक्लास का उपयोग करके यहां एक पूरा उदाहरण दिया गया है। ध्यान दें कि मैंने सीएसएस को बोल्ड के लिए बदल दिया है (जैसा कि मैं इसे समझता हूं, font-weight का उपयोग करके सिस्टम पर निर्भर करता है कि वर्तमान में चयनित फ़ॉन्ट के लिए बोल्ड फ़ॉन्ट है; कुछ सामान्य (sans-serif) का उपयोग करके ) एक -fx-font नियम के साथ अधिक मजबूत है।)

दान.जावा

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Donation {

    public enum Action { NEW_DONATION, DELETE_DONATION, NO_ACTION }
    
    private final StringProperty name = new SimpleStringProperty() ;
    private final ObjectProperty<Action> action = new SimpleObjectProperty<>() ;
    
    public Donation(String name, Action action) {
        setName(name);
        setAction(action);
    }

    public final StringProperty nameProperty() {
        return this.name;
    }
    

    public final String getName() {
        return this.nameProperty().get();
    }
    

    public final void setName(final String name) {
        this.nameProperty().set(name);
    }
    

    public final ObjectProperty<Action> actionProperty() {
        return this.action;
    }
    

    public final Action getAction() {
        return this.actionProperty().get();
    }
    

    public final void setAction(final Action action) {
        this.actionProperty().set(action);
    }
    
    
    
}

ऐप.जावा

import java.util.Random;
import java.util.function.Function;

import javafx.application.Application;
import javafx.beans.property.Property;
import javafx.css.PseudoClass;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;


public class App extends Application {

    @Override
    public void start(Stage stage) {
        TableView<Donation> table = new TableView<>();
        
        table.setRowFactory(tv -> {
            TableRow<Donation> row = new TableRow<>() {
                @Override
                protected void updateItem(Donation donation, boolean empty) {
                    super.updateItem(donation, empty);
                    PseudoClass add = PseudoClass.getPseudoClass("add-row");
                    pseudoClassStateChanged(add, 
                        donation != null && donation.getAction() == Donation.Action.NEW_DONATION);

                    PseudoClass delete = PseudoClass.getPseudoClass("delete-row");
                    pseudoClassStateChanged(delete, 
                        donation != null && donation.getAction() == Donation.Action.DELETE_DONATION);
                }
            };
            return row ;
        });
        
        Random rng = new Random();
        for (int i = 1 ; i <= 40 ; i++) {
            table.getItems().add(new Donation("Donation "+i, Donation.Action.values()[rng.nextInt(3)]));
        }
        
        table.getColumns().add(column("Donation", Donation::nameProperty));
        table.getColumns().add(column("Action", Donation::actionProperty));
        
        BorderPane root = new BorderPane(table);
        Scene scene = new Scene(root);
        scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
        stage.setScene(scene);
        stage.show();
    }
    
    private static <S,T> TableColumn<S,T> column(String name, Function<S, Property<T>> prop) {
        TableColumn<S,T> col = new TableColumn<>(name);
        col.setCellValueFactory(data -> prop.apply(data.getValue()));
        return col ;
    }

    public static void main(String[] args) {
        launch();
    }

}

स्टाइल.सीएसएस:

.table-row-cell:delete-row .text {
    -fx-strikethrough: true;
}

.table-row-cell:add-row {
    /* -fx-font-weight: bold; */
    -fx-font: bold 1em sans-serif ;
}

enter image description here


अद्यतन:

यदि तालिका पंक्ति की शैली का निर्धारण करने वाली संपत्ति किसी एक कॉलम द्वारा नहीं देखी जा रही है (उदाहरण के लिए उपरोक्त उदाहरण में, "क्रिया" कॉलम मौजूद नहीं है), तो आपको उस संपत्ति का निरीक्षण करने के लिए पंक्ति की व्यवस्था करने की आवश्यकता है। यह थोड़ा मुश्किल है, क्योंकि विभिन्न तालिका वस्तुओं के लिए पंक्ति का पुन: उपयोग किया जाता है, इसलिए ऐसा होने पर आपको श्रोता को सही संपत्ति से जोड़ने और निकालने की आवश्यकता होती है। ऐसा दिखता है:

    table.setRowFactory(tv -> {
        TableRow<Donation> row = new TableRow<>() {

            // Listener that updates style when the actionProperty() changes
            private final ChangeListener<Donation.Action> listener = 
                (obs, oldAction, newAction) -> updateStyle();
            
            {
                // make sure listener above is registered 
                // with the correct actionProperty()
                itemProperty().addListener((obs, oldDonation, newDonation) -> {
                    if (oldDonation != null) {
                        oldDonation.actionProperty().removeListener(listener);
                    }
                    if (newDonation != null) {
                        newDonation.actionProperty().addListener(listener);
                    }
                });
            }
            
            @Override
            protected void updateItem(Donation donation, boolean empty) {
                super.updateItem(donation, empty);
                updateStyle();
            }

            private void updateStyle() {
                Donation donation = getItem();
                PseudoClass add = PseudoClass.getPseudoClass("add-row");
                pseudoClassStateChanged(add, donation != null && donation.getAction() == Donation.Action.NEW_DONATION);
                PseudoClass delete = PseudoClass.getPseudoClass("delete-row");
                pseudoClassStateChanged(delete, donation != null && donation.getAction() == Donation.Action.DELETE_DONATION);
            }
        };
        return row ;
    });
1
James_D 12 अक्टूबर 2020, 20:29

आम तौर पर मुझे लगता है कि आपको अपनी अलग-अलग शैलियों को एक अलग फ़ाइल में आज़माकर घोषित करना चाहिए :) (जैसे इस लड़के के पास है: Android में TableRow पर स्टाइल सेट करें)

लेकिन अगर आप वास्तव में सीधे कोड के माध्यम से सीएसएस करना चाहते हैं तो मुझे लगता है कि यह काम करेगा:

else if (d.getAction().equals(Donation.DELETE_DONATION)){
    setStyle("text-decoration: line-through;");
}

मुझे बताएं कि क्या यह काम करता है :)

-1
Andreas Neil Jensen 12 अक्टूबर 2020, 13:57