wan1796
wan1796

Reputation: 1

How to add as many instances of a Pane defined in a separate fxml file as there are entries in a HashMap into a ScrollPane?

The Pane (pane - fxml: deadline-example.fxml) has elements (Labels & a pie chart) that are set based on a specific instance of the Deadline class. I also have another scene (deadline-menu.fxml) that contains a ScrollPane. The idea is that there is a hashmap (DLList) containing X elements of the Deadline class along with its id. The solution logic that I am envisioning is:

have a for-each loop iterate over each element of DLList -> use the attribute of the particular Deadline instance to set the labels of pane -> store the pane in a data structure -> display the instances in the ScrollPane of deadline-menu.fxml using the data structure

The key here is that the number of Deadline instances in DLList is variable, so I can't predefine a number of Panes for use. My initial idea is to define each Pane and store the pane into a separate hashmap (DLPaneList), and then pass it back to DLMenuController.java to finally display its contents onto the ScrollPane and that has failed. I want to know the issues with my approach, as well as another approach that I can use. Thanks.

deadline-example.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.chart.PieChart?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.shape.Rectangle?>
<?import javafx.scene.text.Font?>

<Pane fx:id="pane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="280.0" prefWidth="900.0" xmlns="http://javafx.com/javafx/20.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <Rectangle arcHeight="5.0" arcWidth="5.0" fill="WHITE" height="247.0" layoutX="27.0" layoutY="26.0" stroke="BLACK" strokeType="INSIDE" width="867.0" />
      <Label fx:id="name" layoutX="37.0" layoutY="34.0" prefHeight="45.0" prefWidth="298.0" text="name">
         <font>
            <Font size="30.0" />
         </font>
      </Label>
      <Label fx:id="onTimeLabel" layoutX="37.0" layoutY="95.0" prefHeight="45.0" prefWidth="298.0" text="On time:">
         <font>
            <Font size="20.0" />
         </font>
      </Label>
      <Label fx:id="lateLabel" layoutX="37.0" layoutY="140.0" prefHeight="45.0" prefWidth="298.0" text="Late:">
         <font>
            <Font size="20.0" />
         </font>
      </Label>
      <Label fx:id="naLabel" layoutX="37.0" layoutY="186.0" prefHeight="45.0" prefWidth="298.0" text="N/A:">
         <font>
            <Font size="20.0" />
         </font>
      </Label>
      <PieChart fx:id="deadlineChart" layoutX="463.0" layoutY="38.0" prefHeight="223.0" prefWidth="417.0" />
   </children>
</Pane>

deadline-menu.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>

<Pane fx:id="DLMenuPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="540.0" prefWidth="960.0" xmlns="http://javafx.com/javafx/20.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.ia_real.DLMenuController">
   <children>
      <ChoiceBox fx:id="timeDropDown" layoutX="20.0" layoutY="22.0" prefWidth="150.0" style="-fx-background-color: lightgray;" />
      <ChoiceBox fx:id="limitDropDown" layoutX="185.0" layoutY="22.0" prefWidth="150.0" style="-fx-background-color: lightgray;" />
      <ScrollPane fx:id="scrollPane" layoutY="70.0" prefHeight="471.0" prefWidth="960.0">
         <content>
            <VBox fx:id="DLVBox" prefHeight="468.0" prefWidth="957.0" />
         </content>
      </ScrollPane>
   </children>
</Pane>

DLMenuController.java: (controller of deadline-menu.fxml)

package com.example.ia_real;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.*;

import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import javafx.util.*;
import org.apache.poi.*;

public class DLMenuController extends Controller{
    @FXML
    public Pane DLMenuPane;
    @FXML
    private ChoiceBox<String> timeDropDown;
    ObservableList<String> timeList = FXCollections.observableArrayList("Recent","Chronological");
    @FXML
    private ChoiceBox<String> limitDropDown;
    ObservableList<String> limitList = FXCollections.observableArrayList("All","Subject","Term");
    @FXML
    private VBox DLVBox;

    @FXML
    private ScrollPane scrollPane;


    public DLMenuController() throws IOException {}

    public void init() throws IOException {
        timeDropDown.setItems(timeList);
        timeDropDown.setValue("Recent");

        limitDropDown.setItems(limitList);
        limitDropDown.setValue("All");

        DeadlineController dlcontroller = new DeadlineController();
        HashMap<Integer, Pane> paneList = dlcontroller.createPaneList();

        for (Map.Entry<Integer, Pane> entry : paneList.entrySet()) {
            FXMLLoader loaderMenu = new FXMLLoader(Controller.class.getResource("deadline-exaample.fxml"));
            Parent root = loaderMenu.load();
            DLVBox.getChildren().add(root);
        }
    }
}

DeadlineController.java: (Controller of deadline-example.fxml)

package com.example.ia_real;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javafx.animation.*;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class DeadlineController {
    @FXML
    public Pane pane;
    @FXML
    private Label name;
    @FXML
    private Label onTimeLabel;
    @FXML
    private Label lateLabel;
    @FXML
    private Label naLabel;
    @FXML
    private PieChart deadlineChart;

    private String path;
    private File sheet;

    public DeadlineController() throws IOException {}

    public void passPath(String path) {
        this.path = path;
        this.sheet = new File(path);
    }

    Deadline dl = new Deadline(path);
    HashMap<Integer, Deadline> DLList = dl.createDLs();

    public HashMap<Integer, Pane> createPaneList() {
        HashMap<Integer, Pane> DLPaneList = new HashMap<>();
        Controller controller = new Controller();

        for(Map.Entry<Integer, Deadline> entry : DLList.entrySet()) {
            Deadline current = entry.getValue();

            name.setText(current.getName());
            onTimeLabel.setText(String.valueOf(current.getOnTime()));
            lateLabel.setText(String.valueOf(current.getLate()));
            naLabel.setText(String.valueOf(current.getNa()));

            assert current != null;
            controller.setPieChart(current, deadlineChart);
            DLPaneList.put(current.getID(), pane);
        }

        return DLPaneList;
    }


}

Deadline.java:

package com.example.ia_real;
import javafx.fxml.FXML;
import org.apache.poi.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javafx.scene.control.Label;

import java.io.*;
import java.util.HashMap;
import java.util.Objects;

public class Deadline {

    private File sheet;
    private String path;
    private Sheet deadlines;


    private int id;
    private String name;
    private String subject;
    private int onTime;
    private int late;
    private int na;


    public Deadline(String path) throws IOException {
        this.path = path;
        this.sheet = new File(path);
        FileInputStream fisDL = new FileInputStream(sheet);
        Workbook wb = new XSSFWorkbook(fisDL);
        deadlines = wb.getSheetAt(1);

        wb.close();
        fisDL.close();
    }


    public void setID(int id) {
        this.id = id;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public void setName(String name) { this.name = name; }

    public void setDLStats(int col) throws IOException {
        FileInputStream fisDB = new FileInputStream(sheet);
        Workbook wb = new XSSFWorkbook(fisDB);

        String onTimeColor = "00B050";
        String lateColor = "FFFF00";
        String naColor = "FF0000";
        String cellColor;
        int onTime = 0;
        int late = 0;
        int na = 0;

        for (Row row : deadlines) {
            Cell cell = row.getCell(col);
            //CellStyle cellStyle = cell.getCellStyle();
            String yn = cell.getStringCellValue();

            if (yn.equalsIgnoreCase("y")) {
                onTime+=1;
            }
            else if (yn.equalsIgnoreCase("l")) {
                late+=1;
            }
            else if (yn.equalsIgnoreCase("n")) {
                na+=1;
            }


        }
        this.onTime = onTime;
        this.late = late;
        this.na = na;

        wb.close();
        fisDB.close();
    }


    public HashMap<Integer, Deadline> createDLs() throws IOException {
        int col = 2;
        int id = 1;

        HashMap<Integer, Deadline> deadlineMap = new HashMap<>();
        Row row = deadlines.getRow(0);         // gets row w/ index 0 (row 1)
        Cell currentCell = row.getCell(col);      // gets cell w/ index 2 (C1)
        boolean cellEmpty = (currentCell == null || currentCell.getCellType() == CellType.BLANK);

        while (!cellEmpty) {
            //creates new Deadline instance
            Deadline dl = new Deadline(path);
            //sets ID
            dl.setID(id);

            //sets name
            dl.setName(currentCell.getStringCellValue());

            dl.setDLStats(col);
            deadlineMap.put(id, dl);

            col += 1;
            id += 1;
            currentCell = row.getCell(col);
            cellEmpty = (currentCell == null || currentCell.getCellType() == CellType.BLANK);
        }

        return deadlineMap;
    }
    public int getID() {
        return id;
    }

    public int getOnTime() {
        return onTime;
    }

    public int getLate() {
        return late;
    }

    public int getNa() {
        return na;
    }

    public String getName() {
        return name;
    }


}

Stack trace:

C:\Users\PC\.jdks\openjdk-20.0.2\bin\java.exe "-javaagent:D:\_IntelliJ\IntelliJ IDEA Community Edition 2023.1.1\lib\idea_rt.jar=57793:D:\_IntelliJ\IntelliJ IDEA Community Edition 2023.1.1\bin" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath "C:\Users\PC\.m2\repository\org\openjfx\javafx-controls\20\javafx-controls-20.jar;C:\Users\PC\.m2\repository\org\openjfx\javafx-graphics\20\javafx-graphics-20.jar;C:\Users\PC\.m2\repository\org\openjfx\javafx-base\20\javafx-base-20.jar;C:\Users\PC\.m2\repository\org\openjfx\javafx-fxml\20\javafx-fxml-20.jar;C:\Users\PC\.m2\repository\com\github\virtuald\curvesapi\1.07\curvesapi-1.07.jar;D:\Apache POI\poi-bin-5.2.3\ooxml-lib\commons-logging-1.2.jar;D:\Apache POI\poi-bin-5.2.3\ooxml-lib\curvesapi-1.07.jar;D:\Apache POI\poi-bin-5.2.3\ooxml-lib\jakarta.activation-2.0.1.jar;D:\Apache POI\poi-bin-5.2.3\ooxml-lib\jakarta.xml.bind-api-3.0.1.jar;D:\Apache POI\poi-bin-5.2.3\ooxml-lib\slf4j-api-1.7.36.jar;D:\Apache POI\poi-bin-5.2.3\poi-examples-5.2.3.jar;D:\Apache POI\poi-bin-5.2.3\poi-excelant-5.2.3.jar" -p "C:\Users\PC\.m2\repository\org\apache\poi\poi-ooxml-lite\5.2.3\poi-ooxml-lite-5.2.3.jar;D:\Apache POI\poi-bin-5.2.3\poi-ooxml-full-5.2.3.jar;D:\Apache POI\poi-bin-5.2.3\poi-ooxml-lite-5.2.3.jar;C:\Users\PC\.m2\repository\org\apache\poi\poi-ooxml\5.2.3\poi-ooxml-5.2.3.jar;D:\Apache POI\poi-bin-5.2.3\poi-ooxml-5.2.3.jar;C:\Users\PC\.m2\repository\org\openjfx\javafx-graphics\20\javafx-graphics-20-win.jar;C:\Users\PC\.m2\repository\org\openjfx\javafx-fxml\20\javafx-fxml-20-win.jar;C:\Users\PC\.m2\repository\org\apache\logging\log4j\log4j-api\2.18.0\log4j-api-2.18.0.jar;D:\Apache POI\poi-bin-5.2.3\lib\log4j-api-2.18.0.jar;D:\Apache POI\poi-bin-5.2.3\poi-scratchpad-5.2.3.jar;C:\Users\PC\.m2\repository\org\openjfx\javafx-controls\20\javafx-controls-20-win.jar;C:\Users\PC\.m2\repository\org\apache\poi\poi\5.2.3\poi-5.2.3.jar;D:\Apache POI\poi-bin-5.2.3\poi-5.2.3.jar;C:\Users\PC\IdeaProjects\IA_real\target\classes;C:\Users\PC\.m2\repository\org\apache\commons\commons-collections4\4.4\commons-collections4-4.4.jar;D:\Apache POI\poi-bin-5.2.3\lib\commons-collections4-4.4.jar;C:\Users\PC\.m2\repository\org\apache\xmlbeans\xmlbeans\5.1.1\xmlbeans-5.1.1.jar;D:\Apache POI\poi-bin-5.2.3\ooxml-lib\xmlbeans-5.1.1.jar;C:\Users\PC\.m2\repository\commons-io\commons-io\2.11.0\commons-io-2.11.0.jar;D:\Apache POI\poi-bin-5.2.3\lib\commons-io-2.11.0.jar;C:\Users\PC\.m2\repository\commons-codec\commons-codec\1.15\commons-codec-1.15.jar;D:\Apache POI\poi-bin-5.2.3\lib\commons-codec-1.15.jar;C:\Users\PC\.m2\repository\org\openjfx\javafx-base\20\javafx-base-20-win.jar;C:\Users\PC\.m2\repository\org\apache\commons\commons-compress\1.21\commons-compress-1.21.jar;D:\Apache POI\poi-bin-5.2.3\ooxml-lib\commons-compress-1.21.jar;C:\Users\PC\.m2\repository\org\apache\commons\commons-math3\3.6.1\commons-math3-3.6.1.jar;D:\Apache POI\poi-bin-5.2.3\lib\commons-math3-3.6.1.jar;C:\Users\PC\.m2\repository\com\zaxxer\SparseBitSet\1.2\SparseBitSet-1.2.jar;D:\Apache POI\poi-bin-5.2.3\lib\SparseBitSet-1.2.jar" -m com.example.ia_real/com.example.ia_real.Main
No
Sept 11, 2023 8:32:39 PM javafx.fxml.FXMLLoader$ValueElement processValue
WARNING: Loading FXML document with JavaFX API of version 20.0.1 by JavaFX runtime of version 20
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
Sept 11, 2023 8:32:42 PM javafx.fxml.FXMLLoader$ValueElement processValue
WARNING: Loading FXML document with JavaFX API of version 20.0.1 by JavaFX runtime of version 20
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml@20/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1858)
    at javafx.fxml@20/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1726)
    at javafx.base@20/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at javafx.base@20/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:232)
    at javafx.base@20/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:189)
    at javafx.base@20/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.base@20/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at javafx.base@20/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base@20/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base@20/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base@20/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base@20/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base@20/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base@20/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.base@20/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics@20/javafx.scene.Node.fireEvent(Node.java:8944)
    at javafx.controls@20/javafx.scene.control.Button.fire(Button.java:203)
    at javafx.controls@20/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:207)
    at javafx.controls@20/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
    at javafx.base@20/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
    at javafx.base@20/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at javafx.base@20/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:232)
    at javafx.base@20/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:189)
    at javafx.base@20/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.base@20/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at javafx.base@20/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base@20/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base@20/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base@20/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base@20/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base@20/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base@20/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.base@20/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics@20/javafx.scene.Scene$MouseHandler.process(Scene.java:3980)
    at javafx.graphics@20/javafx.scene.Scene.processMouseEvent(Scene.java:1890)
    at javafx.graphics@20/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2704)
    at javafx.graphics@20/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
    at javafx.graphics@20/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
    at javafx.graphics@20/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
    at javafx.graphics@20/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
    at javafx.graphics@20/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
    at javafx.graphics@20/com.sun.glass.ui.View.handleMouseEvent(View.java:551)
    at javafx.graphics@20/com.sun.glass.ui.View.notifyMouse(View.java:937)
    at javafx.graphics@20/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics@20/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:185)
    at java.base/java.lang.Thread.run(Thread.java:1623)
Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:116)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:72)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at javafx.base@20/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:270)
    at javafx.fxml@20/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:84)
    at javafx.fxml@20/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1855)
    ... 46 more
Caused by: java.lang.NullPointerException
    at java.base/java.io.File.<init>(File.java:278)
    at com.example.ia_real/com.example.ia_real.Deadline.<init>(Deadline.java:30)
    at com.example.ia_real/com.example.ia_real.DeadlineController.<init>(DeadlineController.java:50)
    at com.example.ia_real/com.example.ia_real.DLMenuController.init(DLMenuController.java:46)
    at com.example.ia_real/com.example.ia_real.Controller.onViewAllClick(Controller.java:108)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    ... 53 more

Process finished with exit code 0

Upvotes: 0

Views: 75

Answers (1)

James_D
James_D

Reputation: 209340

The basic structure here is to define your DeadlineController class with a

setDeadline(Deadline deadline) { ... }

method, which takes the Deadline instance to be displayed. Anything that depends on the deadline needs to be done as a result of calling that method, and not before. See Passing Parameters JavaFX FXML for more details.

In your code, you have a passPath(String path) method that sets the path (not exactly sure what that is doing). However you have

Deadline dl = new Deadline(path);

as an instance variable, which will be called before there is a chance to call passPath(...). The path variable will be null at that point, and so you get the null pointer exception.

Here is a greatly simplified, but complete, application that demonstrates loading multiple copies of an FXML file with configurable values, dynamically depending on user input:

Deadline.java

package org.jamesd.examples.multiplepanes;

import java.time.LocalDate;

public class Deadline {
    private final String task;
    private final LocalDate dueDate;

    public String getTask() {
        return task;
    }

    public LocalDate getDueDate() {
        return dueDate;
    }

    public Deadline(String task, LocalDate dueDate) {
        this.task = task;
        this.dueDate = dueDate;
    }
}

DeadlineView.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx"
      xmlns:fx="http://javafx.com/fxml"
      fx:controller="org.jamesd.examples.multiplepanes.DeadlineController"
      styleClass="deadline"
      spacing="5">
    <padding><Insets topRightBottomLeft="20"></Insets></padding>
    <Label fx:id="taskLabel"/>
    <Label fx:id="dueDateLabel"/>
</VBox>

DeadlineController.java

package org.jamesd.examples.multiplepanes;

import javafx.fxml.FXML;
import javafx.scene.control.Label;

import java.time.format.DateTimeFormatter;

public class DeadlineController {

    @FXML
    private Label taskLabel;
    @FXML
    private Label dueDateLabel;

    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMMM YYYY");

    private Deadline deadline ;
    public void setDeadline(Deadline deadline) {
        this.deadline = deadline;
        taskLabel.setText(deadline.getTask());
        dueDateLabel.setText(formatter.format(deadline.getDueDate()));
    }
    public Deadline getDeadline() {
        return deadline;
    }
}

Menu.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Spinner?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.TilePane?>
<?import javafx.scene.layout.VBox?>
<BorderPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="org.jamesd.examples.multiplepanes.MenuController"
            >

    <left>
        <VBox spacing="5">
            <padding><Insets topRightBottomLeft="10"/></padding>
            <HBox spacing="5">
                <Label text = "Number of deadlines:"/>
                <Spinner fx:id="numDeadlinesSpinner">

                </Spinner>
            </HBox>
            <Button text="Generate" onAction="#generateDeadlines"/>
        </VBox>
    </left>
    <center>
        <TilePane fx:id="deadlinePane"/>
    </center>
</BorderPane>

MenuController.java

package org.jamesd.examples.multiplepanes;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.layout.TilePane;

import java.io.IOException;
import java.time.LocalDate;
import java.util.Random;

public class MenuController {
    @FXML
    private TilePane deadlinePane ;
    @FXML
    private Spinner<Integer> numDeadlinesSpinner ;

    private final Random rng = new Random();

    @FXML
    private void initialize() {
        numDeadlinesSpinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 10, 5));
    }

    public void generateDeadlines() throws IOException {
        deadlinePane.getChildren().clear();
        int numDeadlines = numDeadlinesSpinner.getValue();
        for (int i = 0 ; i < numDeadlines ; i++) {
            String task = "Task " + (i+1);
            LocalDate dueDate = LocalDate.now().plusDays(rng.nextInt(5));
            Deadline deadline = new Deadline(task, dueDate);

            FXMLLoader loader = new FXMLLoader(DeadlineController.class.getResource("DeadlineView.fxml"));
            Parent deadlineView = loader.load();
            DeadlineController deadlineController = loader.getController();
            deadlineController.setDeadline(deadline);
            deadlinePane.getChildren().add(deadlineView);
        }
    }
}

DeadlineApplication.java

package org.jamesd.examples.multiplepanes;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class DeadlineApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(DeadlineApplication.class.getResource("Menu.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 800, 500);
        stage.setScene(scene);
        stage.show();
    }

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

Upvotes: 2

Related Questions