JavaFX, TableView - это HashMapили HashMapрешение моей проблемы - PullRequest
0 голосов
/ 19 сентября 2018

Я сейчас на распутье.У меня проблема с окраской в ​​ячейках TableView<Person>. У меня есть 3 столбца: firstName, lastName, and the Days Column (что на самом деле 60 столбцов, представляющих следующие 60 дней с сегодняшнего дня).Каждый Person будет чем-то заниматься в эти дни под названием «events» (максимум 1 событие в день с startDate и endDate).Поэтому каждый человек может иметь до 60 событий, когда я читаю их из файла XML.Вот иллюстрация, чтобы проиллюстрировать то, что я имею в виду.

Планировщик

Это класс Person

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import stack.Event;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;


public class Person{
private StringProperty name;
private StringProperty last;
private String group;
private ArrayList<Event> events;
static ArrayList<String> strDays = new ArrayList<String>();

public ArrayList<Event> getEvents() {
    return events;
}

public void setEvents(ArrayList<Event> events) {
    this.events = new ArrayList<>(events);
}

public String getName() {
return name.get();
}

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

public StringProperty nameProperty(){
return name;
}

public String getLast() {
return last.get();
}

public void setLast(String last) {
this.last.set(last);
}

public StringProperty lastProperty(){
return last;
}

public String getGroups() {
return group;
}

public void setGroups(String group) {
this.group = group;
}
public Person(String name, String last, String group, ArrayList<Event> events){
    this.name = new SimpleStringProperty(name);
    this.last = new SimpleStringProperty(last);
    this.group = group;
    this.events = new ArrayList<Event>(events);
}
public static void print(){
Date current = new Date(); //current first date 
SimpleDateFormat ft = new SimpleDateFormat("yyyy\n MM/dd\n E"); //format wanted
ArrayList<Date> dates = new ArrayList<Date>(); 

Calendar cal = Calendar.getInstance();
cal.setTime(current);
cal.add(Calendar.DATE, 60); //setting the tableView end date

Date startDate = current;
Date endDate = cal.getTime();

Calendar c1 = DateToCalendar(startDate);
Calendar c2 = DateToCalendar(endDate);  

//this generates all the dates between the start date and end date
while (!areEqualDate(c1, c2)){
    ft.format(c1.getTime());
    dates.add(c1.getTime());
    c1.add(Calendar.DAY_OF_YEAR,1);
}

    //this formats the dates
    for (int i = 0; i < dates.size(); i++){
        strDays.add(i, ft.format(dates.get(i)));
        }

    }


private static boolean areEqualDate(Calendar c1, Calendar c2) {
if (c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR)) 
    return false; 
if (c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH)) 
    return false; 
if (c1.get(Calendar.DAY_OF_YEAR) != c2.get(Calendar.DAY_OF_YEAR)) 
    return false; 

return true;
}

private static Calendar DateToCalendar(Date startDate) {
Calendar cal = Calendar.getInstance();
cal.setTime(startDate);
return cal;
}
}

Класс события

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

public class Event {

    private String event;
    private String startDate;
    private String endDate;

public String getStartDate() {
    return startDate;
}

public void setStartDate(String startDate) {
    this.startDate = startDate;
}

public String getEndDate() {
    return endDate;
}

public void setEndDate(String endDate) {
    this.endDate = endDate;
}

public Event(){
    this.event= "";
    this.startDate = "";
    this.endDate = "";
}

public Event(String event, String startDate, String endDate){
    this.event = event;
    this.startDate = startDate;
    this.endDate = endDate;
}

public String getEvent() {
    return event;
}

public void setEvent(String event) {
    this.event = event;
}       

}

Мой класс sample.fxml, имя пакета моего проекта: стек

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.control.ChoiceBox?>
<?import java.lang.String?>
<?import javafx.collections.FXCollections?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.cell.*?> 
<?import javafx.collections.*?> 
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.SeparatorMenuItem?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.control.ScrollBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.CheckBox?> 

<BorderPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml"
  fx:controller="stack.Controller" fx:id="container">
   <center>
        <GridPane alignment="CENTER">
            <padding>
                <Insets top="40" left="20" bottom="20" right="20"></Insets>
            </padding>
            <?language javascript?>
            <Label fx:id="title" text="Scheduler" alignment="CENTER" GridPane.columnIndex="0" GridPane.rowIndex="0"></Label>
            <TableView fx:id="table" GridPane.columnIndex="0" GridPane.rowIndex="2" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS" editable="true">
                <columnResizePolicy>
                    <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
                </columnResizePolicy>
                <columns>
                        <TableColumn fx:id="firstColumn" text="First Name" minWidth="100" maxWidth="100">
                            <cellValueFactory>
                                <PropertyValueFactory property="name"/>
                            </cellValueFactory>
                        </TableColumn>
                        <TableColumn fx:id="secondColumn" text="Last Name" minWidth="100" maxWidth="120">
                            <cellValueFactory>
                                <PropertyValueFactory property="last" />
                            </cellValueFactory>
                        </TableColumn>
                                </columns>
            </TableView>
                <fx:script>          
                    table.getSelectionModel().setCellSelectionEnabled(true);
                    table.getSelectionModel().setSelectionMode(javafx.scene.control.SelectionMode.MULTIPLE);
                </fx:script>
        </GridPane>
    </center>
 </BorderPane>

Основной класс

import javax.print.DocFlavor.URL;

import javafx.application.*;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.MenuItem;
import javafx.scene.image.Image;

public class main extends Application {       
    public Scene theme;

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        try {
            Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));               
            primaryStage.setTitle("Stack");
            Scene scene = new Scene(root, 800, 650); 
            primaryStage.setScene(scene);
            primaryStage.show();    
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

Мой код неправильный, ноЯ понимаю, почему он делает то, что делает.это то, что у меня есть в настоящее время в моем классе контроллеров

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import javafx.application.Platform;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.util.Callback;

public class Controller implements Initializable {

    public TableView<Person> table = new TableView<>();
    public TableColumn<Person, String> firstColumn, secondColumn, days;
    public TableColumn[] tablecols;
    //public TableColumn<Person, Event> days;
    int count = 0;
    //TempTestClass test = new TempTestClass();
    private  String current = "";
    ArrayList<String> dayArray = new ArrayList<String>();

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        Person.print();

        dayArray = new ArrayList<String>(Person.strDays);

        tablecols = new TableColumn[dayArray.size()];
        System.out.println("tablecols size: " + tablecols.length);
        String start = "";
        //in each day for the next 60 days
        for (int i = 0; i < tablecols.length; i++){
            days = new TableColumn<>(dayArray.get(i));
            days.setText(dayArray.get(i));
            days.setMinWidth(55);

            table.getColumns().add(days);

            current = dayArray.get(i);
            //days.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getEvents().toString()));
            //days.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getEvents().get(0).getEvent()));
            for (Person p:getPerson()){           
                if (p.getEvents().size() != 0){ 
                    for (int j = 0; j < p.getEvents().size(); j++){
                        start = p.getEvents().get(j).getStartDate(); 
                        String sub = start.substring(0, 5);

                        // I think we're good here, it gets all the valid days that there's at least one event on
                        if (current.contains(sub)){
                            System.out.println(sub);
                            specific(); 
                        }
                    }
                } } }

        /*These two do not work here*/
        //specific();
        //days.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getEvents().get(0).getEvent().toString()));                
        table.setItems(getPerson());
        table.setEditable(true);       
        table.setStyle("-fx-selection-bar: grey;"); //default cell color  
    }    
/*******************************************************************************************************************************************************************************************************/    
/*******************************************************************************************************************************************************************************************************/    


public void specific(){     //loops through each column?
    days.setCellFactory(new Callback<TableColumn<Person, String>, 
        TableCell<Person, String>>(){
            @Override
            public TableCell<Person, String> call(
                    TableColumn<Person, String> param){
             return new TableCell<Person, String>(){
               @Override
               protected void updateItem(String item, boolean empty){
                super.updateItem(item, empty);
                    if (empty){ //item is null, meaning there's nothing there?
                        setText(null);
                        setGraphic(null);
                    } else {
                        int currentIndex = indexProperty()
                            .getValue() < 0 ? 0
                            : indexProperty().getValue();               
                            ArrayList<Event> type = param //basically person.getEvents()
                            .getTableView().getItems()
                            .get(currentIndex).getEvents();
                            Person person = getTableView().getItems().get(currentIndex);

                        for (int i = 0; i < type.size(); i++){
                            String task = type.get(i).getEvent();
                            /*String day = type.get(i).getStartDate();
                            String sub = day.substring(0, 5);*/
                        if (type.get(1).getEvent().equals("International Travel")){
                            setStyle("-fx-background-color: orange"); 
                            setText(task);
                        }
                        if (type.get(i).getEvent().equals("PTO")){
                            setStyle("-fx-background-color: green"); 
                        setText(task);
                        }  
                        else{
                           setStyle(""); //invisible column but still "filled in"
                           setText(task);
                        }
                       }                    
                      }
                    };
                };
          }
    });
    }

public ObservableList<Person> getPerson(){
        ObservableList<Person> person = FXCollections.observableArrayList();

     ArrayList<Event> eventArray = new ArrayList<Event>();
     eventArray.add(new Event("International Travel", "09/22/2018", "09/22/2018"));
            eventArray.add(new Event("International Travel", "09/30/2018", "09/30/2018"));
            eventArray.add(new Event("PTO", "10/02/2018", "10/02/2018"));
     ArrayList<Event> diffArray = new ArrayList<Event>();
            diffArray.add(new Event("Personal", "09/22/2018", "09/22/2018"));
            diffArray.add(new Event("PTO", "09/30/2018", "09/30/2018"));
            diffArray.add(new Event("PTO", "10/02/2018", "10/02/2018"));
        person.add(new Person("John", "Smith", "GroupA", eventArray));
        person.add(new Person("Karen", "O", "GroupA", eventArray));
        person.add(new Person("Jane", "Doe", "GroupB", diffArray));
        person.add(new Person("Mike", "Johnson", "GroupA", eventArray));
        person.add(new Person("Dukes", "Clan", "GroupB", diffArray));

          return person;        
    }
}

Так что в основном то, что происходит с приведенным выше полным кодом Compilable , - это если Dukes имеет события 09/22, 09/30,и 10/02, которые event Personal только 22-го числа, и PTO в другие дни 30-го и 2-го.09/22 day column будет синим, потому что cellFactory будет смотреть на события, которые есть у Герцогов (которых 3) в этой клетке, каждой клетки, принадлежащей Герцогам, и затем будет видеть, что "О, она делаетв массиве событий есть событие PTO, поэтому давайте сделаем всю ячейку синей ".Дневные столбцы важны для меня, и я подумал о том, чтобы поставить что-то вроде (If PTO && PTO.startDay.equals(dayColumn.getText)), но это будет некрасиво и все равно не будет работать точно.Я не знаю, как быть гибким с этим.Я могу только жестко закодировать его, чтобы он выглядел как то, что я хочу, но это плохая логика, мой код - плохая логика, поэтому я спрашиваю, является ли Hashmap подходом перед тем, как пройти этот маршрут, или есть простая реализацияили что-то я пропускаю?

Нужен ли мне один или два HashMap?потому что я думаю, что должен быть способ нанести на карту человека, и день через событие.

Примерно так Макет

Я искал другие ссылки и думаю, что это можно сделать, но я просто хотел узнать, нужен ли хэш-файлчтобы выполнить то, что я хочу, а также о том, что я делаю неправильно.

Спасибо.

...