Fond avec 2 couleurs en JavaFX?

dans JavaFX 2, en utilisant CSS, est-il possible de créer un fond avec 2 couleurs? Pensez par exemple à un TableCell avec une hauteur de 10 px. Je veux que les 2 premiers px (verticalement) soient rouges, les 8 autres px (verticalement) resteront à la couleur de fond par défaut. Est-ce possible d'utiliser CSS dans JavaFX 2? Comment?

exemple:

arrière-plan d'Origine:

enter image description here

résultat souhaité:

enter image description here (les 2 pixels supérieurs ont été remplacés par le rouge)

Merci pour tout conseil sur ce!

8
demandé sur stefan.at.wpf 2013-04-24 23:49:41

2 réponses

j'ai utilisé une couche simple de couleurs d'arrière-plan pour produire une surbrillance rouge (similaire à la solution suggérée par Stefan).

/**
 * file: table.css
 *   Place in same directory as TableViewPropertyEditorWithCSS.java.
 *   Have your build system copy this file to your build output directory.
 **/

.highlighted-cell {
  -fx-text-fill: -fx-text-inner-color;
  -fx-background-color: firebrick, gainsboro;
  -fx-background-insets: 0, 2 0 0 0;
}

pour une région standard comme un empattement, tout ce que vous devez vraiment faire est d'appliquer les css ci-dessus (moins le -fx-text-fill ) pour obtenir le résultat désiré.


Voici une autre façon délicate de définir la couleur en utilisant un gradient:

-fx-background-color: 
  linear-gradient(
    from 0px 0px to 0px 2px, 
      firebrick, firebrick 99%, 
    gainsboro
  );

Dans la capture d'écran ci-dessous, les cellules de valeur sont surlignées (en leur appliquant la classe highlighted-cell css) si elles ont la valeur false .

highlightedcells

Highlight cell style switch logic:

public void updateItem(Object item, boolean empty) {
  super.updateItem(item, empty);
  if (empty) {
    ....
    getStyleClass().remove("highlighted-cell");
  } else {
    if (getItem() instanceof Boolean && (Boolean.FALSE.equals((Boolean) getItem()))) {
      getStyleClass().add("highlighted-cell");
    } else {
      getStyleClass().remove("highlighted-cell");
    }
    ...
  }
}

Ça a l'air bon quand le highlighted-cell classe de style appliquée à une table standard de la cellule (au cours d'une updateItem appel pour une cellule personnalisé) mais existe quelques inconvénients. Le tableau modèle de coloration est très subtil et complexe. Il a des highlights pour les valeurs impaires / égales, des highlights pour les lignes sélectionnées, des highlights pour les lignes sélectionnées, des highlights pour les lignes ciblées et les cellules, etc. De plus, il a différentes combinaisons de tout ce qui précède. Juste réglage de la couleur de fond directement dans la classe de cellules surlignées est une sorte de force brute moyen d'atteindre ce que vous voulez parce qu'il ne prend pas toutes ces autres subtilités en compte et juste les remplace, donc une cellule qui a été mise en surbrillance en utilisant ce style a toujours la même apparence, peu importe l'état de classe temporaire css psuedo qui lui a été appliqué.

c'est très bien, mais une meilleure solution colorerait la cellule mise en évidence différemment selon les états de la classe de psuedo. C'est une chose assez délicate à faire cependant et vous pourriez perdre beaucoup de temps à jouer avec divers états et les combinaisons de sélecteur css pour essayer d'obtenir le point culminant changeant agréable. Dans l'ensemble, pour cet exemple, il ne semblait pas la peine de cet effort supplémentaire pour moi, bien qu'il puisse être pour vous.


programme de Test (toutes mes excuses pour la longueur et de la complexité du présent, c'était plus facile pour moi d'intégrer le style mettant en évidence la logique dans un programme existant):

import java.lang.reflect.*;
import java.util.logging.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.beans.value.*;
import javafx.collections.*;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.Callback;
// click in the value column (a couple of times) to edit the value in the column.
// property editors are defined only for String and Boolean properties.
// change focus to something else to commit the edit.
public class TableViewPropertyEditorWithCSS extends Application {

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

  @Override
  public void start(Stage stage) {
    final Person aPerson = new Person("Fred", false, false, "Much Ado About Nothing");
    final Label currentObjectValue = new Label(aPerson.toString());
    TableView<NamedProperty> table = new TableView();
    table.setEditable(true);
    table.setItems(createNamedProperties(aPerson));
    TableColumn<NamedProperty, String> nameCol = new TableColumn("Name");
    nameCol.setCellValueFactory(new PropertyValueFactory<NamedProperty, String>("name"));
    TableColumn<NamedProperty, Object> valueCol = new TableColumn("Value");
    valueCol.setCellValueFactory(new PropertyValueFactory<NamedProperty, Object>("value"));
    valueCol.setCellFactory(new Callback<TableColumn<NamedProperty, Object>, TableCell<NamedProperty, Object>>() {
      @Override
      public TableCell<NamedProperty, Object> call(TableColumn<NamedProperty, Object> param) {
        return new EditingCell();
      }
    });
    valueCol.setOnEditCommit(
            new EventHandler<CellEditEvent<NamedProperty, Object>>() {
      @Override
      public void handle(CellEditEvent<NamedProperty, Object> t) {
        int row = t.getTablePosition().getRow();
        NamedProperty property = (NamedProperty) t.getTableView().getItems().get(row);
        property.setValue(t.getNewValue());
        currentObjectValue.setText(aPerson.toString());
      }
    });
    table.getColumns().setAll(nameCol, valueCol);
    table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    VBox layout = new VBox(10);
    layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
    layout.getChildren().setAll(
            currentObjectValue,
            table);
    VBox.setVgrow(table, Priority.ALWAYS);

    Scene scene = new Scene(layout, 650, 600);
    scene.getStylesheets().add(getClass().getResource("table.css").toExternalForm());
    stage.setScene(scene);
    stage.show();
  }

  private ObservableList<NamedProperty> createNamedProperties(Object object) {
    ObservableList<NamedProperty> properties = FXCollections.observableArrayList();
    for (Method method : object.getClass().getMethods()) {
      String name = method.getName();
      Class type = method.getReturnType();
      if (type.getName().endsWith("Property")) {
        try {
          properties.add(new NamedProperty(name, (Property) method.invoke(object)));
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
          Logger.getLogger(TableViewPropertyEditorWithCSS.class.getName()).log(Level.SEVERE, null, ex);
        }
      }
    }
    return properties;
  }

  public class NamedProperty {

    public NamedProperty(String name, Property value) {
      nameProperty.set(name);
      valueProperty = value;
    }
    private StringProperty nameProperty = new SimpleStringProperty();

    public StringProperty nameProperty() {
      return nameProperty;
    }

    public StringProperty getName() {
      return nameProperty;
    }

    public void setName(String name) {
      nameProperty.set(name);
    }
    private Property valueProperty;

    public Property valueProperty() {
      return valueProperty;
    }

    public Object getValue() {
      return valueProperty.getValue();
    }

    public void setValue(Object value) {
      valueProperty.setValue(value);
    }
  }

  public class Person {

    private final SimpleStringProperty firstName;
    private final SimpleBooleanProperty married;
    private final SimpleBooleanProperty hasChildren;
    private final SimpleStringProperty favoriteMovie;

    private Person(String firstName, Boolean isMarried, Boolean hasChildren, String favoriteMovie) {
      this.firstName = new SimpleStringProperty(firstName);
      this.married = new SimpleBooleanProperty(isMarried);
      this.hasChildren = new SimpleBooleanProperty(hasChildren);
      this.favoriteMovie = new SimpleStringProperty(favoriteMovie);
    }

    public SimpleStringProperty firstNameProperty() {
      return firstName;
    }

    public SimpleBooleanProperty marriedProperty() {
      return married;
    }

    public SimpleBooleanProperty hasChildrenProperty() {
      return hasChildren;
    }

    public SimpleStringProperty favoriteMovieProperty() {
      return favoriteMovie;
    }

    public String getFirstName() {
      return firstName.get();
    }

    public void setFirstName(String fName) {
      firstName.set(fName);
    }

    public Boolean getMarried() {
      return married.get();
    }

    public void setMarried(Boolean isMarried) {
      married.set(isMarried);
    }

    public Boolean getHasChildren() {
      return hasChildren.get();
    }

    public void setHasChildren(Boolean hasChildren) {
      this.hasChildren.set(hasChildren);
    }

    public String getFavoriteMovie() {
      return favoriteMovie.get();
    }

    public void setFavoriteMovie(String movie) {
      favoriteMovie.set(movie);
    }

    @Override
    public String toString() {
      return firstName.getValue() + ", isMarried? " + married.getValue() + ", hasChildren? " + hasChildren.getValue() + ", favoriteMovie: " + favoriteMovie.get();
    }
  }

  class EditingCell extends TableCell<NamedProperty, Object> {

    private TextField textField;
    private CheckBox checkBox;

    public EditingCell() {
    }

    @Override
    public void startEdit() {
      if (!isEmpty()) {
        super.startEdit();
        if (getItem() instanceof Boolean) {
          createCheckBox();
          setText(null);
          setGraphic(checkBox);
        } else {
          createTextField();
          setText(null);
          setGraphic(textField);
          textField.selectAll();
        }
      }
    }

    @Override
    public void cancelEdit() {
      super.cancelEdit();
      if (getItem() instanceof Boolean) {
        setText(getItem().toString());
      } else {
        setText((String) getItem());
      }
      setGraphic(null);
    }

    @Override
    public void updateItem(Object item, boolean empty) {
      super.updateItem(item, empty);
      if (empty) {
        setText(null);
        setGraphic(null);
        getStyleClass().remove("highlighted-cell");
      } else {
        if (getItem() instanceof Boolean && (Boolean.FALSE.equals((Boolean) getItem()))) {
          getStyleClass().add("highlighted-cell");
        } else {
          getStyleClass().remove("highlighted-cell");
        }
        if (isEditing()) {
          if (getItem() instanceof Boolean) {
            if (checkBox != null) {
              checkBox.setSelected(getBoolean());
            }
            setText(null);
            setGraphic(checkBox);
          } else {
            if (textField != null) {
              textField.setText(getString());
            }
            setText(null);
            setGraphic(textField);
          }
        } else {
          setText(getString());
          setGraphic(null);
        }
      }
    }

    private void createTextField() {
      textField = new TextField(getString());
      textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
      textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
          if (!newValue) {
            commitEdit(textField.getText());
          }
        }
      });
    }

    private void createCheckBox() {
      checkBox = new CheckBox();
      checkBox.setSelected(getBoolean());
      checkBox.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
      checkBox.focusedProperty().addListener(new ChangeListener<Boolean>() {
        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
          if (!newValue) {
            commitEdit(checkBox.isSelected());
          }
        }
      });
    }

    private String getString() {
      return getItem() == null ? "" : getItem().toString();
    }

    private Boolean getBoolean() {
      return getItem() == null ? false : (Boolean) getItem();
    }
  }
}
14
répondu jewelsea 2013-04-25 00:13:47

regarder, comment comprendre la CSSRef:

http://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html

Regardez

- FX-background-image:

uri [, uri] *

une série D'URIs d'image séparés par des virgules.

Regardez

-FX-background-repeat

répétez-le style [ , répétez-style ]*

où répétez style = repeat-x | repeat-y | [repeat | espace | ronde | stretch | no-repeat]{1,2}

, Une série de valeurs séparées par des virgules. Chaque item de répétition de la série s'applique à l'image correspondante de la série background-image.

regardez : -FX-background-position

BG-position [, bg-position ]* où= [ [ [ taille | gauche | centre | droite ] [ taille | haut | centre | bas ]? ] | [[centre | [gauche / droite ] Taille? ] || [ centre | [ haut | bas ] taille? ] ]

, Une série de valeurs séparées par des virgules. Chaque élément de position bg de la série s'applique à l'image correspondante de la série background-image.

alors, que pouvez-vous voir : vous devez décrire 2 images, (2x2 pixels chacune - un rouge et un gris) Deux positions de bg, et deux styles de répétition pour chacun d'eux correspondant.

comment?

exemple:

{
-fx-backdround-image : "path_to_red", "path_to_grey";
-fx-background-repeat : repeat-x, stretch;
-fx-background-position : 0px 0px, 0px 2px;
}

Je ne donne pas de garantie sur le fonctionnement du code, mais l'idée semble correcte.

peut-être possible avec seulement des couleurs au lieu des images en utilisant des insets. Exemple D'origine JavaFX CSS:

.table-row-cell:odd {
  -fx-background-color: -fx-table-cell-border-color, derive(-fx-control-inner-background,-5%);
  -fx-background-insets: 0, 0 0 1 0;
}

[6 caractères...]

0
répondu Alexander Kirov 2013-04-24 21:03:27