如何在Dart文件间传递Future<List<int>>返回值用于PDF生成
问题:将Stateful Widget中的图表图片数据传递到其他文件生成PDF
我是Flutter新手,希望将Stateful Widget中readImageData()函数(返回Future<List<int>>,对应图表转换后的ByteData)的返回值传递到另一个Dart文件,用于生成包含图片和DataGrid的PDF。请提供实现代码。
以下是我已编写的代码:
import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_charts/charts.dart'; // 假设DataCathodic是已定义的数据类 class DataCathodic { final DateTime timestamp; final double voltage; final double voltageLoc2; final double voltageLoc3; final double voltageLoc4; final double voltageLoc5; DataCathodic({ required this.timestamp, required this.voltage, required this.voltageLoc2, required this.voltageLoc3, required this.voltageLoc4, required this.voltageLoc5, }); } class CathodicColumn extends StatefulWidget { const CathodicColumn({Key? key}) : super(key: key); @override State<CathodicColumn> createState() => _CathodicColumnState(); } class _CathodicColumnState extends State<CathodicColumn> { // Key State for Column Chart late GlobalKey<SfCartesianChartState> keyChart = GlobalKey<SfCartesianChartState>(); List<DataCathodic>? chartData; // Initiate State @override void initState() { loadCathodicData(); keyChart = GlobalKey<SfCartesianChartState>(); super.initState(); } // 模拟加载数据 void loadCathodicData() { chartData = [ DataCathodic( timestamp: DateTime.now(), voltage: 1.2, voltageLoc2: 1.3, voltageLoc3: 1.1, voltageLoc4: 1.4, voltageLoc5: 1.0, ), // 可添加更多测试数据 ]; } // Dispose Data @override void dispose() { chartData!.clear(); super.dispose(); } // Overrides @override Widget build(BuildContext context) { return _buildCathodicColumnChart(); } Column _buildCathodicColumnChart() { const defaultPadding = 16.0; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SfCartesianChart( key: keyChart, plotAreaBorderWidth: 1.0, title: const ChartTitle(text: 'Cathodic Voltages to Time Column Charts'), tooltipBehavior: TooltipBehavior(enable: true), legend: const Legend( position: LegendPosition.bottom, isResponsive: true, isVisible: true, ), primaryXAxis: const DateTimeAxis( edgeLabelPlacement: EdgeLabelPlacement.shift, title: AxisTitle(text: 'Time (hourly)'), intervalType: DateTimeIntervalType.hours, majorGridLines: MajorGridLines(width: 0), isVisible: true, ), primaryYAxis: const NumericAxis( edgeLabelPlacement: EdgeLabelPlacement.shift, axisLine: AxisLine(width: 0), labelFormat: '{value} DCV', majorTickLines: MajorTickLines(size: 0), ), series: _getCathodicColumnSeries(), ), const SizedBox(height: defaultPadding * 1.2), ElevatedButton( onPressed: saveFileAsPdf, style: ElevatedButton.styleFrom( backgroundColor: Colors.red, maximumSize: const Size(200.0, 50.0), ), child: const Row( children: [ Text("Export to PDF"), Spacer(), Icon(Icons.picture_as_pdf_outlined), ], ), ), ], ); } List<ColumnSeries<DataCathodic, DateTime>> _getCathodicColumnSeries() { return <ColumnSeries<DataCathodic, DateTime>>[ ColumnSeries( name: 'TR Area DWP Voltages', dataSource: chartData!, xValueMapper: (DataCathodic cathodic, _) => cathodic.timestamp, yValueMapper: (DataCathodic cathodic, _) => cathodic.voltage, ), ColumnSeries( name: 'Mile Area 22', dataSource: chartData!, xValueMapper: (DataCathodic cathodic, _) => cathodic.timestamp, yValueMapper: (DataCathodic cathodic, _) => cathodic.voltageLoc2, ), ColumnSeries( name: 'Mile Area 34', dataSource: chartData!, xValueMapper: (DataCathodic cathodic, _) => cathodic.timestamp, yValueMapper: (DataCathodic cathodic, _) => cathodic.voltageLoc3, ), ColumnSeries( name: 'Mile Area 50', dataSource: chartData!, xValueMapper: (DataCathodic cathodic, _) => cathodic.timestamp, yValueMapper: (DataCathodic cathodic, _) => cathodic.voltageLoc4, ), ColumnSeries( name: 'Mile Area 68', dataSource: chartData!, xValueMapper: (DataCathodic cathodic, _) => cathodic.timestamp, yValueMapper: (DataCathodic cathodic, _) => cathodic.voltageLoc5, ), ]; } Future<List<int>> readImageData() async { // Convert Charts to Images final ui.Image data = await keyChart.currentState!.toImage(pixelRatio: 3.0); // Creates Image from Chart with format PNG final ByteData? bytesImage = await data.toByteData(format: ui.ImageByteFormat.png); // Return the Image return bytesImage!.buffer.asUint8List( bytesImage.offsetInBytes, bytesImage.lengthInBytes, ); } // 待实现的PDF保存方法 Future<void> saveFileAsPdf() async { // 后续补充实现 } }
实现方案
1. 添加依赖
在pubspec.yaml中添加PDF生成相关依赖:
dependencies: pdf: ^3.10.0 printing: ^5.12.0 syncfusion_flutter_charts: ^25.1.39 # 保持你已使用的版本
2. 创建PDF生成工具文件
新建pdf_generator.dart,封装生成PDF的逻辑,接收图表图片数据和表格数据:
import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; import 'package:printing/printing.dart'; import '../models/data_cathodic.dart'; // 导入你的DataCathodic类 class PdfGenerator { static Future<void> generatePdf(List<int> chartImageBytes, List<DataCathodic> tableData) async { final pdf = pw.Document(); // 添加图表图片和DataGrid表格 pdf.addPage( pw.Page( build: (context) { return pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ pw.Text('Cathodic Voltages Report', style: pw.TextStyle(fontSize: 24, fontWeight: pw.FontWeight.bold)), pw.SizedBox(height: 20), pw.Image(pw.MemoryImage(chartImageBytes), width: PdfPageFormat.a4.width - 40), pw.SizedBox(height: 20), // 生成DataGrid表格 pw.Table.fromTextArray( headers: ['时间', 'TR Area DWP', 'Mile Area 22', 'Mile Area 34', 'Mile Area 50', 'Mile Area 68'], data: tableData.map((item) => [ item.timestamp.toString(), item.voltage.toStringAsFixed(2), item.voltageLoc2.toStringAsFixed(2), item.voltageLoc3.toStringAsFixed(2), item.voltageLoc4.toStringAsFixed(2), item.voltageLoc5.toStringAsFixed(2), ]).toList(), border: pw.TableBorder.all(), headerStyle: pw.TextStyle(fontWeight: pw.FontWeight.bold), cellAlignment: pw.Alignment.centerLeft, ), ], ); }, ), ); // 保存或打印PDF await Printing.layoutPdf(onLayout: (format) async => pdf.save()); } }
3. 在原Widget中调用PDF生成函数
修改_CathodicColumnState中的saveFileAsPdf方法,获取图表图片数据后调用工具类:
import 'pdf_generator.dart'; // 导入PDF生成工具 // ... 其他代码保持不变 Future<void> saveFileAsPdf() async { try { // 获取图表图片数据 final chartImageBytes = await readImageData(); // 调用PDF生成函数 await PdfGenerator.generatePdf(chartImageBytes, chartData!); } catch (e) { // 处理错误,显示提示 ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('生成PDF失败: $e')), ); } }
内容的提问来源于stack exchange,提问作者Agil Calfarera
相关产品推荐
相关产品推荐

