首页 > 解决方案 > 更新 CustomPaint 绘图

问题描述

我的 CustomPainter 小部件有问题。我想绘制一个可以正常工作的 PieChart,然后我添加了一个将图表绘制到该角度的变量。现在我想为它制作动画,我使用了 Future.delayed 函数并在其中使用 setState 我想更新变量,但不幸的是这不起作用。

我正在为网络开发。感谢您的帮助!

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:stats/data/listLanguages.dart';
import 'painter/pieChartPainter.dart';

class Chart extends StatefulWidget {
  ListLanguages listLanguages;

  Chart({ListLanguages listLanguages}) {
    if (listLanguages == null) {
      listLanguages = new ListLanguages();
    }

    this.listLanguages = listLanguages;
  }

  @override
  _ChartState createState() => _ChartState();
}

class _ChartState extends State<Chart> {
  @override
  Widget build(BuildContext context) {
    List angles = widget.listLanguages.calcCounts();

    int angle = 0;
    Future.delayed(new Duration(seconds: 2), (){
      setState(() {
        angle = 360;
        print("test");
      });
    });

    return Column(
      children: [
        Spacer(flex: 2),
        Row(
          children: [
            Spacer(),
            CustomPaint(
              size: Size.square(400),
              painter: PieChartPainter(
                angles: angles,
                colors: new List()
                  ..add(Colors.green)
                  ..add(Colors.blue)
                  ..add(Colors.brown)
                  ..add(Colors.pink)
                  ..add(Colors.orange)
                  ..add(Colors.grey.shade700),
                angle: angle,
              ),
            ),
            Spacer(flex: 10),
          ],
        ),
        Spacer(flex: 3),
      ],
    );
  }
}
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math.dart' as vm;

class PieChartPainter extends CustomPainter {
  List angles, colors;
  int angle;

  PieChartPainter(
      {@required List angles, @required List colors, int angle: 360}) {
    this.angles = angles;
    this.colors = colors;
    this.angle = angle;
  }

  @override
  void paint(Canvas canvas, Size size) {
    Paint p = new Paint();
    double start = -90;
    double tmp = 0;

    for (int i = 0; i < angles.length; i++) {
      if (i < 5) {
        p.color = colors[i];
      } else {
        p.color = colors[5];
      }

      if (tmp + angles[i] < angle) {
        canvas.drawArc(Rect.fromLTRB(0, 0, size.width, size.height),
            vm.radians(start), vm.radians(angles[i]), true, p);

        start = start + angles[i];
        tmp = tmp + angles[i];
      } else {
        double x = angle - tmp;
        canvas.drawArc(Rect.fromLTRB(0, 0, size.width, size.height),
            vm.radians(start), vm.radians(x), true, p);
        return;
      }
    }
  }

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

这是我必须创建饼图的完整代码

标签: flutterpaintflutter-web

解决方案


您可以在下面复制粘贴运行完整代码
在您的情况下,您可以在 2、4、6 秒内Future.delayed将逻辑build移至 initState并使用addPostFrameCallback
工作演示更改,并且是 150、250、360 代码片段angleangle

class _ChartState extends State<Chart> {
  int angle = 0;
  List angles;

  @override
  void initState() {
    angles = widget.listLanguages.calcCounts();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      Future.delayed(Duration(seconds: 2), () {         
        setState(() {
          angle = 150;            
        });
      });
      Future.delayed(Duration(seconds: 4), () {         
        setState(() {
          angle = 250;            
        });
      });
      Future.delayed(Duration(seconds: 6), () {         
        setState(() {
          angle = 360;            
        });
      });
    });

工作演示

在此处输入图像描述

完整代码

import 'package:flutter/material.dart';
import 'package:vector_math/vector_math.dart' as vm;

class ListLanguages {
  List calcCounts() {
    return [10.0, 20.0, 100.0, 150.0, 250.0, 300.0];
  }
}

class Chart extends StatefulWidget {
  ListLanguages listLanguages;

  Chart({ListLanguages listLanguages}) {
    if (listLanguages == null) {
      listLanguages = ListLanguages();
    }

    this.listLanguages = listLanguages;
  }

  @override
  _ChartState createState() => _ChartState();
}

class _ChartState extends State<Chart> {
  int angle = 0;
  List angles;

  @override
  void initState() {
    angles = widget.listLanguages.calcCounts();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      Future.delayed(Duration(seconds: 2), () {
        print("delay");
        setState(() {
          angle = 150;
          print("test");
        });
      });
      Future.delayed(Duration(seconds: 4), () {
        print("delay");
        setState(() {
          angle = 250;
          print("test");
        });
      });
      Future.delayed(Duration(seconds: 6), () {
        print("delay");
        setState(() {
          angle = 360;
          print("test");
        });
      });
    });

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Spacer(flex: 2),
        Row(
          children: [
            Spacer(),
            CustomPaint(
              size: Size.square(400),
              painter: PieChartPainter(
                angles: angles,
                colors: List()
                  ..add(Colors.green)
                  ..add(Colors.blue)
                  ..add(Colors.brown)
                  ..add(Colors.pink)
                  ..add(Colors.orange)
                  ..add(Colors.grey.shade700),
                angle: angle,
              ),
            ),
            Spacer(flex: 10),
          ],
        ),
        Spacer(flex: 3),
      ],
    );
  }
}

class PieChartPainter extends CustomPainter {
  List angles, colors;
  int angle;

  PieChartPainter(
      {@required List angles, @required List colors, int angle: 360}) {
    this.angles = angles;
    this.colors = colors;
    this.angle = angle;
  }

  @override
  void paint(Canvas canvas, Size size) {
    Paint p = Paint();
    double start = -90;
    double tmp = 0;

    for (int i = 0; i < angles.length; i++) {
      if (i < 5) {
        p.color = colors[i];
      } else {
        p.color = colors[5];
      }

      if (tmp + angles[i] < angle) {
        canvas.drawArc(Rect.fromLTRB(0, 0, size.width, size.height),
            vm.radians(start), vm.radians(angles[i]), true, p);

        start = start + angles[i];
        tmp = tmp + angles[i];
      } else {
        double x = angle - tmp;
        canvas.drawArc(Rect.fromLTRB(0, 0, size.width, size.height),
            vm.radians(start), vm.radians(x), true, p);
        return;
      }
    }
  }

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: Chart(
        listLanguages: ListLanguages(),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

推荐阅读