Home > Back-end >  CustomPainter drawImage throws an exception ("Object has been disposed.")
CustomPainter drawImage throws an exception ("Object has been disposed.")

Time:01-27

I have created a SamplePainter that inherits from CustomPainter as shown below, and in it, I am trying to create cartoonish screen tones using PictureRecorder.

When I try to use that screen tone to draw a shape using the paintImage function, I get an exception ("Object has been disposed.").

If I try to use canvas.drawImage instead, I get the same exception. What is the problem?

import 'package:flutter/material.dart';
import 'dart:ui' as ui;

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

// https://www.flutter-study.dev/widgets/button-widget
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo'),
        ),
        body: SizedBox(
          width: 400,
          height: 400,
          child: CustomPaint(
            painter: _SamplePainter(),
          ),
        ),
        floatingActionButton: FloatingActionButton(
          backgroundColor: Colors.green,
          onPressed: () {},
          child: const Icon(Icons.add),
        ),
      ),
    );
  }
}

class _SamplePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) async {
    final paint = Paint()..color = Colors.blue;
    final boundsRect = const Offset(50, 50) & const Size(100, 100);

    canvas.drawRect(boundsRect, paint);

    var aPattern = await getPattern();

    canvas.drawImage(aPattern, Offset.zero, paint);

    // paintImage(
    //   canvas: canvas,
    //   rect: boundsRect,
    //   image: aPattern,
    //   repeat: ImageRepeat.repeat,
    // );
  }

  Future<ui.Image> getPattern() async {
    var pictureRecorder = ui.PictureRecorder();
    Canvas patternCanvas = Canvas(pictureRecorder);

    List<Offset> points = const [Offset(0, 0), Offset(1, 1)];
    final patternPaint = Paint()
      ..color = Colors.black
      ..strokeWidth = 1
      ..style = PaintingStyle.stroke
      ..strokeJoin = StrokeJoin.round
      ..isAntiAlias = false;

    patternCanvas.drawPoints(ui.PointMode.points, points, patternPaint);
    final aPatternPicture = pictureRecorder.endRecording();

    return aPatternPicture.toImage(2, 2);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

CodePudding user response:

Try like this, the main problem you have, is that paint, should be sync method, not async

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

// https://www.flutter-study.dev/widgets/button-widget
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo'),
        ),
        body: SizedBox(
          width: 400,
          height: 400,
          child: FutureBuilder(
            future: getPattern()
            builder: (BuildContext context, AsyncSnapshot<ui.Image> 
              snapshot) {
              return CustomPaint(
                painter: _SamplePainter(snapshot.data),
              );
            },
          ),
        ),
        floatingActionButton: FloatingActionButton(
          backgroundColor: Colors.green,
          onPressed: () {},
          child: const Icon(Icons.add),
        ),
      ),
    );
  }
}

Future<ui.Image> getPattern() async {
  var pictureRecorder = ui.PictureRecorder();
  Canvas patternCanvas = Canvas(pictureRecorder);

  List<Offset> points = const [Offset(0, 0), Offset(1, 1)];
  final patternPaint = Paint()
    ..color = Colors.black
    ..strokeWidth = 1
    ..style = PaintingStyle.stroke
    ..strokeJoin = StrokeJoin.round
    ..isAntiAlias = false;

  patternCanvas.drawPoints(ui.PointMode.points, points, patternPaint);
  final aPatternPicture = pictureRecorder.endRecording();

  return aPatternPicture.toImage(2, 2);
}

class _SamplePainter extends CustomPainter {
  final ui.Image? aPattern;

  _SamplePainter(this.aPattern);

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..color = Colors.blue;
    final boundsRect = const Offset(50, 50) & const Size(100, 100);

    canvas.drawRect(boundsRect, paint);
    if (aPattern != null) {
      canvas.drawImage(aPattern!, Offset.zero, paint);
    }

    // paintImage(
    //   canvas: canvas,
    //   rect: boundsRect,
    //   image: aPattern,
    //   repeat: ImageRepeat.repeat,
    // );
  }

  @override
  bool shouldRepaint(_SamplePainter oldDelegate) {
    return aPattern != oldDelegate.aPattern;
  }
}
  •  Tags:  
  • Related