2013-04-24 59 views
8

Trong JavaFX 2, sử dụng CSS, bạn có thể tạo nền với 2 màu không? Hãy nghĩ về ví dụ a TableCell với chiều cao là 10 px. Tôi muốn 2 px đầu tiên (theo chiều dọc) có màu đỏ, 8 px còn lại (theo chiều dọc) sẽ giữ nguyên màu nền mặc định. Có thể sử dụng CSS trong JavaFX 2 không? Làm sao?Bối cảnh có 2 màu trong JavaFX?

Ví dụ:

nền gốc:

enter image description here

kết quả mong muốn:

enter image description here (2 pixel trên được thay thế bằng màu đỏ)

Thanks cho bất kỳ gợi ý về điều này!

Trả lời

0

Look, làm thế nào để hiểu được CSSRef:

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

Nhìn vào

-fx-background-image:

uri [, uri] *

Một loạt của URI hình ảnh được phân tách bằng dấu phẩy.

Nhìn vào

-fx-background-lặp lại

lặp lại kiểu [, lặp lại theo phong cách] *

nơi lặp lại-style = lặp lại-x | lặp lại-y | [lặp lại | không gian | vòng | căng | không lặp lại] {1,2}

Một loạt giá trị được phân tách bằng dấu phẩy. Mỗi mục kiểu lặp lại trong chuỗi áp dụng cho hình ảnh tương ứng trong loạt hình nền.

Nhìn vào: -fx-background-position

bg-position [, bg-position] * nơi = [ [[size | trái | trung tâm | đúng] [size | đầu trang | trung tâm | dưới cùng]? ] | [[center | [trái | đúng] cỡ? ] || [center | [top | dưới cùng] kích thước? ] ]

Một loạt các giá trị được phân tách bằng dấu phẩy. Mỗi mục vị trí bg trong chuỗi áp dụng cho hình ảnh tương ứng trong loạt hình nền.

Vì vậy, những gì bạn có thể thấy: bạn nên mô tả 2 hình ảnh, (2x2 pixel mỗi - một màu đỏ và một - xám) Hai vị trí bg và hai kiểu lặp lại cho mỗi tương ứng.

Làm cách nào?

dụ:

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

Tôi không đưa ra một garantee trên workness của mã này, nhưng ý tưởng dường như đúng.

Có thể chỉ với các màu thay vì hình ảnh khi sử dụng các loại insets. Ví dụ từ gốc 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 ký tự ...]

+0

ah, tôi đã không biết rằng người ta có thể trực tiếp chỉ định nhiều hình ảnh, mặc dù hình ảnh thậm chí không cần thiết nếu tôi không sai :-) Cảm ơn các gợi ý! Đã không thử nghiệm nó, vì nó là một số fiddling (.table-hàng-tế bào thực sự không có biên giới nhưng không thủ đoạn với nền để mô phỏng biên giới - làm cho mọi thứ phức tạp hơn một chút), nhưng tôi cũng giả định nó hoạt động. Cập nhật sẽ theo sau. –

+0

Nếu bạn nghĩ rằng, thay vì hình ảnh bạn có thể sử dụng màu nền, nhưng có vẻ như bạn sai, vì màu không có kích cỡ, nó chỉ là màu, nhưng hình ảnh có kích thước, vì vậy nó có thể được lặp lại, v.v ...Nếu không, bạn sẽ phải chỉ định kích thước của màu smth .. –

+0

Alexander, nó có thể vẫn còn có thể sử dụng insets, xem bài viết của bạn/trả lời (tôi chỉnh sửa nó). Bạn nghĩ gì về điều này? –

12

tôi đã sử dụng một lớp đơn giản của màu nền để tạo ra một điểm nhấn màu đỏ (tương tự như giải pháp đề nghị 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; 
} 

Đối với một khu vực tiêu chuẩn như một stackpane, tất cả các bạn thực sự cần phải làm là áp dụng css trên (trừ -fx-text-fill) để có được kết quả mong muốn.


Dưới đây là một cách khéo léo để xác định màu sắc sử dụng một gradient:

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

Trong hình dưới đây, các tế bào có giá trị được đánh dấu (bởi có lớp highlighted-cell css áp dụng đối với họ) nếu có giá trị false.

highlightedcells

Highlight switch lớp phong cách logic cell:

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

Nó có vẻ tốt khi lớp highlighted-cell phong cách áp dụng cho một ô trong bảng tiêu chuẩn (trong một cuộc gọi updateItem cho một tế bào tùy chỉnh) nhưng có một vài nhược điểm. Lược đồ tô màu bảng rất tinh tế và phức tạp. Nó có điểm nổi bật cho các giá trị lẻ/chẵn, nổi bật cho các hàng đã chọn, nổi bật cho các hàng được chọn, các điểm nổi bật cho các hàng và ô được tập trung, v.v. Chỉ cần thiết lập màu nền trực tiếp trong lớp ô tô nổi bật là một loại cách thức bạo lực để đạt được những gì bạn muốn bởi vì nó không đưa tất cả các tinh tế khác vào tài khoản và chỉ ghi đè chúng, do đó một ô đã được đánh dấu bằng cách sử dụng phong cách luôn luôn trông giống nhau không có vấn đề gì tạm thời css psuedo-class nhà nước đã được áp dụng cho nó.

Thực sự tốt, nhưng một giải pháp đẹp hơn sẽ tô màu ô được đánh dấu khác nhau tùy thuộc vào trạng thái loại psuedo. Đó là một điều khá khó khăn để làm mặc dù và bạn có thể lãng phí rất nhiều thời gian chơi xung quanh với các tiểu bang khác nhau và kết hợp chọn css để cố gắng để có được sự thay đổi đẹp thay đổi. Trong tất cả, đối với ví dụ này nó có vẻ không có giá trị mà nỗ lực thêm cho tôi, mặc dù nó có thể là dành cho bạn.


chương trình thử nghiệm (xin lỗi cho chiều dài và độ phức tạp của việc này, đó chỉ là dễ dàng hơn cho tôi để tích hợp các phong cách nổi bật logic vào một chương trình hiện có):

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, cảm ơn rất nhiều công việc mà bạn đã đầu tư ở đây! –

+0

Rất đẹp. Cảm ơn bạn. – jkaufmann

Các vấn đề liên quan