在Flutter应用中,我有一个rxDart块,该块从API服务器获取JSON字符串并将其转换为类列表(销售)。
除了在ListView小部件上显示数据外,我还想使用软件包pdf: 1.3.23
打印数据。
pdf程序包具有一个生成器,但不会使用ListView,因此我需要将Sales列表转换为List>,以便将其传递给Table.fromTextArray。
或更笼统地说,如何从已解析的API响应中创建pdf?或者,如何从数据创建pdf?在显示数据之后,从颤动屏幕打印数据必须是第二个最常见的要求,但是我看不出如何解决该问题的线索。
当我尝试将SalesResponse对象传递给Table.fromTextArray时,会收到此消息。
不能将参数类型“ SalesResponse”分配给该参数 类型List
>。
到目前为止,这是我的代码:
销售模式:
class Sale {
int _id;
int _billId;
String _item;
int _qty;
double _price;
Sale(sale) {
_id = sale['id'];
_billId = sale['bill_id'];
_item = sale['item'];
_qty = sale['qty'];
_price = (sale['price'] as num).toDouble();
}
int get id => _id;
int get billId => _billId;
String get item => _item;
int get qty => _qty;
double get price => _price;
}
这是我的销售响应模型
import 'package:exactpos_mobile/model/sale.dart';
class SalesResponse {
List<Sale> _sales = [];
String error;
SalesResponse.fromJson(Map<String, dynamic> parsedJson) {
print(parsedJson);
List<Sale> temp = [];
if (parsedJson['sales'] != null) {
for (int i = 0; i < parsedJson['sales'].length; i++) {
Sale _sale = Sale(parsedJson['sales'][i]);
temp.add(_sale);
}
_sales = temp;
}
}
SalesResponse.withError(String errorValue)
: _sales = List(),
error = errorValue;
List<Sale> get sales => _sales;
}
销售库
class SaleRepository{
ApiProvider _apiProvider = ApiProvider();
Future<SalesResponse> getSales(int billId){
return _apiProvider.getSales(billId);
}
}
销售集团
import 'package:rxdart/rxdart.dart';
class SalesBloc {
final SaleRepository _repository = SaleRepository();
final PublishSubject<SalesResponse> _subject = PublishSubject<SalesResponse>();
getSales(int billId) async {
SalesResponse response = await _repository.getSales(billId);
_subject.sink.add(response);
}
void dispose() async{
await _subject.drain();
_subject.close();
}
PublishSubject<SalesResponse> get subject => _subject;
}
final salesBloc = SalesBloc();
这是我的小部件屏幕
SalesResponse salesList;
class SalesScreen extends StatefulWidget {
static const routeName = '/sales';
final Bill bill;
final Tbl table;
SalesScreen({
Key key,
@required this.table,
@required this.bill
}) : super(key: key);
@override
State<StatefulWidget> createState() => SalesScreenState();
}
class SalesScreenState extends State<SalesScreen> {
@override
void initState() {
super.initState();
salesBloc.getSales(widget.bill.id);
salesList = salesBloc.getSales(widget.bill.id);
print('hello');
print(salesList.sales);
print('hello');
}
@override
void dispose() {
salesBloc.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: AppDrawer(),
appBar: AppBar(
backgroundColor: Colors.blue,
automaticallyImplyLeading: false,
centerTitle : true,
title: Text(widget.bill.billNumber.toString(),
style: TextStyle(color: Colors.white)
),
leading: IconButton(icon:Icon(Icons.arrow_back),
onPressed:() =>
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) =>
BillsScreen(table: widget.table)), (Route<dynamic> route) => false)
)
),
body: SafeArea(
child: Container(
child:
StreamBuilder<SalesResponse>(
stream: salesBloc.subject.stream,
builder: (context, AsyncSnapshot<SalesResponse> snapshot) {
if (snapshot.hasData) {
if (snapshot.data.error != null && snapshot.data.error.length > 0) {
return _buildErrorWidget(snapshot.data.error);
}
return _buildSalesListWidget(snapshot.data);
}
},
)
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
FloatingActionButton(
heroTag: 1,
backgroundColor: Colors.yellow,
onPressed: () {
Printing.layoutPdf(onLayout:(format)=>
buildReceipt(widget.table,
widget.bill,
salesList));
},
child: Icon(FontAwesomeIcons.print),
),
],
),
)
);
}
Widget _buildSalesListWidget(SalesResponse data) {
return ListView.builder(
itemCount: data.sales.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(
data.sales[index].item,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 20,
),
),
subtitle: Text('qty' + ' ' + data.sales[index].qty.toString() + ', ' + 'price' + ' ' + data.sales[index].price.toStringAsFixed(2)),
leading: Icon(
FontAwesomeIcons.beer,
color: Colors.blue[500],
),
onTap: () {},
);
},
);
}
}
最后,我的pdf代码
Future<List<int>> buildReceipt(Tbl table, Bill bill, SalesResponse salesList) async {
const PdfPageFormat format = PdfPageFormat(160, 900);
final Document pdf = Document();
pdf.addPage(MultiPage(
pageFormat: format, // PdfPageFormat.a4.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
crossAxisAlignment: CrossAxisAlignment.start,
header: (Context context) {
if (context.pageNumber == 1) {
return null;
}
return Container(
alignment: Alignment.centerRight,
margin: const EdgeInsets.only(top: 3.0 * PdfPageFormat.mm),
padding: const EdgeInsets.only(bottom: 3.0 * PdfPageFormat.mm),
decoration: const BoxDecoration(
border:
BoxBorder(bottom: true, width: 0.5, color: PdfColors.grey)),
child: Text('Exact POS',
style: Theme.of(context)
.defaultTextStyle
.copyWith(color: PdfColors.grey)));
},
footer: (Context context) {
return Container(
alignment: Alignment.centerRight,
margin: const EdgeInsets.only(top: 1.0 * PdfPageFormat.cm),
child: Text('Page ${context.pageNumber} of ${context.pagesCount}',
style: Theme.of(context)
.defaultTextStyle
.copyWith(color: PdfColors.grey)));
},
build: (Context context) => <Widget>[
Header(
level: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Exact POS', textScaleFactor: 2),
PdfLogo()
]
)
),
Padding(padding: const EdgeInsets.all(4)),
Paragraph(text: table.number),
Table.fromTextArray(context: context, data: salesList ),
]
)
);
return pdf.save();
}
答案 0 :(得分:0)
问题是public class testBasesetup {
public static Properties prop;
public static WebDriver driver;
public static testBasesetup testBaseObj;
public static EventFiringWebDriver e_driver;
public testBasesetup() throws Exception
{
try {
prop = new Properties();
File src = new File("C:\\Users\\LENOVO\\eclipse-workspace\\Demon\\src\\main\\java\\Config\\config.properties");
FileInputStream ip = new FileInputStream(src) ;
prop.load(ip);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void initialization() throws Exception
{
String browsername = prop.getProperty("browser");
if(browsername.equals("chrome"))
{
System.setProperty("webdriver.chrome.driver", "F:\\Eclipse\\chromedriver.exe");
**driver = new ChromeDriver();**
}
else if(browsername.equals("firefox"))
{
System.setProperty("webdriver.gecko.driver", "F:\\Eclipse\\browser\\geckodriver.exe");
**driver = new FirefoxDriver();**
}
driver.manage().window().maximize();
driver.manage().deleteAllCookies();
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
String URLtoTest = prop.getProperty("URL");
Thread.sleep(1000);
}
}
期望Table.fromTextArray
为List<List<String>>
,而您传递的是data
。
这是一个简单的示例:
SalesResponse
或在Table.fromTextArray(context: context, data: <List<String>>[
<String>['Id', 'Bill Id', 'Item', 'Qty', 'Price'],
...salesList.sales.map((s) =>
['${s.id}', '${s.billId}', '${s.item}', '${s.qty}', '${s.price}']),
])
中创建一个吸气剂以获取列表,如下所示:
Sale
然后像这样使用它:
List<String> get stringList => ['$id', '$billId', '$item', '$qty', '$price'];
或直接在Table.fromTextArray(context: context, data: <List<String>>[
<String>['Id', 'Bill Id', 'Item', 'Qty', 'Price'],
...salesList.sales.map((sale) => sale.stringList),
])
中创建一个吸气剂以获取列表列表,如下所示:
SalesResponse
然后像这样使用它:
List<List<String>> get salesStringList =>
<List<String>>[
<String>['Id', 'Bill Id', 'Item', 'Qty', 'Price'],
...sales.map((sale) => sale.stringList),
];