Hugo Pherst
Hugo Pherst

Reputation: 21

How to add a time delay when printing multiple lines using canvas.drawLine()

I am learning Flutter/Dart, specifically, how to draw on the Canvas.

I want to draw multiple lines using a FOR loop. I want a delay between iterations, so that I see each line painted individually, one after another.

Referencing these two articles:

Asynchronous Programming: Futures https://www.dartlang.org/tutorials/language/futures

Asynchronous Programming: Streams https://www.dartlang.org/tutorials/language/streams

I was able to write a 'text version' line painter to show I could delay a running FOR loop and print some text.

// print 10 lines 'text version'
Future printTenLines() async {
    for (int z = 0; z <= 9; z++) {
      await addDelay();
      print('Line $z');
    }
  }

  main() {
    printTenLines();
  }

  const delayTime = Duration(milliseconds: 1000);

  Future addDelay() => Future.delayed(delayTime);

But when I substitute the actual canvas.drawLine() function for the 'text version' print() routine, I get exception errors.

  const delayTime = Duration(milliseconds: 10);

  Future<String> addDelay() => Future.delayed(delayTime);

  // draw 10 lines on the canvas   
  Future<void> drawTenLines() async {
    for (double i = 0; i <= 100; i += 10) {
      await addDelay();
      print('Line $i');
      canvas.drawLine(
        Offset(size.width/2, size.height/2),
        Offset(i, 0),
        paint,
      );
    }

     drawTenLines();

I found this problem to be similar to trying to print the output of two nested loops. Code executes, and the output of both loops is printed when the outer loop is completed.

I tried nested loops for painting the lines, with the outer loop painting the lines, and the inner loop acting as the delay timer. The program waits until both loops complete, and all the lines are drawn at once.

Using this example of asynchronous Futures and Streams is the closest I got to achieving the desired result. The 'text version" line printer is delayed and works correctly. But the delay will not work with canvas.drawLine().

Here is my complete code. It works as is and draws 10 lines. Un-comment the delay call to see the exception. I just want canvas to delay for some given time before drawing the next line.

`

    import 'package:flutter/material.dart';
    import 'dart:async';

    void main() {
      runApp(MyApp());
    }

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: "Drawing Lines",
          home: DrawingPage(),
        );
      }
    }

    class DrawingPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text("Draw Ten Lines"),
            ),
            body: CustomPaint(
              painter: LinePainter(),
              child: Center(
                child: Text(
                  "",
                  style: TextStyle(fontSize: 20, fontStyle: FontStyle.italic),
                ),
              ),
            ));
      }
    }

    class LinePainter extends CustomPainter {
      @override
      void paint(Canvas canvas, Size size) {
        var paint = Paint();
        paint.color = Colors.blue;
        paint.strokeWidth = 1;
        paint.style = PaintingStyle.stroke;

        const delayTime = Duration(milliseconds: 1000);

        Future<void> addDelay() => Future.delayed(delayTime);

        Future<void> drawTenLines() async {
          for (double i = 0; i <= 100; i += 10) {
            //await addDelay();
            print('Line $i');
            canvas.drawLine(
              Offset(size.width / 2, size.height / 2),
              Offset(i, 0),
              paint,
            );
            //await addDelay();
          }
        }

        drawTenLines();
      }

      @override
      bool shouldRepaint(CustomPainter oldDelegate) => true;
    }

`

Upvotes: 2

Views: 537

Answers (1)

Infusion Analysts
Infusion Analysts

Reputation: 489

Try this way..

Future.delayed(const Duration(milliseconds: 500), () {

// Here you can write your code

setState(() {
// Here you can write your code for open new view
});

 });

second way.. Used Timer

 Timer _timer;
_timer = new Timer(const Duration(milliseconds: 400), () {
  setState(() {

  // Here you can write your code for open new view
  });
});

Timer import 'dart:async'

Upvotes: 1

Related Questions