在一个TableCell中具有多种颜色的Jfx / TableColumn.setCellFactory

时间:2017-02-12 13:14:22

标签: javafx tableview uicolor

在JavaFx / TableView中,是否可以为文本获取具有多种颜色的TableCell?我使用'Text'尝试了以下代码,其中每个字符都是RED / BLUE / RED / BLUE ......但是单元格仍然是黑色。

   (...)
    tableColumn.setCellFactory(tc -> new TableCell<MyObject, String>() { 
        @Override
        protected void updateItem(final String item, boolean empty) {
            super.updateItem(item, empty);
            if(item==null) return;
            this.setText(item);

            final List<Text> L=new ArrayList<>(item.length());
            for(int i=0;i< item.length();++i) {
                final Text txt=new Text(String.valueOf(item.charAt(i)));
                txt.setStroke(i%2==0?Color.RED:Color.BLUE);
                L.add(txt);
                }
            this.getChildren().setAll(L);
        }
    });
 (...)

有没有办法实现这个目标?感谢。

1 个答案:

答案 0 :(得分:1)

创建TextFlow以保存Text个实例并将其设置为单元格的图形。另请注意,您有一个错误(如果从表的列表中删除项目,或者滚动时可能会显而易见):如果单元格为空,则需要清除文本和图形。

tableColumn.setCellFactory(tc -> new TableCell<MyObject, String>() { 

    final TextFlow textFlow = new TextFlow();

    @Override
    protected void updateItem(final String item, boolean empty) {
        super.updateItem(item, empty);
        if(item==null) {
            setText(null);
            setGraphic(null);
            return ;
        }

        this.setText(item);

        final List<Text> L=new ArrayList<>(item.length());
        for(int i=0;i< item.length();++i) {
            final Text txt=new Text(String.valueOf(item.charAt(i)));
            txt.setStroke(i%2==0?Color.RED:Color.BLUE);
            L.add(txt);
        }
        textFlow.getChildren().setAll(L);
        setGraphic(textFlow);
    }
});

这是一个SSCCE:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;

public class TableWithAlternateColorText extends Application {

    private final Random rng = new Random();
    private final String[] bases = "ACGT".split("") ;

    @Override
    public void start(Stage primaryStage) {
        TableView<StringProperty> table = new TableView<>();
        TableColumn<StringProperty, String> col = new TableColumn<>("Sequence");
        col.setCellValueFactory(CellDataFeatures::getValue);
        col.setCellFactory(tc -> new TableCell<StringProperty, String>() { 

            final TextFlow textFlow = new TextFlow();


            @Override
            protected void updateItem(final String item, boolean empty) {
                super.updateItem(item, empty);
                if(item==null) {
                    setText(null);
                    setGraphic(null);
                    return ;
                }

                List<Text> texts = new ArrayList<>();
                for(int i=0;i< item.length();++i) {
                    char base = item.charAt(i);
                    final Text txt=new Text(String.valueOf(base));
                    txt.setStroke(isPyrimidine(base) ? Color.RED : Color.BLUE);
                    texts.add(txt);
                }
                textFlow.getChildren().setAll(texts);

                setGraphic(textFlow);
                setPrefHeight(textFlow.prefHeight(-1));

            }
        });
        table.getColumns().add(col);

        for (int i = 0 ; i < 100 ; i++) {
            table.getItems().add(new SimpleStringProperty(randomSequence(20)));
        }

        primaryStage.setScene(new Scene(table, 600, 600));
        primaryStage.show();
    }

    private boolean isPyrimidine(char base) {
        return base == 'C' || base  == 'T' ;
    }

    private String randomSequence(int seqLength) {
        return rng.ints(seqLength, 0, bases.length)
                .mapToObj(i -> bases[i])
                .collect(Collectors.joining());
    }

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

enter image description here