Fondo con 2 colores en JavaFX?

En JavaFX 2, usando CSS, ¿es posible crear un fondo con 2 colores? Piense, por ejemplo, en una TableCell con una altura de 10 px. Quiero que los primeros 2 px (verticalmente) sean rojos, los 8 píxeles restantes (verticalmente) se mantendrán en el color de fondo predeterminado. ¿Es posible usar CSS en JavaFX 2? ¿Cómo?

Ejemplo:

Antecedentes originales:

enter image description here

Resultado deseado:

enter image description here (los 2 píxeles superiores fueron reemplazados por rojo)

Gracias por cualquier pista sobre esto!

Usé una capa simple de colores de fondo para producir un resaltado rojo (similar a la solución sugerida por 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; } 

Para una región estándar como un stackpane, todo lo que necesita hacer es aplicar el css anterior (menos el -fx-text-fill ) para obtener el resultado deseado.


Aquí hay otra forma complicada de definir el color usando un degradado:

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

En la captura de pantalla siguiente, las celdas de valor se resaltan (haciendo que se les aplique la clase css de highlighted-cell ) si tienen el valor false .

células destacadas

Resalte la lógica de cambio de clase de estilo de celda:

 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"); } ... } } 

Se ve bien cuando la clase de estilo de highlighted-cell aplica a una celda de tabla estándar (durante una invocación de elemento de actualización para una celda personalizada) pero tiene un par de inconvenientes. El esquema de coloración de la mesa es muy sutil y complejo. Tiene aspectos destacados para los valores impares / pares, los resaltados para las filas seleccionadas, los resaltados para las filas suspendidas seleccionadas, los resaltados para las filas y las celdas enfocadas, etc. Además, tiene varias combinaciones de todas las anteriores. Simplemente establecer el color de fondo directamente en la clase de celda de resaltado es una especie de fuerza bruta para lograr lo que quiere porque no tiene en cuenta todas estas sutilezas y simplemente las anula, por lo que una celda que se ha resaltado con este el estilo siempre se ve igual sin importar qué estado de clase psuedo css temporal se le haya aplicado.

En realidad está bien, pero una solución más agradable colorearía la celda resaltada de manera diferente dependiendo de los estados de la clase psuedo. Sin embargo, es una tarea bastante complicada y puede perder mucho tiempo jugando con varios estados y combinaciones de selector de CSS para tratar de obtener el mejor toque de cambio. En general, para este ejemplo, no me pareció que mereciera ese esfuerzo extra, aunque puede ser para usted.


Progtwig de prueba (disculpas por la longitud y la complejidad de esto, fue más fácil para mí integrar el estilo resaltando la lógica en un progtwig existente):

 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 table = new TableView(); table.setEditable(true); table.setItems(createNamedProperties(aPerson)); TableColumn nameCol = new TableColumn("Name"); nameCol.setCellValueFactory(new PropertyValueFactory("name")); TableColumn valueCol = new TableColumn("Value"); valueCol.setCellValueFactory(new PropertyValueFactory("value")); valueCol.setCellFactory(new Callback, TableCell>() { @Override public TableCell call(TableColumn param) { return new EditingCell(); } }); valueCol.setOnEditCommit( new EventHandler>() { @Override public void handle(CellEditEvent 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 createNamedProperties(Object object) { ObservableList 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 { 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() { @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() { @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(); } } } 

Mira, cómo entender el CSSRef:

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

Mirar

-fx-background-image:

uri [, uri] *

Una serie de URI de imágenes separadas por comas.

Mirar

-fx-background-repeat

estilo de repetición [, estilo de repetición] *

donde repeat-style = repeat-x | repeat-y | [repetir | espacio | ronda | estiramiento | no-repeat] {1,2}

Una serie de valores separados por comas. Cada elemento de estilo de repetición de la serie se aplica a la imagen correspondiente en la serie de imágenes de fondo.

Mira: -fx-background-position

bg-position [, bg-position] * donde = [[[size | izquierda | centro | derecha] [tamaño | arriba | centro | fondo ]? ] | [[centro | [izquierda | ¿Talla correcta? ] || [centro | [arriba | abajo] tamaño? ]]

Una serie de valores separados por comas. Cada elemento de posición bg en la serie se aplica a la imagen correspondiente en la serie de imágenes de fondo.

Entonces, qué puedes ver: debes describir 2 imágenes, (2×2 píxeles cada una – una roja y una – gris) Dos posiciones de bg, y dos estilos de repetición para cada uno de ellos correspondiente.

¿Cómo?

ejemplo:

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

No doy ninguna garantía sobre la funcionalidad del código, pero la idea parece correcta.

Tal vez sea posible con solo colores en lugar de imágenes al usar inserciones. Ejemplo de Java CSS original:

 .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 personajes …]