2014-01-14 462 views
9

我試圖在JavaFX2中設置單個表格單元格的樣式TableView(表示表格單元格值已更改,包含錯誤,等等)。爲了達到這個目的,我創建了一個自定義TableCell,根據它的內容設置合適的CSS類。如何使用CSS設置JavaFX2中的表格單元格樣式(不移除懸停/選擇等)

這在某種程度上起作用,但問題是我現在失去了所有效果,懸停,選擇顏色梯度等(即僞類)。

如何使用CSS對錶格單元格進行樣式設計,而不需要重新定義僞類的所有可能組合?

我讀過this answer但該解決方案對我無效。如果我將-fx-control-inner-background設置爲我想要的背景顏色,我會得到像我想要的懸停和選擇顏色,,但初始顏色是透明的,這顯然不是我想要的(我已經在下面的CSS中註釋了嘗試,可以取消註釋並嘗試自己)。如果你能解釋原因並提供解決方案,我很樂意接受。

我也見過this answer,但我真的不想爲所有僞類重複定義(此外,它似乎只適用於行選擇)。

以下是證明該問題的SSCCE。

截屏(這看起來像我想要什麼,除了懸停和選擇不工作):

TableView showing modified and error cells

TableViewSample.java(基於Table View tutorial code):

import javafx.application.Application; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.geometry.Insets; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.control.Label; 
import javafx.scene.control.SelectionMode; 
import javafx.scene.control.TableCell; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.scene.layout.VBox; 
import javafx.scene.text.Font; 
import javafx.stage.Stage; 
import javafx.util.Callback; 

public class TableViewSample extends Application { 

    public static final String CSS_ORIGINAL = "cell-renderer-original"; 
    public static final String CSS_CHANGED = "cell-renderer-changed"; 
    public static final String CSS_ERROR = "cell-renderer-error"; 
    public static final String CSS_ERROR_AND_CHANGED = "cell-renderer-error-and-changed"; 

    private TableView<Person> table = new TableView<>(); 
    private final ObservableList<Person> data = 
      FXCollections.observableArrayList(
        new Person("Jacob", "Smith", "[email protected]"), 
        new Person("Isabella", "Johnson", "[email protected]"), 
        new Person("Ethan", "Williams", "[email protected]"), 
        new Person("Emma", "Jones", "[email protected]"), 
        new Person("Michael", "Brown", "[email protected]") 
      ); 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @Override 
    public void start(Stage stage) { 
     Scene scene = new Scene(new Group()); 
     stage.setTitle("Table View Sample"); 
     stage.setWidth(450); 
     stage.setHeight(500); 

     Label label = new Label("Address Book"); 
     label.setFont(new Font("Arial", 20)); 

     table.setEditable(true); 

     // Cell selection only (I need this) 
     table.getSelectionModel().setCellSelectionEnabled(true); 
     table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); 

     TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name"); 
     firstNameCol.setMinWidth(100); 
     firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 

     TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name"); 
     lastNameCol.setMinWidth(100); 
     lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 

     TableColumn<Person, String> emailCol = new TableColumn<>("Email"); 
     emailCol.setMinWidth(200); 
     emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email")); 

     // Install custom cell renderer 
     emailCol.setCellFactory(new Callback<TableColumn<Person, String>, TableCell<Person, String>>() { 
      @Override public TableCell<Person, String> call(final TableColumn<Person, String> personStringTableColumn) { 
       return new BackgroundTableCell(); 
      } 
     }); 

     table.setItems(data); 
     table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); 

     VBox vbox = new VBox(); 
     vbox.setSpacing(5); 
     vbox.setPadding(new Insets(10, 0, 0, 10)); 
     vbox.getChildren().addAll(label, table); 

     ((Group) scene.getRoot()).getChildren().addAll(vbox); 

     scene.getStylesheets().add(getClass().getResource("/my.css").toExternalForm()); 

     stage.setScene(scene); 
     stage.show(); 
    } 

    public static class Person { 

     private final SimpleStringProperty firstName; 
     private final SimpleStringProperty lastName; 
     private final SimpleStringProperty email; 

     private Person(String fName, String lName, String email) { 
      this.firstName = new SimpleStringProperty(fName); 
      this.lastName = new SimpleStringProperty(lName); 
      this.email = new SimpleStringProperty(email); 
     } 

     public String getFirstName() { 
      return firstName.get(); 
     } 

     public void setFirstName(String fName) { 
      firstName.set(fName); 
     } 

     public String getLastName() { 
      return lastName.get(); 
     } 

     public void setLastName(String fName) { 
      lastName.set(fName); 
     } 

     public String getEmail() { 
      return email.get(); 
     } 

     public void setEmail(String fName) { 
      email.set(fName); 
     } 
    } 

    // My custom background cell renderer 
    private static class BackgroundTableCell extends TableCell<Person, String> { 
     @Override protected void updateItem(final String item, final boolean empty) { 
      super.updateItem(item, empty); 

      setText(empty ? "" : item); 

      getStyleClass().removeAll(CSS_ORIGINAL, CSS_CHANGED, CSS_ERROR, CSS_ERROR_AND_CHANGED); 
      updateStyles(empty ? null : item); 
     } 

     private void updateStyles(String item) { 
      if (item == null) { 
       return; 
      } 

      if (item.startsWith("i") || item.startsWith("j")) { 
       getStyleClass().add(CSS_CHANGED); 
      } 
      else if (item.startsWith("e")) { 
       getStyleClass().add(CSS_ERROR); 
      } 
      else if (item.startsWith("m")) { 
       getStyleClass().add(CSS_ERROR_AND_CHANGED); 
      } 
     } 
    } 
} 

my.css:

.cell-renderer-changed { 
    -fx-background-color: rgba(255, 248, 33, .4); 
    /*-fx-control-inner-background: rgb(255, 248, 33);*/ 
    -fx-accent: derive(-fx-control-inner-background, -40%); 
    -fx-cell-hover-color: #cce3f4; 
    -fx-cell-focus-inner-border: #85b9de; 
} 

.cell-renderer-error { 
    -fx-background-color: rgba(255, 159, 160, .4); 
    /*-fx-control-inner-background: rgb(255, 159, 160);*/ 
    -fx-accent: derive(-fx-control-inner-background, -40%); 
    -fx-cell-hover-color: #cce3f4; 
    -fx-cell-focus-inner-border: #85b9de; 
} 

.cell-renderer-error-and-changed { 
    -fx-background-color: rgba(255, 205, 158, .4); 
    /*-fx-control-inner-background: rgb(255, 205, 158);*/ 
    -fx-accent: derive(-fx-control-inner-background, -40%); 
    -fx-cell-hover-color: #cce3f4; 
    -fx-cell-focus-inner-border: #85b9de; 
} 
+1

之所以設定'-fx-控制內background'不工作是'-fx-控制內background'用作背景表格行,不適用於表格單元格。表格單元在未選中/聚焦時是透明的。不是那樣有幫助... –

+0

這種解釋了爲什麼第一個鏈接問題的答案不起作用。謝謝!你知道如何設置單元格背景嗎? ;-)這似乎不合理地難以做到,這在Swing中是單線的。 – haraldK

+2

我沒有看到任何明顯的。表格單元格的背景色由'-fx-background-color:...'設置;與不使用僞類的table-row不同,table-row可以更改表格單元格的值設置只是硬編碼(在caspian.css中是透明的,在modena.css中是null)。因此,不必更改查找顏色,而必須直接覆蓋該設置,而且似乎也會覆蓋所有僞類的值。在JavaFX 8中,您可以通過使用僞類API(而不是添加和刪除樣式類)來解決問題,但我沒有看到採用這種方法。 –

回答

6

雖然不是究竟是我想要什麼,我最終找到了一種創建不包含太多冗餘的CSS的方法。

非常感謝@James_D的幫助!

下面是更新my.css

.cell-renderer-changed { 
    my-bg: rgba(255, 248, 33, .5); 
    -fx-background-color: my-bg; 
} 

.cell-renderer-error { 
    my-bg: rgba(255, 159, 160, .5); 
    -fx-background-color: my-bg; 
} 

.cell-renderer-error-and-changed { 
    my-bg: rgba(255, 205, 158, .5); 
    -fx-background-color: my-bg; 
} 

/* Restore default behaviour from caspian.css */ 
.cell-renderer-changed:hover, .cell-renderer-error:hover, .cell-renderer-error-and-changed:hover { 
    -fx-background-color: -fx-table-cell-border-color, -fx-cell-hover-color; 
    -fx-background-insets: 0, 0 0 1 0; 
} 

.cell-renderer-changed:selected, .cell-renderer-error:selected, .cell-renderer-error-and-changed:selected { 
    -fx-background: -fx-accent; 
    -fx-background-color: -fx-selection-bar; 
    -fx-text-fill: -fx-selection-bar-text; 
    -fx-background-insets: 0 0 1 0; 
} 

.cell-renderer-changed:focused:selected, .cell-renderer-error:focused:selected, .cell-renderer-error-and-changed:focused:selected { 
    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar; 
    -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2; 
    -fx-background: -fx-accent; 
    -fx-text-fill: -fx-selection-bar-text; 
} 

.cell-renderer-changed:focused, .cell-renderer-error:focused, .cell-renderer-error-and-changed:focused { 
    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, my-bg; 
    /*-fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, transparent;*/ 
    -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2; 
} 
相關問題