在JavaFX中有两种颜色的背景? [英] Background with 2 colors in JavaFX?

查看:2740
本文介绍了在JavaFX中有两种颜色的背景?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在JavaFX 2中,使用CSS,是否可以用2种颜色创建背景?想想a TableCell ,高度为10像素。我想要第一个2 px(垂直)为红色,剩余的8 px(垂直)将保持默认的背景颜色。这是可能使用JavaFX 2中的CSS吗?怎么样?

In JavaFX 2, using CSS, is it possible to create a background with 2 colors? Think of e.g. a TableCell with a height of 10 px. I want to the first 2 px (vertically) to be red, the remaining 8 px (vertically) shall stay at the default background color. Is that possible using CSS in JavaFX 2? How?

示例:

原始背景:

所需结果:

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

(the upper 2 pixels were replaced by red)

感谢您的任何提示!

推荐答案

我使用一个简单的背景颜色层来产生红色高亮(类似于Stefan的建议解决方案)。

I used a simple layer of background colors to produce a red highlight (similar to Stefan' suggested solution).

/**
 * 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 )来获得所需的结果。

For a standard region like a stackpane, all you really need to do is apply the above css (less the -fx-text-fill) to get the desired result.

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

Here is another tricky way to define the color using a gradient:

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






在下面的截图中, (通过应用 highlight-cell css类)如果值 false


In the screenshot below, the value cells are highlighted (by having the highlighted-cell css class applied to them) if have the value false.

突出显示单元格样式类切换逻辑:

Highlight cell style class switch logic:

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






当将 highlight-cell 样式类应用于标准表单元格时( updateItem 调用自定义细胞),但有几个缺点。表着色方案非常微妙和复杂。它具有奇数/偶数值的高亮,所选行的高亮,所选择的悬停行的高亮,关注的行和单元格的高亮等。此外,它具有所有上述的各种组合。只是直接在highlight-cell类中设置背景颜色是一种强力的方式来实现你想要的,因为它不考虑所有这些其他微妙,只是覆盖他们,所以一个单元格已经突出显示使用这风格总是看起来相同,无论什么临时css psuedo-class状态已应用于它。


It looks good when the highlighted-cell style class applied to a standard table cell (during an updateItem call for a custom cell) but does have a couple of drawbacks. The table coloring scheme is very subtle and complex. It has highlights for odd/even values, highlights for selected rows, highlights for selected hovered rows, highlights for focused rows and cells, etc. Plus it has various combinations of all of the above. Just setting the background-color directly in the highlight-cell class is a kind of brute force way to achieve what you want because it does not take all these other subtleties into account and just overrides them, so a cell which has been highlighted using this style always looks the same no matter what temporary css psuedo-class state has been applied to it.

真的很好,但是更好的解决方案会根据伪类的状态对突出显示的单元格进行不同的颜色。这是一个相当棘手的事情,虽然,你可以浪费很多时间玩各种状态和CSS选择器组合,试图获得漂亮的变化亮点。总而言之,对于这个例子来说,对我来说似乎不值得付出额外的努力,虽然这可能对你有用。

It's fine really, but a nicer solution would color the highlighted cell differently depending on psuedo-class states. That is quite a tricky thing to do though and you could waste a lot of time playing around with various states and css selector combinations to try to get the nice changing highlight. In all, for this example it didn't seem worth that extra effort for me, though it may be for you.

测试程序(对于长度和复杂性,对我来说,更容易将风格突出逻辑集成到现有程序中):

Test program (apologies for length and complexity of this, it was just easier for me to integrate the style highlighting logic into an existing program):

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();
    }
  }
}

这篇关于在JavaFX中有两种颜色的背景?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆