This discussion is archived
2 Replies Latest reply: Mar 5, 2013 4:51 AM by jaylogan RSS

How to center icon node in TableCell

jaylogan Newbie
Currently Being Moderated
Hello,

I created a table as an example and surprisingly got it (almost) right the second time. However, I am having trouble centering my icon column.

This is a table of colors. My model class is the ColorBlob (see code below)
package tablewithicon;

import javafx.scene.paint.Color;

public class ColorBlob {

   public ColorBlob(String name, Color color)  {
      this.name = name;
      this.color = color;
   }
   
   private String name;

   public String getName()   { return name; }

   private Color color;

   public Color getColor() { return color; }

   @Override
   public String toString() {
      return "ColorBlob{" + "name=" + name + ", color=" + color + '}';
   }
}
-------

I made a ColorDisplay class to hold the code that builds the table. This class holds the TableCell implementation that I think I need for the icon (which is really just a rectangle). But:

1. I cannot get the icon centered.
2. There is an extra column of nothing-ness displayed, even though I only specified 2 columns.
3. I don't understand why so many TableCell objects are being created for my one column of icons. Wouldn't 1 TableCell be enough?

Here is the code for ColorDisplay (and, after that, the framework code to pull it all together)
package tablewithicon;


import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.RectangleBuilder;
import javafx.util.Callback;

public class ColorDisplay
{
   private TableView<ColorBlob> table = new TableView<>();
   private ObservableList<ColorBlob> colors = FXCollections
     .observableArrayList(
       new ColorBlob("Gray", Color.LIGHTGRAY),
       new ColorBlob("Red", Color.RED));

   public ColorDisplay() { fillTable(); }
   
   private void fillTable() {
      table.setItems(colors);

      TableColumn<ColorBlob,String> nameColumn = new TableColumn<>("Name");
      nameColumn.setCellValueFactory(
          new PropertyValueFactory<ColorBlob, String>("name"));
      nameColumn.setPrefWidth(100);

      TableColumn<ColorBlob,Color> colorColumn = new TableColumn<>("Color");
      colorColumn.setCellValueFactory(
         new PropertyValueFactory<ColorBlob, Color>("color"));
      colorColumn.setCellFactory(new ColorCellFactory());
      colorColumn.setPrefWidth(100);

      ObservableList<TableColumn<ColorBlob, ?>> columns = table.getColumns();
      columns.add(nameColumn);
      columns.add(colorColumn);
      // ????????????????????????
      // Why is there a 3rd empty column and how do I get rid of it?
   }

   public static class ColorCell extends TableCell<ColorBlob, Color> {
      Rectangle rect = RectangleBuilder.create()
          .width(20)
          .height(20)
          .build();

      public ColorCell() {
         setGraphic(rect);

//       ????????????????????????
//       How do I get the icon in the center of the table cell?
//       I've tried the following:
         setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
//         setContentDisplay(ContentDisplay.TOP);
//         setContentDisplay(ContentDisplay.CENTER);
//         setText(null);
      }

      @Override
      protected void updateItem(Color color, boolean empty) {
         super.updateItem(color, empty);

         rect.setVisible(!empty);
         
         if (!empty) {
            rect.setFill(color);
         }
      }
   }
   
   public TableView<ColorBlob> getTable() { return table; }

   private static class ColorCellFactory 
      implements Callback<TableColumn<ColorBlob, Color>,
                                    TableCell<ColorBlob, Color>> {
//      private Map<TableColumn<ColorBlob, Color>, TableCell<ColorBlob,Color>>
//             cellMap = new IdentityHashMap<>();
      
      @Override
      public TableCell<ColorBlob, Color> call(TableColumn<ColorBlob, Color> p) {
         return new ColorCell();

//       ????????????????????????
//       Why does it create so many cells? 
//       I thought only one would be needed 
//       but the following code causes problems.

//         TableCell<ColorBlob, Color> cell = cellMap.get(p);
//         
//         if (cell == null)
//         {
//            System.out.println("HEY: " + p);
//            cell = new ColorCell();
//            cellMap.put(p, cell);
//         }
//         else
//         {
//            System.out.println("ALREADY THERE!");
//         }
//         return cell;
      }
   }
}
--------------

Main class:
package tablewithicon;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class TableWithIcon extends Application
{
   
   @Override
   public void start(Stage primaryStage)
   {
      ColorDisplay colorDisplay = new ColorDisplay();
      StackPane root = new StackPane();
      root.getChildren().add(colorDisplay.getTable());
      
      Scene scene = new Scene(root, 300, 250);
      
      primaryStage.setTitle("Hello World!");
      primaryStage.setScene(scene);
      primaryStage.show();
   }

   public static void main(String[] args)
   {
      launch(args);
   }
}
Again, my questions are:

1. How do I center the icon in my "Color" column?
2. How do I get rid of the extra blank column?
3. Why is one TableCell object not enough to populate the "Color" column? (optional)


Thank you so much for taking the time to read this.

Edited by: jaylogan on Mar 4, 2013 12:56 AM
  • 1. Re: How to center icon node in TableCell
    shakir.gusaroff Expert
    Currently Being Moderated
    1. How do I center the icon in my "Color" column?
    It might not be the best approach. You can find a better solution.
       if (!empty) {
                rect.setTranslateX(35);
                  
                rect.setFill(color);
             }
    2. How do I get rid of the extra blank column?
             tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);     
  • 2. Re: How to center icon node in TableCell
    jaylogan Newbie
    Currently Being Moderated
    Thank you, shakir!

    Based on your answer, I used the width property of the TableCell to center my icon. I still don't know why so many of them are created but, unless there is a better way to center, I am happy with this solution.

    For anyone who is interested, here is my updated ColorCell constructor:
          public ColorCell() {
             setGraphic(rect);
             setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
             
    //       ????????????????????????
    //       How do I get the icon in the center of the table cell?
    //       Adjust icon's translateX in accordance with the cell's width.
             widthProperty().addListener(new ChangeListener<Number>() {
                @Override public void changed(ObservableValue<? extends Number> ov,
                                    Number oldWidth,
                                    Number newWidth) {
                   if (rect.isVisible()) {
                      rect.setTranslateX((newWidth.doubleValue() / 2) 
                                                  - (rect.getWidth() / 2));
                   }
                }
             });
          }

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points