2013-04-24 17 views
8

In JavaFX 2, utilizzando CSS, è possibile creare uno sfondo con 2 colori? Pensa ad es. a TableCell con un'altezza di 10 px. Voglio che il primo 2 px (verticalmente) sia rosso, il restante 8 px (verticalmente) deve rimanere al colore di sfondo predefinito. È possibile usare i CSS in JavaFX 2? Come?Sfondo con 2 colori in JavaFX?

Esempio:

sfondo originale:

enter image description here

risultato desiderato:

enter image description here (tomaia 2 pixel sono stati sostituiti da rosso)

Grazie per qualsiasi suggerimento su questo!

risposta

0

Guardate, come capire il CSSRef:

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

Guarda

-fx-background-image:

uri [, uri] *

Una serie di URI immagine separati da virgole.

Guarda

-fx-background-repeat

ripetizione in stile [ripetere in stile] *

in cui ripetere-style = repeat-x | repeat-y | [ripeti | spazio | rotondo | allungare | no-repeat] {1,2}

Una serie di valori separati da virgole. Ogni elemento di stile ripetuto della serie si applica all'immagine corrispondente nella serie di immagini di sfondo.

un'occhiata a: -fx-background-position

bg-posizione [, bg-position] * dove = [ [[size | sinistra | centro | destra] [dimensione | in alto | centro | parte inferiore ]? ] | [[center | [sinistra | misura giusta? ] || [centro | [in alto | dimensione inferiore? ] ]

Una serie di valori separati da virgole. Ogni articolo di posizione bg della serie si applica all'immagine corrispondente nella serie di immagini di sfondo.

Quindi, cosa puoi vedere: dovresti descrivere 2 immagini, (2x2 pixel ciascuna - una rossa e una - grigia) Due posizioni bg e due stili di ripetizione per ognuno di essi corrispondenti.

Come?

esempio:

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

Non me ne frega un GARANZIA sul workness del codice, ma l'idea sembra corretto.

Forse possibile con solo colori invece di immagini quando si utilizzano inserti. Esempio dall'originale 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 caratteri ...]

+0

ah, non ero consapevole del fatto che si possono specificare direttamente più immagini, anche se non sono necessarie anche le immagini se non sbaglio :-) Grazie per i suggerimenti! Non l'ho ancora testato, perché è un po 'più giocherellona (.table-row-cell in realtà non ha confini ma fa trucchi con lo sfondo per simulare i confini - rende le cose un po' più complesse), ma suppongo anche che funzioni. L'aggiornamento seguirà. –

+0

Se pensi che al posto delle immagini puoi usare il colore di sfondo, ma sembra, ti sbagli, perché il colore non ha dimensioni, è solo un colore, ma l'immagine ha dimensioni, quindi può essere ripetuta, ecc ...Altrimenti, dovrai specificare la dimensione della smth colorata. –

+0

Alexander, forse è ancora possibile usare le cornici, vedere il tuo post/risposta (l'ho modificato). Cosa ne pensi di questo? –

12

ho usato un semplice strato di colori di sfondo per produrre un punto culminante rosso (simile alla soluzione suggerita 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; 
} 

Per una regione come un normale stackpane, tutto ciò che dovete fare è applicare il CSS sopra (meno la -fx-text-fill) per ottenere il risultato desiderato.


Ecco un altro modo difficile da definire il colore utilizzando un gradiente:

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

Nella schermata qui sotto, le celle di valore sono evidenziate (avendo la classe highlighted-cell css loro applicata) se hanno il valore false.

highlightedcells

Evidenziare logica interruttore classe di stile delle cellule:

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

Sembra buono quando la classe highlighted-cell stile applicato a una cella di tabella standard (durante una updateItem chiamata per una cella personalizzato) ma ha un paio di inconvenienti. Lo schema di colorazione della tavola è molto sottile e complesso. Ha punti salienti per i valori pari/dispari, punti salienti per le file selezionate, punti salienti per le righe selezionate, punti salienti per righe e celle focalizzate, ecc. Inoltre ha varie combinazioni di tutto quanto sopra. Basta impostare il colore di sfondo direttamente nella classe delle celle di evidenziazione è una sorta di metodo di forza bruta per ottenere ciò che vuoi perché non prende tutte queste sottigliezze in considerazione e semplicemente le sostituisce, quindi una cella che è stata evidenziata usando questo lo stile sembra sempre lo stesso indipendentemente da quale stato temporaneo di css psuedo-class sia stato applicato ad esso.

Va bene davvero, ma una soluzione migliore colorerebbe la cella evidenziata in modo diverso a seconda degli stati di classe psuedo. Questa è una cosa abbastanza complicata da fare e potresti sprecare un sacco di tempo a giocare con vari stati e combinazioni di selettori di CSS per cercare di ottenere il bel cambiamento. In tutto, per questo esempio non mi è valsa la pena di fare uno sforzo in più per me, anche se potrebbe essere per voi.


Programma di prova (scuse per la lunghezza e la complessità di questo, era solo più facile per me integrare lo stile mettendo in evidenza la logica in un programma esistente):

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, grazie per il tanto lavoro che hai investito qui! –

+0

Molto bello. Grazie. – jkaufmann