簡體   English   中英

Javafx:TreeView的域對象

[英]Javafx : Domain objects to TreeView

我的應用程序中有三個域對象,如下所示:

public class Workflow {
  private String name;
  private List<Sheet> sheets;
}

public class Sheet {
  private String name;
  private List<Task> tasks;
}

public class Task {
  private String name;
}

這三個都依賴於工作流程->工作表->任務。 我的目標是構建TreeView,使其看起來如下所示:

-Workflow
|
 - workflow name
 -Sheets
 |
  - sheet name
  - Tasks
  |
   - task name

到目前為止,我已經構建了一個樣本,該樣本的構建比我期望的要少得多,但是它不是通用的,也不是“自動化的”。

public class TreeViewSample extends Application {

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

@Override
public void start(Stage primaryStage) {
    primaryStage.setTitle("Tree View Sample");        

    Workflow w = setup();

    TreeItem<String> rootItem = new TreeItem<String> ("Workflow");
    rootItem.setExpanded(true);

        TreeItem<String> item = new TreeItem<String> (w.getName());
        rootItem.getChildren().add(item);
(...)


    TreeView<String> tree = new TreeView<String> (rootItem);        
    StackPane root = new StackPane();
    root.getChildren().add(tree);
    primaryStage.setScene(new Scene(root, 300, 250));
    primaryStage.show();
}

private Workflow setup(){

    Workflow wflow = new Workflow();
    wflow.setName("wflow name");
    wflow.setSheets(Arrays.asList(new Sheet("sheet name", Arrays.asList(new Task("task name")))));

    return wflow;
}

有人可以建議我如何像我的示例中那樣遞歸地訪問域對象並構建TreeView嗎?

您必須為所有模型(工作流,工作表,任務)創建一個通用Model ,因為所有模型都具有String屬性,因此創建一個模型非常簡單。 假設我們有以下模型:

public class Model {

    private String name;

    public Model(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return getName();
    }
}

class Workflow {
    private String name;
    private List<Sheet> sheets = new ArrayList<>();

    public Workflow(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public List<Sheet> getSheets() {
        return sheets;
    }
}

class Sheet {
    private String name;
    private List<Task> tasks = new ArrayList<>();

    public Sheet(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public List<Task> getTasks() {
        return tasks;
    }
}

class Task {
    private String name;

    public Task(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

我將所有的模型都放在這里,以便更好地查看它們。

我看你不使用任何.fxml在你的應用程序文件,我的是與.fxml我建議你至少分離到分離Main類從Controller類,如:

public class Main extends Application{


    @Override
    public void start(Stage primaryStage) throws Exception {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("View.fxml"));
        AnchorPane pane = loader.load();
        primaryStage.setScene(new Scene(pane,800,600));
        primaryStage.show();
    }

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

然后是Controller類:

public class Controller implements Initializable {

    @FXML
    private TreeView<Model> treeView;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        Workflow workflow = createWorkflow(); // This just sets up the models that you are using.

        // You have to create a root in your case the "Workflow"
        TreeItem<Model> root = new TreeItem<>(new Model(workflow.getName()));
        // The foreach sheet you create a branch
        workflow.getSheets().forEach(sheet -> {
            TreeItem<Model> sheetBranch = new TreeItem<>(new Model(sheet.getName()));
            // Then you have to add each branch to the root
            root.getChildren().add(sheetBranch);
            // Then foreach sheet you create a task item
            sheet.getTasks().forEach(task -> {
                TreeItem<Model> taskItem = new TreeItem<>(new Model(task.getName()));
                // Then you have to add each task to its sheet parent
                sheetBranch.getChildren().add(taskItem);
            });
        });
        // Finally, you set the root for the TreeView. Of course this can be done right after instantiating the root.
        treeView.setRoot(root);
    }

    // ------------------- Setup the model -----------------------

    private Workflow createWorkflow() {
        Workflow workflow = new Workflow("Workflow");
        workflow.getSheets().addAll(createSheets());
        return workflow;
    }

    private List<Sheet> createSheets() {
        List<Sheet> sheets = new ArrayList<>();
        IntStream.range(1, 10).forEach(value -> sheets.add(createSheet()));
        return sheets;
    }

    private Sheet createSheet() {
        Sheet sheet = new Sheet("Sheet" + new Random().nextInt(100)); // Random added to have different names
        sheet.getTasks().addAll(createTasks());
        return sheet;
    }

    private List<Task> createTasks() {
        List<Task> tasks = new ArrayList<>();
        IntStream.range(1, 5).forEach(value -> tasks.add(createTask()));
        return tasks;
    }

    private Task createTask() {
        return new Task("Task" + new Random().nextInt(100)); // Random added to have different names
    }
}

萬一您需要的是.fxml文件:

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

<?import javafx.scene.control.TreeView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="stackoverflow.tree.Controller">
    <TreeView fx:id="treeView"/>
</AnchorPane>

如果您不知道TreeView的深度,則可以使用遞歸創建所有分支或葉子。 在這種情況下,使用兩個foreach而不是創建構建樹結構的遞歸方法要簡單得多。

缺少提供子項列表的公共超類型,您需要為每個包含子對象列表的對象使用1種不同的method / 1嵌套循環。

private TreeItem<String> createWorkFlow(Workflow workflow) {
    TreeItem<String> item = new TreeItem<>(workflow.getName());
    for (Sheet sheet : workflow.getSheets()) {
        item.getChildren().add(createSheet(sheet));
    }
    return item;
}

private TreeItem<String> createSheet(Sheet sheet) {
    TreeItem<String> item = new TreeItem<>(sheet.getName());
    for (Task task : sheet.getTasks()) {
        item.getChildren().add(new TreeItem<>(task.getName());
    }
    return item;
}

要么

private TreeItem<String> createWorkFlow(Workflow workflow) {
    TreeItem<String> workflowItem = new TreeItem<>(workflow.getName());
    for (Sheet sheet : workflow.getSheets()) {
        TreeItem<String> sheetItem = new TreeItem<>(sheet.getName());
        for (Task task : sheet.getTasks()) {
            sheetItem.getChildren().add(new TreeItem<>(task.getName()));
        }
        workflowItem.getChildren().add(sheetItem);
    }
    return item;
}

除非您想使用反射。


為了避免這種情況,您可以使用您的類型實現一個接口:

public interface Item<T extends Item<?>> {
    String getName();
    default List<T> getChildren() {
        return null; // default for terminal object
    }
}

這將使您簡化TreeItem的創建,以

public static <T extends Item<?>> TreeItem<String> createItem(Item<T> item) {
    TreeItem<String> treeItem = new TreeItem<>(item.getName());
    List<T> children = item.getChildren();
    if (children != null) {
        for (Item<?> ci : children) {
            treeItem.getChildren().add(createItem(ci));
        }
    }
    return treeItem;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM