2013-04-24 13 views
8

In JavaFX 2, mit CSS, ist es möglich, einen Hintergrund mit 2 Farben zu erstellen? Denken Sie z.B. a TableCell mit einer Höhe von 10 px. Ich möchte, dass die ersten 2 px (vertikal) rot sind, die restlichen 8 px (vertikal) sollen auf der Standardhintergrundfarbe bleiben. Ist das mit CSS in JavaFX 2 möglich? Wie?Hintergrund mit 2 Farben in JavaFX?

Beispiel:

Original-Hintergrund:

enter image description here

Gewünschtes Ergebnis:

enter image description here (der obere 2 Pixel durch rote ersetzt wurde)

Dank für jeden Hinweis darauf!

Antwort

0

Schauen Sie, wie die CSSRef zu verstehen:

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

Blick auf

-fx-background-image:

uri [, uri] *

Eine Reihe von Bild-URIs getrennt durch Kommas.

Blick auf

-fx-background-repeat

repeat-style [, wiederholen-style] *

wo repeat-style = repeat-x | wiederhole y | [wiederhole | Raum | Runde | Strecken | no-repeat] {1,2}

Eine Reihe von Werten getrennt durch Kommas. Jedes Objekt im Wiederholungsstil der Reihe gilt für das entsprechende Bild in der Hintergrundbildserie.

Blick auf: -fx-background-position

bg-Position [, bg-Position] * where = [ [[size | verlassen | Zentrum | richtig] [Größe | Nach oben | Zentrum | Unterseite ]? ] | [Mitte | [links | richtige Größe? ] || [Mitte | [ Nach oben | Bodenmaß? ] ]

Eine Reihe von Werten getrennt durch Kommas. Jedes bg-Positionselement in der Reihe gilt für das entsprechende Bild in der Hintergrundbildserie.

Also, was können Sie sehen: Sie sollten 2 Bilder beschreiben, (2x2 Pixel jeweils - eine rote und eine - grau) Zwei bg-Positionen und zwei Wiederholungsstile für jeden von ihnen entsprechen.

Wie?

Beispiel:

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

Ich gebe nicht eine Gewährleistung auf workness des Codes, aber die Idee scheint richtig.

Vielleicht möglich mit nur Farben anstelle von Bildern bei Verwendung von Einsätzen. Beispiel von den ursprünglichen 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 Zeichen ...]

+0

ah, ich war nicht bewusst, dass man kann direkt mehrere Bilder angeben, obwohl auch Bilder nicht benötigt werden, wenn ich mich nicht irre :-) Danke für die Hinweise! Habe es noch nicht getestet, da es ein bisschen mehr fummelt (.table-row-cell hat eigentlich keinen Rahmen, macht aber Tricks mit dem Hintergrund, um Grenzen zu simulieren - macht die Dinge ein bisschen komplexer), aber ich würde auch annehmen, dass es funktioniert. Das Update wird folgen. –

+0

Wenn Sie denken, dass anstelle von Bildern können Sie Hintergrundfarbe verwenden, aber scheint, Sie haben Unrecht, weil Farbe keine Größe hat, ist es nur eine Farbe, aber Bild hat Größe, so kann es wiederholt werden, etc ...Sonst müssen Sie die Größe der farbigen Smeth .. –

+0

Alexander, es ist vielleicht noch möglich, mit Einsätzen, sehen Sie Ihren Beitrag/Antwort (ich habe es bearbeitet). Was denkst du darüber? –

12

habe ich eine einfache Schicht von Hintergrundfarben mit einem roten Highlight (‚ähnlich wie Stefan vorgeschlagene Lösung) zu erzeugen.

/** 
* 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; 
} 

Für eine Standard-Region wie ein stackpane, alles, was Sie wirklich tun müssen, ist die oben CSS anwenden (abzüglich die -fx-text-fill), um das gewünschte Ergebnis zu erhalten.


Hier ist eine andere komplizierte Weise ist die Farbe unter Verwendung eines Gradienten zu definieren:

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

in der Abbildung unten, die Wertzellen sind markiert (indem der highlighted-cell CSS-Klasse auf sie angewendet) wenn Sie den Wert false haben.

highlightedcells

Spitzlichtnäpfchen Artklasse Schaltlogik:

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

Es sieht gut aus, wenn die highlighted-cell Artklasse auf eine Standardtabellenzelle angelegt (während eines updateItem Aufruf für eine benutzerdefinierte Zelle) hat aber ein paar Nachteile. Das Tabellenfarbschema ist sehr subtil und komplex. Es enthält Hervorhebungen für ungerade/gerade Werte, Hervorhebungen für ausgewählte Zeilen, Hervorhebungen für ausgewählte schwebende Zeilen, Hervorhebungen für fokussierte Zeilen und Zellen usw. Außerdem bietet es verschiedene Kombinationen aller oben genannten Möglichkeiten. Nur die Hintergrundfarbe direkt in der Highlight-Cell-Klasse zu setzen, ist eine Art roher Gewalt, um das zu erreichen, was Sie wollen, weil es all diese anderen Feinheiten nicht berücksichtigt und sie nur überschreibt, also eine Zelle, die damit markiert wurde Der Stil sieht immer gleich aus, unabhängig davon, welcher temporäre CSS-Pseudo-Klassen-Status auf ihn angewendet wurde.

Es ist wirklich in Ordnung, aber eine bessere Lösung würde die markierte Zelle je nach Pseudo-Klassen-Status anders färben. Das ist eine ziemlich schwierige Sache und du könntest viel Zeit damit verschwenden, mit verschiedenen Zuständen und CSS-Selektor-Kombinationen herumzuspielen, um zu versuchen, das schöne wechselnde Highlight zu bekommen. Alles in allem schien es mir für dieses Beispiel nicht so viel Mühe zu geben, auch wenn es für dich sein könnte.


Testprogramm (Entschuldigung für Länge und Komplexität dieser, es war einfach für mich einfacher, den Stil hervorheben Logik in ein bestehendes Programm zu integrieren):

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(); 
    } 
    } 
} 
+1

wow, danke für so viel Arbeit, die Sie hier investiert haben! –

+0

Sehr schön. Vielen Dank. – jkaufmann