问题
我正在尝试使用 Flutter 构建排序可视化工具。我用 aCustomPainter
绘制了与我打算排序的整数列表的值相对应的垂直线。应用程序设置为,当用户从DropDownButton
(我打算稍后添加更多排序算法)中单击“冒泡排序”选项时,CustomPainter
画布中的垂直线必须自行排序。
代码
import 'dart:io';
import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() => runApp(HomePage());
class HomePage extends StatefulWidget {
@override
HomePageSate createState() {
return HomePageState();
}
}
class HomePageState extends State<HomePage> {
List<int> arr;
@override
void initState() {
super.initState();
arr = _getRandomIntegerList();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Sorting Visualiser'),
actions: <Widget>[
DropdownButton<String>(
onChanged: (dynamic choice) {
switch (choice) {
case 'Bubble Sort':
_bubbleSortVisualiser();
break;
}
},
items: <String>['Bubble Sort']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
)
],
),
//The following flatButton refreshes arr to have a new array of random integers.
bottomNavigationBar: FlatButton(
onPressed: () {
setState(() {
arr = _getRandomIntegerList();
});
},
child: Icon(Icons.refresh),
),
body: CustomPaint(
size: Size(double.infinity, double.infinity),
painter: SortingCanvas(arr),
),
),
);
}
//function to sort the list using bubble sort and repaint the canvas at every iteration.
void _bubbleSortVisualiser() {
print('Bubble sort function called');
List<int> bubbleArr = List.from(arr);
for (int i = 0; i < bubbleArr.length - 1; i++) {
for (int j = 0; j < bubbleArr.length - 1 - i; j++) {
int temp;
if (bubbleArr[j] < bubbleArr[j + 1]) {
temp = bubbleArr[j];
bubbleArr[j] = bubbleArr[j + 1];
bubbleArr[j + 1] = temp;
//Every time arr changes setState() is called to visualise the changing array.
setState(() {
arr = List.from(bubbleArr);
print("Updated to : $arr");
});
//Sleep is called so that the change is noticeable
sleep(Duration(seconds: 1));
}
}
}
}
}
class SortingCanvas extends CustomPainter {
List<int> arr;
SortingCanvas(this.arr);
@override
void paint(Canvas canvas, Size size) {
var linePaint = Paint()
..color = Colors.black
..style = PaintingStyle.stroke
..strokeWidth = 5.0
..isAntiAlias = true;
//IMP the first offset is the bottom point and the second is the top point of the vertical line.
//It is offset from the top left corner of the canvas
for (int i = 1; i <= arr.length; i++) {
canvas.drawLine(Offset(50.0 + (20 * i), size.height - 50),
Offset(50.0 + (20 * i), 50.0 * arr[i - 1]), linePaint);
}
}
@override
bool shouldRepaint(SortingCanvas oldDelegate) {
return !listEquals(this.arr, oldDelegate.arr);
}
}
//Helper function to get a list of 10 random integers
List<int> _getRandomIntegerList() {
List<int> arr = [];
Random rng = new Random();
for (int i = 0; i < 10; i++) {
arr.add(rng.nextInt(10));
}
return arr;
}
然而,最终发生的是arr
在画布上仅显示最终排序,并且由于某种原因跳过了所有中间步骤。但是日志显示列表正在更新。
截图
随机列表的初始屏幕 单击下拉按钮中的冒泡排序 排序列表
添加该sleep()
功能只是为了模拟动画,一旦解决此问题,我打算用适当的动画替换它。另外,我知道该应用程序有点丑陋,但我想在任何 UI 抛光之前获得逻辑。