2013-04-24 2 views
8

В JavaFX 2, используя CSS, можно ли создать фон с двумя цветами? Подумайте, например. a TableCell с высотой 10 px. Я хочу, чтобы первые 2 px (по вертикали) были красными, остальные 8 px (по вертикали) должны оставаться на цвет фона по умолчанию. Возможно ли использование CSS в JavaFX 2? Как?Фон с 2 цветами в JavaFX?

Пример:

Оригинальный фон:

enter image description here

Желаемый результат:

enter image description here (верхние 2 пикселя были заменены на красный)

Спасибо за какого-либо намека на этом!

ответ

0

Посмотрите, как понять CSSRef:

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

Посмотрите на

-fx-фона изображения:

[URI, Ури] *

Серия URI изображений, разделенных запятыми.

Посмотрите на

-fx-фон-повторить

повторить стиль [повторить стиль] *

где повторяют стиль = повторить-х | repeat-y | [повторить | пространство | круглый | стрейч | no-repeat] {1,2}

Ряд значений, разделенных запятой. Каждый элемент повторного стиля в серии применяется к соответствующему изображению в серии фоновых изображений.

Посмотрите: -fx-фон-позиция

BG-положения [Б.Г. положение] * где = [ [[размера | левый | центр | правый] [размер | наверх | центр | дно ]? ] | [[центр | [left | правильный размер? ] || [центр | [наверх | низ] размер? ] ]

Ряд значений, разделенных запятой. Каждый элемент bg-position в серии применяется к соответствующему изображению в серии фоновых изображений.

Итак, что вы можете увидеть: вы должны описать 2 изображения (2x2 пикселя в каждом - один красный и один серый) Две позиции bg и два стиля повторения для каждого из них.

Как?

пример:

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

Я не даю гарантии на workness коды, но идея кажется правильной.

Возможно использование только цветов вместо изображений при использовании вставок. Пример из оригинального 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 символов ...]

+0

ах, я не знал, что можно напрямую указать несколько изображений, хотя даже изображения не нужны, если я не ошибаюсь :-) Спасибо за подсказки! Еще не тестировал, так как это еще немного возиться (у таблицы-строки-строки фактически нет границы, но есть трюки с фоном для имитации границ - делает вещи немного более сложными), но я также предполагаю, что это работает. Обновление будет следовать. –

+0

Если вы думаете, что вместо изображений вы можете использовать цвет фона, но, кажется, вы ошибаетесь, потому что цвет не имеет размера, это просто цвет, но изображение имеет размер, поэтому его можно повторить и т. Д.В противном случае вам нужно будет указать размер цветного smth. –

+0

Александр, возможно, все еще возможно использовать вставки, см. Ваш пост/ответ (я его отредактировал). Что Вы думаете об этом? –

12

Я использовал простой слой цвета фона, чтобы произвести красный блик (аналог предлагаемого решения Стефана).

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

Для стандартной области, как stackpane, все, что вам действительно нужно сделать, это применить выше CSS (меньше -fx-text-fill), чтобы получить желаемый результат.


Вот еще сложнее способ определения цвета с использованием градиента:

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

на рисунке ниже, значение ячейки выделены (при наличии класс highlighted-cell CSS применяемые к ним), если они имеют значение false.

highlightedcells

Выделите переключатель класса стиля ячейки логика:

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

Он выглядит хорошо, когда класс highlighted-cell стиля применяется к стандартной ячейке таблицы (во время updateItem вызова для пользовательской ячейки) но имеет несколько недостатков. Схема раскраски стола очень тонкая и сложная. Он имеет подсветку для нечетных/четных значений, бликов для выбранных строк, бликов для выбранных зависающих строк, бликов для сфокусированных строк и ячеек и т. Д. Кроме того, он имеет различные комбинации всего вышеперечисленного. Просто установка фонового цвета непосредственно в классе подсветки ячейки является своего рода грубой силой для достижения того, что вы хотите, потому что она не учитывает все эти другие тонкости и просто переопределяет их, поэтому ячейка, которая была подсвечена с использованием этого стиль всегда выглядит одинаково независимо от того, какое временное состояние css psuedo-класса было применено к нему.

Это нормально, но более приятное решение будет окрашивать выделенную ячейку по-разному в зависимости от состояний класса psuedo. Это довольно сложная задача, и вы можете тратить много времени на игры с различными состояниями и комбинациями селектора css, чтобы попытаться получить приятный смену. В целом, для этого примера мне не показалось, что это для меня лишние усилия, хотя это может быть для вас.


программа испытаний (Извинения для длины и сложности этого, это было просто для меня легче интегрировать стиль подсветки логики в существующую программу):

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

Вау, спасибо за столько работы, которую вы здесь инвестировали! –

+0

Очень приятно. Спасибо. – jkaufmann