Java Fx — добавление стилей к ярлыку программно без перезаписи

#java #css #javafx

#java #css #javafx

Вопрос:

Я хочу добавлять стили к ярлыку в зависимости от условий. Когда я пытаюсь это сделать, он перезаписывает предыдущий стиль. Есть ли лучший способ объединить стили?

     Label lbl = new Label(labelDescription.getLabelText());

    if (labelDescription.getLabelStyling() == LabelStyling.BOLD) {
        lbl.setStyle("-fx-font-weight: bold;");
    }

    if (labelDescription.getLabelStyling() == LabelStyling.ITALIC) {
        lbl.setStyle("-fx-font-style: italic;");
    }

    if (labelDescription.getTextSize() != null) {
        lbl.setStyle("-fx-font-size: "   labelDescription.getTextSize()   "px;");
    }
  

Комментарии:

1. Для подобных задач я рекомендую использовать классы стилей , основанные на классах, определенных в таблицах стилей CSS (или псевдоклассах, если вы хотите немного пофантазировать), а не использовать прямые строки стиля. Одним из преимуществ классов стилей перед строками стилей является то, что классы можно добавлять и удалять из коллекции, поэтому добавление нескольких классов стилей не перезаписывает предыдущие классы стилей.

Ответ №1:

Я думаю, что в вашем случае было бы проще немного реорганизовать логику стиля, например, так:

 Label lbl = new Label(labelDescription.getLabelText());

String style = "";
if (labelDescription.getLabelStyling() == LabelStyling.BOLD) {
    style  = "-fx-font-weight: bold;";
}

if (labelDescription.getLabelStyling() == LabelStyling.ITALIC) {
    style  = "-fx-font-style: italic;";
}

if (labelDescription.getTextSize() != null) {
    style  = "-fx-font-size: "   labelDescription.getTextSize()   "px;";
}

lbl.setStyle(style);
  

Хотя это может быть довольно неэффективно, если установлено более этих 3 значений, вам следует рассмотреть возможность использования StringBuilder

Надеюсь, это помогло!

Ответ №2:

Обратите внимание, что вы можете просто установить шрифт программно, вообще не используя CSS:

 Label lbl = new Label(labelDescription.getLabelText());

// get defaults:
Font font = lbl.getFont();
String family = font.getFamily();
double size = font.getSize();
FontPosture posture = FontPosture.REGULAR ;
FontWeight weight = FontWeight.NORMAL ;

if (labelDescription.getLabelStyling() == LabelStyling.BOLD) {
    weight = FontWeight.BOLD ;
}

if (labelDescription.getLabelStyling() == LabelStyling.ITALIC) {
    posture = FontPosture.ITALIC ;
}

if (labelDescription.getTextSize() != null) {
    size = labelDescription.getTextSize();
}

lbl.setFont(Font.font(family, weight, posture, size));
  

Если вы действительно хотите использовать CSS, вы можете либо создать стиль с помощью конкатенации строк, либо для веса шрифта и стиля использовать внешнюю таблицу стилей и пользовательские псевдоклассы CSS.

Например.:

label-style.css :

 /*
Note that you have to use a font which supports
bold, italic, and bold-italic on the system.
*/

#my-label {
  -fx-font-family: "Arial" ;
}

#my-label:important {
  -fx-font-weight: bold ;
}

#my-label:emphasized {
  -fx-font-style: italic ;
}
  

Я обычно предпочитаю этот подход, поскольку он упрощает программное изменение стилей в ответ на изменения состояния в приложении логическим образом. Для цветов вы можете использовать «просмотренные цвета». Единственным недостатком является то, что я не знаю способа изменить размеры шрифта, поэтому их все равно нужно выполнять с помощью встроенных стилей.

Вот полный пример использования этого, который устанавливает псевдоклассы в соответствии с пользовательским вводом:

 import javafx.application.Application;
import javafx.css.PseudoClass;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class LabelStyleTest extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        
        VBox root = new VBox(5);
        root.setAlignment(Pos.CENTER);
        
        CheckBox important = new CheckBox("Important");
        CheckBox emphasized = new CheckBox("Emphasized");
        Spinner<Integer> size = new Spinner<>(4, 36, 12);

        HBox sizeBox = new HBox(2, new Label("Size:"), size);
        sizeBox.setAlignment(Pos.CENTER);
        
        Label label = new Label("A label");
        label.setId("my-label");
        
        PseudoClass importantPC = PseudoClass.getPseudoClass("important");
        PseudoClass emphasizedPC = PseudoClass.getPseudoClass("emphasized");
        
        important.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> 
            label.pseudoClassStateChanged(importantPC, isNowSelected));
        emphasized.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> 
            label.pseudoClassStateChanged(emphasizedPC, isNowSelected));
        
        size.valueProperty().addListener((obs, oldSize, newSize) -> 
            label.setStyle("-fx-font-size: " newSize " px;"));
        
        root.getChildren().addAll(important, emphasized, sizeBox, label);
        Scene scene = new Scene(root, 800, 500);
        scene.getStylesheets().add("label-style.css");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}
  

В вашем примере вы бы сделали что-то вроде:

 Label lbl = new Label(labelDescription.getLabelText());
lbl.setId("my-label");

PseudoClass importantPC = PseudoClass.getPseudoClass("important");
PseudoClass emphasizedPC = PseudoClass.getPseudoClass("emphasized");

lbl.pseudoClassStateChanged(importantPC, 
    labelDescription.getLabelStyling() == LabelStyling.BOLD));

lbl.pseudoClassStateChanged(emphasizedPC, 
    labelDescription.getLabelStyling() == LabelStyling.ITALIC);

if (labelDescription.getTextSize() != null) {
    lbl.setStyle("-fx-font-size: "   labelDescription.getTextSize()   "px;");
}