javafxgridpanejavafx-css

How to style the GridPane using CSS in JavaFx


I'm new in JavaFx. I have a GridPane created in FXML. I want to style that GridPane as the following image. I have tried with the following answers and tried with more CSS elements. But none of these helped me to do this.

JavaFX CSS class for GridPane, VBox, VBox

Center children in GridPane using CSS

Adding borders to GridPane JavaFX

And also am I using a wrong approach? Can I achieve this using GridPane or will the TableView is easy to this?

Table Image


Solution

  • I think you can use a TableView control. You can use the following code to start with:

    Controller Class:

    package sample;
    
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.TableCell;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableView;
    import javafx.scene.control.cell.PropertyValueFactory;
    import javafx.scene.image.Image;
    import javafx.scene.image.ImageView;
    
    import java.net.URL;
    import java.time.Duration;
    import java.time.LocalDate;
    import java.time.LocalTime;
    import java.time.format.DateTimeFormatter;
    import java.util.ResourceBundle;
    
    public class Controller implements Initializable {
    
        @FXML
        private TableView<Project>
                projectTableView;
        @FXML
        private TableColumn<Project, String>
                projeNameColumn;
        @FXML
        private TableColumn<Project, LocalDate>
                dateColumn;
        @FXML
        private TableColumn<Project, LocalTime>
                startTimeColumn,
                stopTimeColumn;
        @FXML
        private TableColumn<Project, Duration>
                durationColumn;
    
        private ObservableList<Project> projectList = FXCollections.observableArrayList();
    
        @Override
        public void initialize(URL location, ResourceBundle resources) {
    
            projectList.addAll(
                    new Project("Landing page Design",
                            LocalDate.of(2019, 5, 21),
                            LocalTime.of(13, 10),
                            LocalTime.of(21, 20, 37)),
                    new Project("Mobile App",
                            LocalDate.of(2019, 5, 21),
                            LocalTime.of(12, 0),
                            LocalTime.of(20, 0)),
                    new Project("UI/UX",
                            LocalDate.of(2019, 5, 21),
                            LocalTime.of(13, 10),
                            LocalTime.of(13, 20, 37)),
                    new Project("Website/apps",
                            LocalDate.of(2019, 5, 21),
                            LocalTime.of(13, 11),
                            LocalTime.of(21, 0, 37)),
                    new Project("Branding",
                            LocalDate.of(2019, 5, 21),
                            LocalTime.of(13, 10),
                            LocalTime.of(13, 20, 37))
            );
    
            projectTableView.setItems(projectList);
    
            projeNameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
            projeNameColumn.setCellFactory(tc -> {
                final Image image = new Image(getClass().getResource("image.png").toString());
                return new TableCell<Project, String>() {
                    private ImageView imageView = new ImageView();
    
                    @Override
                    protected void updateItem(String item, boolean empty) {
                        super.updateItem(item, empty);
                        if (item == null || empty)
                            setGraphic(null);
                        else {
                            imageView.setImage(image);
                            imageView.setPreserveRatio(true);
                            imageView.setFitHeight(35);
                            setGraphic(imageView);
                            setText(item);
                        }
                    }
                };
            });
    
            dateColumn.setCellValueFactory(new PropertyValueFactory("date"));
            dateColumn.setCellFactory((TableColumn<Project, LocalDate> column) -> new TableCell<Project, LocalDate>() {
                protected void updateItem(LocalDate item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item == null || empty)
                        setText(null);
                    else
                        setText(DateTimeFormatter.ofPattern("MMM dd, yyyy").format(item));
                }
            });
    
            startTimeColumn.setCellValueFactory(new PropertyValueFactory("startTime"));
            startTimeColumn.setCellFactory((TableColumn<Project, LocalTime> column) -> new TableCell<Project, LocalTime>() {
                protected void updateItem(LocalTime item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item == null || empty)
                        setText(null);
                    else
                        setText(DateTimeFormatter.ofPattern("hh:mm a").format(item));
                }
            });
    
            stopTimeColumn.setCellValueFactory(new PropertyValueFactory("stopTime"));
            stopTimeColumn.setCellFactory((TableColumn<Project, LocalTime> column) -> new TableCell<Project, LocalTime>() {
                protected void updateItem(LocalTime item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item == null || empty)
                        setText(null);
                    else
                        setText(DateTimeFormatter.ofPattern("hh:mm a").format(item));
                }
            });
    
            durationColumn.setCellValueFactory(new PropertyValueFactory("duration"));
            durationColumn.setCellFactory((TableColumn<Project, Duration> column) -> new TableCell<Project, Duration>() {
                protected void updateItem(Duration item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item == null || empty) {
                        setText(null);
                    } else {
                        int s = (int) item.getSeconds();
                        int hours = s / 3600;
                        int minutes = (s % 3600) / 60;
                        int seconds = (s % 60);
                        setText(String.format("%02d:%02d:%02d", hours, minutes, seconds));
                    }
                }
            });
        }
    }
    

    Project Class:

    package sample;
    
    import javafx.beans.property.ObjectProperty;
    import javafx.beans.property.SimpleObjectProperty;
    import javafx.beans.property.SimpleStringProperty;
    
    import java.time.Duration;
    import java.time.LocalDate;
    import java.time.LocalTime;
    
    public class Project {
    
        private final SimpleStringProperty name;
        private final ObjectProperty<LocalDate> date;
        private final ObjectProperty<LocalTime> startTime, stopTime;
        private final ObjectProperty<Duration> duration;
    
        public Project(String name, LocalDate date, LocalTime startTime, LocalTime stopTime) {
            this.name = new SimpleStringProperty(name);
            this.date = new SimpleObjectProperty<>(date);
            this.startTime = new SimpleObjectProperty<>(startTime);
            this.stopTime = new SimpleObjectProperty<>(stopTime);
            this.duration = new SimpleObjectProperty<>(Duration.between(startTime, stopTime));
        }
    
        public String getName() {
            return name.get();
        }
    
        public SimpleStringProperty nameProperty() {
            return name;
        }
    
        public void setName(String name) {
            this.name.set(name);
        }
    
        public LocalDate getDate() {
            return date.get();
        }
    
        public ObjectProperty<LocalDate> dateProperty() {
            return date;
        }
    
        public void setDate(LocalDate date) {
            this.date.set(date);
        }
    
        public LocalTime getStartTime() {
            return startTime.get();
        }
    
        public ObjectProperty<LocalTime> startTimeProperty() {
            return startTime;
        }
    
        public void setStartTime(LocalTime startTime) {
            this.startTime.set(startTime);
        }
    
        public LocalTime getStopTime() {
            return stopTime.get();
        }
    
        public ObjectProperty<LocalTime> stopTimeProperty() {
            return stopTime;
        }
    
        public void setStopTime(LocalTime stopTime) {
            this.stopTime.set(stopTime);
        }
    
        public Duration getDuration() {
            return duration.get();
        }
    
        public ObjectProperty<Duration> durationProperty() {
            return duration;
        }
    
        public void setDuration(Duration duration) {
            this.duration.set(duration);
        }
    }
    

    FXML File:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.TableColumn?>
    <?import javafx.scene.control.TableView?>
    
    <TableView fx:id="projectTableView" stylesheets="@styling.css" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/11.0.1" fx:controller="sample.Controller">
      <columns>
        <TableColumn id="first-column" fx:id="projeNameColumn" prefWidth="144.0" style="-fx-alignment: center-left;" text="Project" />
        <TableColumn fx:id="dateColumn" prefWidth="96.0" style="-fx-alignment: center;" text="Date" />
          <TableColumn fx:id="startTimeColumn" prefWidth="75.0" style="-fx-alignment: center;" text="Start Time" />
          <TableColumn fx:id="stopTimeColumn" prefWidth="75.0" style="-fx-alignment: center;" text="Stop Time" />
          <TableColumn fx:id="durationColumn" prefWidth="75.0" style="-fx-alignment: center;" text="Duration" />
      </columns>
       <columnResizePolicy>
          <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
       </columnResizePolicy>
    </TableView>
    

    CSS File:

    .table-view .column-header,
    .table-view .column-header-background .filler {
        -fx-background-color: #F9F9F9;
    }
    
    .table-view .column-header {
        -fx-cell-size: 35;
        -fx-border-width: 0.25 0.25 1 0.25;
        -fx-border-color: #EDEDED;
    }
    
    .table-view .column-header .label{
       -fx-padding: 10 0 10 0;
    }
    
    .table-view .cell{
        -fx-cell-size: 35;
    }
    

    Preview:

    enter image description here