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;
}
}
