2

问题

我正在尝试使用 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 抛光之前获得逻辑。

4

2 回答 2

1

Try using Future.delay like

      void _bubbleSortVisualiser() async {
        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.
    await Future.delayed(const Duration(seconds: 1), () {
      setState(() {
                arr = List.from(bubbleArr);
                print("Updated to : $arr");
              });
    });




        }
      }
    }
  }
}
于 2019-12-09T08:20:23.870 回答
0

这一行:

class HomePageState extends State<StatefulWidget> {

应该

class HomePageState extends State<HomePage> {

就这样。它应该工作。

另外,你应该改变这个:

  @override
  State<StatefulWidget> createState() {
    return HomePageState();
  }

至:

  @override
  State<HomePage> createState() => HomePageState();
于 2019-12-08T15:25:24.063 回答