-1

I currently have a working table, but I want to change the SimpleIntegerProperty "status" to a square. Basically, I want the all the "1" to become squares. This is the code that I made:

public ObservableList<PumpSites> list = FXCollections.observableArrayList(
        new PumpSites (1, "Canduman"),
        new PumpSites (1, "Cubacub"),
        new PumpSites (1, "Liloan"),
        new PumpSites (1, "Talamban"),
        new PumpSites (1, "Tisa")
        );

status.setCellValueFactory(new PropertyValueFactory<PumpSites, Integer>("status"));
ps.setCellValueFactory(new PropertyValueFactory<PumpSites, String>("ps"));
table.setItems(list);

public class PumpSites {
    private final SimpleIntegerProperty status;
    private final SimpleStringProperty ps;

    public PumpSites(Integer status, String ps){
        super();
        this.status = new SimpleIntegerProperty(status);
        this.ps = new SimpleStringProperty(ps);
    }

    public Integer getStatus() {
        return status.get();
    }

    public String getPs() {
        return ps.get();
    }

}

How can I do that?

Guillaume S
  • 1,462
  • 2
  • 19
  • 31
  • 2
    What have you tried so far? What specifically are you having trouble with? You're code has only slightly changed since your [last question](https://stackoverflow.com/questions/52088396/javafx-dynamic-tableview-from-url-json). Hint: Use a [`cellFactory`](https://docs.oracle.com/javase/10/docs/api/javafx/scene/control/TableColumn.html#cellFactoryProperty) and override [`updateItem`](https://docs.oracle.com/javase/10/docs/api/javafx/scene/control/Cell.html#updateItem(T,boolean)). – Slaw Aug 30 '18 at 09:06
  • I managed to make the dynamic table work by replacing the "status" with variables and placing them inside a task to be run every 5 mins. I have read that shapes can be created so I decided to just use shapes instead of images, but I'm having trouble with placing them inside the cell of a tableview. I'm quite new to javafx so I'm just getting ideas from what I can get here in stackoverflow and I was hoping to get an answer that can be understood by newbies like me. – TheChosenWan Aug 30 '18 at 09:12
  • For the square, does it still have the behavior described in your previous question (changes color based on status)? – Slaw Aug 30 '18 at 09:25
  • Yes, it still has that behavior, but I think setTextFill can be the solution for that. – TheChosenWan Aug 30 '18 at 09:29
  • 2
    Please provide a [mcve] that demonstrates the problem. I'm really really fed up with you forcing us into guessing games ... again! – kleopatra Aug 30 '18 at 09:47
  • Based on both your previous question and this question, see [this example](https://gist.github.com/tkslaw/6548216382e23a19f35fbfdee1b56c99). – Slaw Aug 30 '18 at 11:14
  • Thanks! @Slaw I got an idea from your example, and made it finally work! – TheChosenWan Aug 31 '18 at 00:54

1 Answers1

-3

Instead of the IntegerProperty use an ObjectProperty<Shape> and @Override in a TableCell the updateItem(item,empty) method to display the shape

Here is the working code:

public class Controller implements Initializable {

    @FXML
    private TableView<Model> tableView;
    @FXML
    private TableColumn<Model, Shape> shapeColumn;
    @FXML
    private TableColumn<Model, String> textColumn;

    @Override

    public void initialize(URL location, ResourceBundle resources) {
        shapeColumn.setCellValueFactory(data -> data.getValue().shapeProperty());
        textColumn.setCellValueFactory(data -> data.getValue().textProperty());

        shapeColumn.setCellFactory(cell -> new ShapeTableCell());

        ObservableList<Model> items = FXCollections.observableArrayList();

        items.add(new Model(new Circle(10), "Circle"));
        items.add(new Model(new Rectangle(20, 20), "Rectangle"));

        tableView.setItems(items);
    }

    private class Model {
        // Instead of shape you can use anything, which inherits from Node,
        // like an ImageView to display a specific image
        private ObjectProperty<Shape> shape;
        private StringProperty text;

        public Model(Shape shape, String text) {
            this.shape = new SimpleObjectProperty<>(shape);
            this.text = new SimpleStringProperty(text);
        }

        public Shape getShape() {
            return shape.get();
        }

        public ObjectProperty<Shape> shapeProperty() {
            return shape;
        }

        public String getText() {
            return text.get();
        }

        public StringProperty textProperty() {
            return text;
        }
    }

    private class ShapeTableCell extends TableCell<Model, Shape> {
        @Override
        protected void updateItem(Shape item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setGraphic(null);
            } else {
                setGraphic(item);
            }
        }
    }

}

Hint: Try to avoid using PropertyValueFactory and use Callback instead. PVF uses reflection which is never the best solution when you have an alternative one.

Sunflame
  • 2,993
  • 4
  • 24
  • 48
  • 4
    You should try to avoid having UI code (`Shape`) in model classes. – Slaw Aug 30 '18 at 09:24
  • Thank you so much! I was hoping for this kind of answer. I will try this later, and comment here if I made it work. – TheChosenWan Aug 30 '18 at 09:24
  • @Slaw if you have an UI element as "Model" what would you do? – Sunflame Aug 30 '18 at 09:25
  • I agree, and even if he replaces the `Shape` to an Image, he can use a path to the Image and let the `TableCell` handle the graphic part, but here it is about shapes so I put `Shape` there . – Sunflame Aug 30 '18 at 09:34
  • 3
    *"If the item is 1, it should be displayed as square"* doesn't sound like a) A shape is a "natural" part of the model b) there's a need to display arbitrary `Shape`s. Using a property of type `Shape` seems like a quick and dirty fix. Furthermore there's no need for a custom `cellFactory`, if you do use a property of type `Shape`. The default cell factory produces cell putting the item in the `graphic` property, if it's a `Node`. – fabian Aug 30 '18 at 09:49
  • 1
    sorry, having ui elements in the model is plain wrong - the OP is unclear about what she needs, so jumping to conclusions with suboptimal examples is ... suboptimal ;) -1 until you change that .. – kleopatra Aug 30 '18 at 09:50
  • Thanks @fabian to pointing on that, indeed the custom cell part is an overkill. Then if there is a default implementation of handling `Node`s from the Model, why is it wrong? If I want to use a `Shape` what would be the correct way of implementation? – Sunflame Aug 30 '18 at 10:03
  • you introduce the node for wrong reasons, that's the error. If you really have a model that contains a shape you could use it - but then there wouldn't be any need for a custom cell implementation (due to the over-engineered default implementation). – kleopatra Aug 31 '18 at 08:38
  • @kleopatra Yes you are right. Maybe I misunderstood the question that is why I put the `Shape` there. Thanks both you and @fabian for the explanations. – Sunflame Aug 31 '18 at 13:08