問題
Flutter を使用して並べ替えビジュアライザーを構築しようとしています。を使用してCustomPainter
、ソートする整数リストの値に対応する垂直線を描画しました。アプリケーションは、ユーザーが [バブル ソート] オプションをクリックすると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 を磨く前にロジックを正しく取得したいと考えています。