为啥我的 Flutter CustomPainter 类在使用 scanAngle 小于 2*pi 的 canvas..drawArc() 函数时不在屏幕上绘制任何内容?

Posted

技术标签:

【中文标题】为啥我的 Flutter CustomPainter 类在使用 scanAngle 小于 2*pi 的 canvas..drawArc() 函数时不在屏幕上绘制任何内容?【英文标题】:Why does my Flutter CustomPainter class not paint anything on the screen when using the canvas..drawArc() function with a sweepAngle less than 2*pi?为什么我的 Flutter CustomPainter 类在使用 scanAngle 小于 2*pi 的 canvas..drawArc() 函数时不在屏幕上绘制任何内容? 【发布时间】:2021-12-14 10:08:41 【问题描述】:

由于某种原因,我的 CustomPainter 没有在屏幕上绘制任何内容。我正在尝试构建一个饼图,但仅当我将 sweepAngle 设置为 2*pi 时,画家才能工作。

调用CustomPaint的Widget结构如下:

class PieChart extends StatelessWidget 
  const PieChart(
    Key? key,
  ) : super(key: key);

  @override
  Widget build(BuildContext context) 
    return SizedBox(
      height: 160,
      width: 210,
      child: CustomPaint(
        painter: PieChartPainter(categories: dataset, width: 10),
      ),
    );
  

这是我的 CustomPainter 类:

class PieChartPainter extends CustomPainter 
  PieChartPainter(
    required this.categories,
    required this.width,
  );

  final List<Category> categories;
  final double width;

  @override
  void paint(Canvas canvas, Size size) 
    Offset center = Offset(size.width / 2, size.height / 2);
    double radius = min(size.width / 2, size.height / 2);

    double total = 0;
    // Calculate total amount from each category
    for (var expense in categories) 
      total += expense.amount;
    

    // The angle/radian at 12 o'clock
    double startRadian = -pi / 2;
    for (var index = 0; index < categories.length; index++) 
      final currentCategory = categories.elementAt(index);
      final sweepRadian = currentCategory.amount / total * 2 * pi;
      final paint = Paint()
        ..style = PaintingStyle.fill
        ..strokeWidth = width
        ..color = categoryColors.elementAt(index % categories.length);
      final rect = Rect.fromCenter(
          center: center, width: radius * 2, height: radius * 2);
      canvas.drawArc(
        rect,
        startRadian,
        2 * pi, // should really be "sweepRadian"
        false,
        paint,
      );
      startRadian += sweepRadian;
    
  

  @override
  bool shouldRepaint(PieChartPainter oldDelegate) 
    return true;
  

我几乎可以肯定地说,问题与我提供的数据和颜色无关,因为每当我将当前元素记录到控制台时,它都会给出正确的输出。 在这里,您可以看到我的 Widget 结构:

这是组件本身的图像:(请注意,整个圆圈只显示最后一个类别颜色,因为每当我使用小于 2*pi 的扫描角度时,整个小部件都不会显示颜色。)

这是我设置的扫描角度小于 2*pi 时的组件:

我真的无法弄清楚可能导致此问题的原因。有没有人知道sweepAngle参数还会影响什么?我也不知道为什么各个类别左侧的彩色圆圈不可见,因为它们呈现在一个完全不同的小部件分支中...... 如果您对如何解决此问题有任何想法,我将非常乐意提供更多信息,但只要我不知道去哪里寻找,我不想在此问题上发送不必要的信息。

【问题讨论】:

仅用于测试:尝试for (var index = 0; index &lt; 1; index++) 并使用canvas.drawArc( rect, startRadian, pi / 2, false, paint, ); @pskink 当我将 for 循环标题更改为“... index 所以如果你这样做canvas.drawArc(rect, startRadian, pi / 2, false, paint, ); 会画出完整的圆圈?而不是四分之一? @pskink 不完全是。当我使用canvas.drawArc(rect, startRadian, pi / 2, false, paint, );它看起来像帖子的最后一张图片。意思是,根本没有圆圈显示。但是,当我将 sweepAngle 留在 2 * pi 并更改 for 循环标题时,然后 - 正如预期的那样 - 一个完整的圆圈以蓝色绘制。 @pskink 我复制了您的 CustomPainter 实现,并用这个替换了 Widget-Tree 中的 PieChartPainter。可悲的是,它仍然显示同样的问题。当我使用您的确切代码运行该应用程序时,没有显示任何圆圈。但是,当我只将canvas.drawArc(rect, st, sw, true, paint..color = zip[1] as Color); 更改为canvas.drawArc(rect, st, 2 * pi, true, paint..color = zip[1] as Color); 时,它会显示一个青色的大圆圈,并且类别名称左侧的小圆圈也会重新出现。 【参考方案1】:

对于任何想知道的人: 问题与“--enable-software-rendering”参数有关。一旦我用flutter run --enable-software-rendering 运行,一切都按预期工作。

【讨论】:

以上是关于为啥我的 Flutter CustomPainter 类在使用 scanAngle 小于 2*pi 的 canvas..drawArc() 函数时不在屏幕上绘制任何内容?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 Flutter 应用中的 FAB 很大?

为啥我的 Flutter 应用程序在执行时没有构建?

Flutter:为啥我的构建器在 Web 服务调用后没有重新加载?

为啥 Flutter 编译器告诉我我的应用程序不存在?

为啥我的 Flutter 应用在​​ Android 上请求 Run on Startup 权限?

为啥我的 Flutter 应用在​​ iOS 上启动时会崩溃?