Flutter GraphView点击节点新增子节点及升序排列问题求解
问题分析
原有代码出现随机添加子节点的核心问题有3个:
- 新增节点的
add()方法中使用r.nextInt(graph.nodeCount())随机选取父节点,完全没有关联当前点击的节点 - 点击添加按钮时没有传递当前节点的标识,无法定位需要新增子节点的目标父节点
- 节点ID使用随机数生成,既可能出现ID重复,也无法满足节点升序排列的要求,且每次点击仅新增1个节点,不符合需求。
具体修改方案
- 新增自增的节点ID计数器,初始值从现有最大节点ID+1开始,保证后续新增节点ID连续递增
- 调整
rectangleWidget方法,接收当前节点的完整Node对象而非仅ID值,点击添加按钮时将当前节点作为参数传入新增方法 - 重写新增逻辑:接收父节点参数,每次点击添加按钮时生成2个连续ID的新节点,绑定到当前点击的父节点下
- 移除新增逻辑中随机选取父节点、随机生成节点ID的错误代码
修正后完整代码
import 'package:flutter/material.dart'; import 'package:graphview/GraphView.dart'; class MyGraphView extends StatefulWidget { const MyGraphView({Key? key}) : super(key: key); @override _MyGraphViewState createState() => _MyGraphViewState(); } class _MyGraphViewState extends State<MyGraphView> { // 移除无用的Random实例,新增自增ID计数器,初始值从初始节点最大值+1开始 int currentMaxId = 3; final Graph graph = Graph()..isTree = true; BuchheimWalkerConfiguration builder = BuchheimWalkerConfiguration(); @override void initState() { final node1 = Node.Id(1); final node2 = Node.Id(2); final node3 = Node.Id(3); graph.addEdge(node1, node2); graph.addEdge(node1, node3, paint: Paint()); builder ..siblingSeparation = (50) ..levelSeparation = (50) ..subtreeSeparation = (50) // 同层节点按添加顺序(即ID升序)排列 ..orientation = (BuchheimWalkerConfiguration.ORIENTATION_TOP_BOTTOM); } @override Widget build(BuildContext context) { return SafeArea( child: Center( child: Scaffold( appBar: AppBar(title: const Text("GraphView Example"),), body: Column( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ Expanded( child: InteractiveViewer( constrained: false, boundaryMargin: const EdgeInsets.all(100), minScale: 0.01, maxScale: 5.6, child: GraphView( graph: graph, algorithm: BuchheimWalkerAlgorithm( builder, TreeEdgeRenderer(builder)), paint: Paint() ..color = Colors.green ..strokeWidth = 1 ..style = PaintingStyle.stroke, builder: (Node node) { // 直接传入完整node对象,不再只取int值 return rectangleWidget(node); }, )), ), ], )), ), ); } Widget rectangleWidget(Node node) { int a = node.key?.value as int; return InkWell( onTap: () { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text("Node $a Clicked"), duration: const Duration(seconds: 2, milliseconds: 500), )); }, child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(5), boxShadow: const [ BoxShadow(color: Colors.grey, spreadRadius: 1), ], ), child: Column( children: [ Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( borderRadius: BorderRadius.circular(7), boxShadow: const [ BoxShadow(color: Colors.green, spreadRadius: 1), ], ), child: Text('Node $a') ), const SizedBox(height: 10,), GestureDetector( onTap: () { // 传入当前节点作为父节点 addChildNodes(node); }, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(5), boxShadow: const [ BoxShadow(color: Colors.grey, spreadRadius: 1), ], ), child: const Icon(Icons.add), ), ), ], ), ), ); } // 重写新增方法,接收父节点参数,一次添加2个升序ID的子节点 void addChildNodes(Node parentNode){ // 生成2个连续递增ID的子节点 for(int i=0; i<2; i++){ currentMaxId +=1; final newNode = Node.Id(currentMaxId); graph.addEdge(parentNode, newNode); } setState(() {}); } }
效果说明
- 点击任意节点的添加按钮,会固定在当前点击节点下新增2个子节点
- 所有节点ID连续递增,同层节点按ID升序排列,不会出现随机挂载的问题
- 移除了无用的随机数逻辑,避免ID重复问题
内容的提问来源于stack exchange,提问作者Anjali
相关产品推荐
相关产品推荐

