2017-02-12 1 views
0

Dans un JavaFx/TableView, est-il possible d'obtenir un TableCell avec plusieurs couleurs pour le texte? J'ai essayé le code suivant en utilisant 'Texte' où chaque caractère serait en ROUGE/BLEU/ROUGE/BLEU ... mais les cellules restent noires.Jfx/TableColumn.setCellFactory avec plusieurs couleurs en une TableCell

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

Y at-il un moyen d'y parvenir? Merci.

Répondre

1

Créez un TextFlow pour contenir les instances Text et définissez-le comme graphique de la cellule. Notez également que vous avez un bug (qui apparaîtra si vous supprimez des éléments de la liste de la table, ou éventuellement si vous faites défiler): vous devez effacer le texte et le graphique si la cellule est vide.

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

Voici un 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