【问题标题】:Background with 2 colors in JavaFX?JavaFX中有2种颜色的背景?
【发布时间】:2013-04-18 12:43:23
【问题描述】:

在 JavaFX 2 中,是否可以使用 CSS 创建具有 2 种颜色的背景?想想例如TableCell 高度为 10 像素。我希望前 2 px(垂直)为红色,其余 8 px(垂直)应保持默认背景颜色。在 JavaFX 2 中使用 CSS 是否可行?如何?

示例:

原始背景:

想要的结果:

(上面2个像素被红色代替)

感谢您对此的任何提示!

【问题讨论】:

    标签: css javafx-2 tableview cell background-color


    【解决方案1】:

    看,如何理解 CSSRef:

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

    看看

    -fx-背景图像:

    uri [ , uri ]*

    一系列以逗号分隔的图像 URI。

    看看

    -fx-背景重复

    重复样式 [ , 重复样式 ]*

    其中重复样式 = 重复-x |重复-y | [重复|空间 |圆|拉伸|不重复]{1,2}

    一系列以逗号分隔的值。系列中的每个重复样式项都适用于背景图像系列中的相应图像。

    看看: -fx-背景位置

    背景位置 [ , 背景位置 ]* 其中= [ [ [ 尺寸 |离开 |中心 |对] [大小|顶部 |中心 |底部 ]? ] | [ [ 中心 | [ 左 |合适的尺码? ] || [ 中心 | [ 顶部 |底部] 尺寸? ] ]

    一系列以逗号分隔的值。系列中的每个 bg-position 项都适用于背景图像系列中的相应图像。

    那么,你能看到什么:你应该描述 2 张图片(每张 2x2 像素 - 一个红色和一个 - 灰色) 两个背景位置,每个对应的两个重复样式。

    怎么做?

    例子:

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

    我不保证代码的工作性,但这个想法似乎是正确的。

    在使用插图时可能只使用颜色而不是图像。来自原始 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 个字符...]

    【讨论】:

    • 啊,我不知道可以直接指定多个图像,尽管如果我没记错的话,甚至不需要图像 :-) 感谢您的提示!还没有测试它,因为它更麻烦(.table-row-cell 实际上没有边框,但会使用背景来模拟边框 - 让事情变得更复杂一些),但我也认为它可以工作。更新将随之而来。
    • 如果你认为可以用背景色代替图片,但似乎你错了,因为颜色没有大小,它只是一种颜色,而图片有大小,所以可以重复,等等......否则,你将不得不指定彩色smth的大小......
    • Alexander,可能仍然可以使用插图,请参阅您的帖子/答案(我编辑了它)。您对此有何看法?
    • 我明白了,你的答案比我的更正确。我的不正确,因为它是针对区域的,但单元格不是区域。因此,只需将您的答案发布为答案,如果可行的话 =)
    • css 是一个强大的东西。 Modena - 是 javafx 的全新外观。它与里海完全不同。你可以看到,css 的使用可以完全改变外观和感觉......
    【解决方案2】:

    我使用了一个简单的背景颜色层来产生红色高光(类似于 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;
    }
    

    对于像堆栈窗格这样的标准区域,您真正需要做的就是应用上述 css(减去 -fx-text-fill)来获得所需的结果。


    这是使用渐变定义颜色的另一种棘手方法:

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

    在下面的屏幕截图中,如果值为false,则值单元格会突出显示(通过将highlighted-cell css 类应用于它们)。

    高亮单元格样式类切换逻辑:

    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 调用自定义单元格期间),但确实有几个缺点。表格着色方案非常微妙和复杂。它具有奇数/偶数值的突出显示、选定行的突出显示、选定悬停行的突出显示、聚焦行和单元格的突出显示等。此外,它具有上述所有内容的各种组合。直接在 highlight-cell 类中设置背景颜色是一种蛮力方式来实现你想要的,因为它没有考虑所有其他细微之处而只是覆盖它们,所以使用这个突出显示的单元格无论应用了何种临时 CSS 伪类状态,样式看起来总是一样的。

    确实很好,但更好的解决方案会根据伪类状态对突出显示的单元格进行不同的着色。这是一件相当棘手的事情,你可能会浪费大量时间来玩弄各种状态和 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();
        }
      }
    }
    

    【讨论】:

    猜你喜欢
    • 2022-10-31
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    相关资源
    最近更新 更多