Javafx:TreeView 的域对象
Posted
技术标签:
【中文标题】Javafx:TreeView 的域对象【英文标题】:Javafx : Domain objects to TreeView 【发布时间】:2018-08-28 22:20:50 【问题描述】:我的应用中有三个域对象,如下所示:
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 吗?
【问题讨论】:
【参考方案1】:您必须为所有模型(工作流、工作表、任务)创建一个共同的Model
,因为它们都有一个字符串属性,创建一个非常简单。假设我们有以下模型:
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="***.tree.Controller">
<TreeView fx:id="treeView"/>
</AnchorPane>
如果您不知道TreeView
的深度,您可以使用递归创建所有分支或叶子。在这种情况下,使用两个 foreach 比创建构建树结构的递归方法要简单得多。
【讨论】:
【参考方案2】:缺少提供子项目列表的通用超类型,您需要使用 1 个不同的方法/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
s 的创建简化为
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;
【讨论】:
我已按照您的指示进行操作,效果也很好,谢谢! 是的,如果你更喜欢递归方式,你应该使用这个答案;)以上是关于Javafx:TreeView 的域对象的主要内容,如果未能解决你的问题,请参考以下文章