I'm trying to do a chart on flutter and my numbers are decimal, but the charts flutter only let me use whole(int) ticks, that said my chart becomes very uggly.
I've tried to change my tick provider in many ways, but it doesn't seem to accept double in any way.
With this code I can generate a nice graph, but i just want my Measure Axis is between 3 and 4, and I wanted like, 3.1/3.2/3.3.
import 'dart:convert';
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:math';
class Graficos extends StatefulWidget {
#override
_GraficosState createState() => _GraficosState();
}
class _GraficosState extends State<Graficos> {
List<charts.Series> seriesList;
int qteMeses = 6;
bool baixou = false;
var jsonData;
List<LinearSales> dados = List();
List<double> precos = List();
double menorPreco = 0;
double maiorPreco = 0;
final myController = TextEditingController();
#override
void initState() {
super.initState();
_Carregar();
}
Future<String> _Carregar( ) async{
print('local');
var response = await _funcaoJson();
if(response.length != null) {
seriesList = await _pegaDados();
}
return 'ok';
}
#override
Widget build(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: jsonData == null ?
Container(): Column(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: new charts.TimeSeriesChart(seriesList,primaryMeasureAxis: new charts.NumericAxisSpec(
viewport: new charts.NumericExtents(menorPreco - 0.3, maiorPreco + 0.3), tickProviderSpec:
new charts.BasicNumericTickProviderSpec(desiredTickCount: 1)), behaviors: [
new charts.PanAndZoomBehavior(),
new charts.RangeAnnotation([
new charts.RangeAnnotationSegment(new DateTime(int.parse(((jsonData['pesquisa_total'][0]['pesquisas'][qteMeses]['data_publicacao']).toString()).split("\/")[2]),int.parse(((jsonData['pesquisa_total'][0]['pesquisas'][qteMeses]['data_publicacao']).toString()).split("\/")[1]),int.parse(((jsonData['pesquisa_total'][0]['pesquisas'][qteMeses]['data_publicacao']).toString()).split("\/")[0])),
new DateTime.now(), charts.RangeAnnotationAxisType.domain),
new charts.LineAnnotationSegment(
maiorPreco, charts.RangeAnnotationAxisType.measure,
endLabel: 'Maior Preco: $maiorPreco',
color: charts.MaterialPalette.gray.shade400),
new charts.LineAnnotationSegment(
menorPreco, charts.RangeAnnotationAxisType.measure,
startLabel: 'Menor preco: $menorPreco',
color: charts.MaterialPalette.gray.shade400),
]),
]),
),
],
),
);
}
List<charts.Series<LinearSales, DateTime>> _pegaDados() {
montaGrafico();
menorPreco = precos.reduce(min);
maiorPreco = precos.reduce(max);
return [
new charts.Series<LinearSales, DateTime>(
id: 'Preço',
displayName: 'Preço',
domainFn: (LinearSales sales, _) => sales.mes,
measureFn: (LinearSales sales, _) => sales.sales,
data: dados,
)
];
}
Future<void> montaGrafico() async {
for(var i = qteMeses; i >= 0; i--){
dados.add(
LinearSales(new DateTime(int.parse(((jsonData['pesquisa_total'][0]['pesquisas'][i]['data_publicacao']).toString()).split("\/")[2]),int.parse(((jsonData['pesquisa_total'][0]['pesquisas'][i]['data_publicacao']).toString()).split("\/")[1]),int.parse(((jsonData['pesquisa_total'][0]['pesquisas'][i]['data_publicacao']).toString()).split("\/")[0])), double.parse((jsonData['pesquisa_total'][0]['pesquisas'][i]['items'][0]['ranking'][0]['preco'].toString()).replaceAll(',', '.'))),
);
print(int.parse(((jsonData['pesquisa_total'][0]['pesquisas'][i]['data_publicacao']).toString()).split("\/")[0]));
precos.add(double.parse((jsonData['pesquisa_total'][0]['pesquisas'][i]['items'][0]['ranking'][0]['preco'].toString()).replaceAll(',', '.')));
}
}
var aux;
Future<String> _funcaoJson() async {
var data = await http.get(
'My secret http');
setState(() {
jsonData = jsonDecode(data.body);
});
return 'Sucesso';
}
}
class LinearSales {
final DateTime mes;
final double sales;
LinearSales(this.mes, this.sales);
}
´´´
I found something that can interest those who will see this answer. To display double on your axis you can do so :
In your TimeSeriesChart() widget :
TimeSeriesChart(
primaryMeasureAxis: new charts.NumericAxisSpec(
tickProviderSpec: new charts.StaticNumericTickProviderSpec(
_createTickSpec(),
),
),
),
Then you can create a function _createTickSpec() :
List<charts.TickSpec<num>> _createTickSpec() {
List<charts.TickSpec<num>> _tickProvidSpecs = new List<charts.TickSpec<num>>();
double d = minVal;
while (d <= maxVal) {
_tickProvidSpecs.add(new charts.TickSpec(d,
label: '$d%', style: charts.TextStyleSpec(fontSize: 14)));
d += 0.1;
}
}
Related
I hope somebody can help me out on a problem that i have.
I try to explain the problem the best i can.
The idea is the following for a Desktop App
First i tried to fetch and save data locally in a Json file that i get over WebSocket. What is working.
Second i tried to display the data of the local Json file inside a Chart. What is also working.
After i tried to combine the two above scenarios i one app and here i get the following error.
Exception has occurred.
FileSystemException (FileSystemException: read failed, path = 'C:\Users\7ke19\Documents/Measure/measure.json' (OS Error: The process cannot access the file because another process has locked a portion of the file.
, errno = 33))
In my app i am using the following packages.
Getx for the state manegment. https://pub.dev/packages/get
Localstorage for the Json storage. https://pub.dev/packages/localstorage
Syncfusion_flutter_charts for the Chart. https://pub.dev/packages/syncfusion_flutter_charts
Path_provider to get access to file and folders. https://pub.dev/packages/path_provider
I think i get the above error because at some moment inside my code the app is trying to read a write to the file at the same time.
Follows the code that i have.
The code is divided in three separated files.
Main Function:
import 'package:flutter/material.dart';
import 'package:flutter_application_2/controller/diagram_controller.dart';
import 'package:flutter_application_2/home_screen.dart';
import 'package:get/get.dart';
void main() async {
Get.put(DiagramController());
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const GetMaterialApp(
debugShowCheckedModeBanner: false,
home: HomeScreen(),
);
}
}
HomeScreen:
import 'package:flutter_application_2/controller/diagram_controller.dart';
import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: GetBuilder<DiagramController>(
init: DiagramController(),
initState: (_) {},
builder: (gtxs1) {
return FutureBuilder(
future: gtxs1.getJsonData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
//********Showing if Websocket is Connected or Disconnected*******
child: gtxs1.connectedS1Status
? const Text(
"WEBSOCKET: CONNECTED",
style: TextStyle(
fontSize: 18,
color: Colors.green,
),
)
: const Text(
"WEBSOCKET: DISCONNECTED",
style: TextStyle(
fontSize: 18,
color: Colors.red,
),
),
),
//**********************Showing Range Diagram **********************
Column(
children: [
const Text(
'Range Diagram:',
),
const SizedBox(
height: 5,
),
SizedBox(
width: 800,
height: 280,
child: SfCartesianChart(
title: ChartTitle(
borderWidth: 2,
alignment: ChartAlignment.near,
),
series: gtxs1.getSeriesRange(),
legend: Legend(isVisible: true),
),
),
],
),
const SizedBox(
height: 20,
),
//**********************Showing Force Diagram **********************
Column(
children: [
const Text(
'Force Diagram:',
),
const SizedBox(
height: 5,
),
SizedBox(
width: 800,
height: 280,
child: SfCartesianChart(
title: ChartTitle(
borderWidth: 2,
alignment: ChartAlignment.near,
),
series: gtxs1.getSeriesForce(),
legend: Legend(isVisible: true),
),
),
],
),
],
);
} else {
return const CircularProgressIndicator();
}
},
);
},
),
);
}
}
Controller:
// ignore_for_file: avoid_print
import 'package:get/get.dart';
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:path_provider/path_provider.dart';
import 'package:web_socket_channel/io.dart';
import 'package:localstorage/localstorage.dart';
final MeasureList list = MeasureList(); //List for LocalStorage
bool initialized = false; //for LocalStorage
int istcyclesJson = 0; //variable for istcycles
List<dynamic> istrangesensorJson = [0]; //variable for istrangesensor
List<dynamic> istforcesensorJson = [0]; //variable for istforcesensor
//***********************************************************************************************
//-----class MeasureItem for LocalStorage--------------------------------------------------------
//***********************************************************************************************
class MeasureItem {
int titleCountJson;
List<dynamic> titleRangeJson;
List<dynamic> titleForceJson;
MeasureItem({
required this.titleCountJson,
required this.titleRangeJson,
required this.titleForceJson,
});
toJSONEncodable() {
Map<String, dynamic> m = {};
m['count_array'] = titleCountJson;
m['range_array'] = titleRangeJson;
m['force_array'] = titleForceJson;
return m;
}
}
//***********************************************************************************************
//-----class MeasureList for LocalStorage--------------------------------------------------------
//***********************************************************************************************
class MeasureList {
List<MeasureItem> items = [];
toJSONEncodable() {
return items.map((item) {
return item.toJSONEncodable();
}).toList();
}
}
class DiagramController extends GetxController {
static DiagramController get to => Get.find();
List<List<ChartDataRange>> dataListRange = [];
List<List<ChartDataForce>> dataListForce = [];
LocalStorage storage = LocalStorage('/Measure/measure.json');
final MeasureList list = MeasureList();
late IOWebSocketChannel channel;
late bool connectedS1Status;
Directory? rootPath;
//**********************************************************************
#override
void onInit() {
connectedS1Status = false;
createFileFolder();
Future.delayed(
Duration.zero,
() async {
channelconnect();
},
);
Future.delayed(
const Duration(milliseconds: 1000),
() async {
loadStringRange();
loadStringForce();
},
);
super.onInit();
}
//***********************************************************************************************
//-----Channelconnect----------------------------------------------------------------------------
//***********************************************************************************************
channelconnect() {
try {
channel = IOWebSocketChannel.connect("ws://192.168.1.100:80");
channel.stream.listen(
(message) {
print(message);
Map<String, dynamic> jsondat = json.decode(message);
String data = json.encode(jsondat);
if (data.contains("cycle")) {
connectedS1Status = true;
update();
}
if (data.contains("count_array")) {
istcyclesJson = jsondat['count_array'];
istrangesensorJson = jsondat['range_array'];
istforcesensorJson = jsondat['force_array'];
_save();
//update();
}
},
onDone: () {
print("Web socket is closed");
connectedS1Status = false;
},
onError: (error) {
print(error.toString());
},
);
} catch (_) {
print("error on connecting to websocket.");
}
//update();
}
//***********************************************************************************************
//-----Functions to create and generate Json List using LocalStorage-----------------------------
//***********************************************************************************************
//...................................................
void _save() {
_addItem(istcyclesJson, istrangesensorJson, istforcesensorJson);
print("SAVE");
// update();
}
//...................................................
_addItem(int titlecount, List<dynamic> titlerange, List<dynamic> titleforce) {
final item = MeasureItem(
titleCountJson: titlecount,
titleRangeJson: titlerange,
titleForceJson: titleforce);
list.items.add(item);
_saveToStorage();
//update();
}
//...................................................
_saveToStorage() {
storage.setItem('measure', list.toJSONEncodable());
//update();
}
//***********************************************************************************************
//-----Functions to create Folder and File if not exist and write to the file some zero values
//-----not to get error when display the chart and the file is empty
//***********************************************************************************************
Future<File> createFileFolder() async {
rootPath = await getApplicationDocumentsDirectory();
Directory sampleFolder = Directory('${rootPath!.path}/Measure');
if (!sampleFolder.existsSync()) {
sampleFolder.createSync();
}
File sampleFile =
await File('${sampleFolder.path}/measure.json').create(recursive: true);
if (!sampleFile.existsSync()) {
sampleFolder.createSync();
}
final file = sampleFile;
return file.writeAsString(
'{"measure": [{"count": 0,"range_array": [0,0,0],"force_array": [0,0,0]}]}');
}
//**********************************************************************
Future<String> getJsonData() async {
rootPath = await getApplicationDocumentsDirectory();
Directory sampleFolder = Directory('${rootPath!.path}/Measure');
await File('${sampleFolder.path}/measure.json').create(recursive: true);
return await File('${sampleFolder.path}/measure.json').readAsString();
}
//**********************************************************************
Future loadStringRange() async {
final String jsonString = await getJsonData();
final dynamic jsonResponse = json.decode(jsonString);
List<dynamic> values = jsonResponse['measure'].last['range_array'];
List<ChartDataRange> chartDataR = [];
for (var j = 0; j < values.length; j++) {
chartDataR.add(ChartDataRange(j, values[j]));
}
dataListRange.add(chartDataR);
update();
}
//**********************************************************************
Future loadStringForce() async {
final String jsonString = await getJsonData();
final dynamic jsonResponse = json.decode(jsonString);
List<dynamic> values = jsonResponse['measure'].last['force_array'];
List<ChartDataForce> chartDataF = [];
for (var j = 0; j < values.length; j++) {
chartDataF.add(ChartDataForce(j, values[j]));
}
dataListForce.add(chartDataF);
update();
}
//**********************************************************************
List<ChartSeries<ChartDataRange, num>> getSeriesRange() {
List<ChartSeries<ChartDataRange, num>> seriesListRange = [];
for (var index = 0; index < dataListRange.length; index++) {
seriesListRange.add(
SplineSeries<ChartDataRange, num>(
dataSource: dataListRange[index],
xValueMapper: (ChartDataRange data, _) => data.x,
yValueMapper: (ChartDataRange data, _) => data.y,
),
);
}
return seriesListRange;
}
//**********************************************************************
List<ChartSeries<ChartDataForce, num>> getSeriesForce() {
List<ChartSeries<ChartDataForce, num>> seriesListForce = [];
for (var index = 0; index < dataListForce.length; index++) {
seriesListForce.add(
SplineSeries<ChartDataForce, num>(
dataSource: dataListForce[index],
xValueMapper: (ChartDataForce data, _) => data.x,
yValueMapper: (ChartDataForce data, _) => data.y,
),
);
}
return seriesListForce;
}
}
//**********************************************************************
class ChartDataRange {
final num x;
final num y;
ChartDataRange(this.x, this.y);
}
//**********************************************************************
class ChartDataForce {
final num x;
final num y;
ChartDataForce(this.x, this.y);
}
My goal is to let a user selected image (via image_picker) and then use an eraser type tool to modify that image and make it transparent. Any ideas on how I should go about this?
Simple example:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:image_edit/image_edit_screen.dart';
import 'package:image_edit/image_processor.dart';
import 'dart:ui' as ui;
void main() => runApp(
ProviderScope(
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyApp(),
),
),
);
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
_enterImageEditController() async {
final imageBytes =
await ImageProcessor.getImageBytesAsset('lib/basic_0_people.png');
final bgImageBytes =
await ImageProcessor.getImageBytesAsset('lib/eraser_bg.jpg');
ui.decodeImageFromList(imageBytes, (result) async {
ui.decodeImageFromList(bgImageBytes, (bgResult) async {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (BuildContext ctx) => ImageEditScreen(
imageBytes: imageBytes,
bgImageBytes: bgImageBytes,
image: result,
bgImage: bgResult,
),
),
);
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromARGB(255, 56, 66, 66),
floatingActionButtonLocation: FloatingActionButtonLocation.centerTop,
floatingActionButton: Wrap(
direction: Axis.horizontal,
children: [
Center(
child: ElevatedButton(
onPressed: () {
_enterImageEditController();
},
child: Text(
'ImageEdit Controller',
style: TextStyle(fontSize: 25),
),
),
),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class ImageProcessor {
static Future<Uint8List> getImageBytesAsset(String path) async {
WidgetsFlutterBinding.ensureInitialized();
final byteData = await rootBundle.load(path);
final uint8List = Uint8List.view(byteData.buffer);
return uint8List;
}
}
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:ui' as ui;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:image_edit/image_edit_service.dart';
class ImageEditScreen extends StatelessWidget {
final Uint8List imageBytes;
final Uint8List bgImageBytes;
final ui.Image image;
final ui.Image bgImage;
ImageEditScreen({
Key? key,
required this.imageBytes,
required this.bgImageBytes,
required this.image,
required this.bgImage,
}) : super(key: key);
GlobalKey bgImageKey = GlobalKey();
GlobalKey imageKey = GlobalKey();
GlobalKey bgImageEraserKey = GlobalKey();
GlobalKey imageEraserKey = GlobalKey();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.cyanAccent,
floatingActionButtonLocation: FloatingActionButtonLocation.centerTop,
floatingActionButton: Wrap(
direction: Axis.horizontal,
children: [
Center(
child: FittedBox(
child: SizedBox(
width: image.width.toDouble(),
height: image.height.toDouble(),
child: Consumer(
builder: (context, ref, child) {
return GestureDetector(
onPanStart: (details) {
final imageEditService =
ref.read(imageEditProvider.notifier);
imageEditService.startEdit(details.localPosition);
},
onPanUpdate: (details) {
final imageEditService =
ref.read(imageEditProvider.notifier);
imageEditService.updateEdit(details.localPosition);
},
child: Container(
color: Colors.transparent,
child: Stack(
children: [
Positioned.fill(
child: RepaintBoundary(
key: bgImageKey,
child: ImageEditPaint(
canvasPaths: [],
image: bgImage,
),
),
),
Positioned.fill(
child: Consumer(
builder: (context, ref, child) {
final imageEditState =
ref.watch(imageEditProvider);
return RepaintBoundary(
key: imageEraserKey,
child: ImageEditPaint(
canvasPaths: imageEditState.eraserPath,
image: image,
),
);
},
),
),
],
),
),
);
},
),
),
),
),
Center(
child: Consumer(
builder: (context, ref, child) {
return ElevatedButton(
child: Text(
'undo',
style: TextStyle(
fontSize: 25,
),
),
onPressed: () {
final imageEditService =
ref.read(imageEditProvider.notifier);
imageEditService.undo();
},
);
},
),
),
],
),
);
}
Future<Uint8List> takeScreenShot(GlobalKey screenshotKey) async {
RenderRepaintBoundary boundary = screenshotKey.currentContext!
.findRenderObject() as RenderRepaintBoundary;
ui.Image image = await boundary.toImage();
ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData!.buffer.asUint8List();
return pngBytes;
}
}
class ImageEditPaint extends StatelessWidget {
final List<PlaygroundEraserCanvasPath> canvasPaths;
final ui.Image image;
const ImageEditPaint({
Key? key,
required this.canvasPaths,
required this.image,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return CustomPaint(
isComplex: true,
willChange: true,
foregroundPainter: EraserPainter(
canvasPaths: canvasPaths,
image: image,
),
);
}
}
class EraserPainter extends CustomPainter {
final List<PlaygroundEraserCanvasPath> canvasPaths;
final ui.Image image;
EraserPainter({
required this.canvasPaths,
required this.image,
});
#override
void paint(Canvas canvas, Size size) {
canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), Paint());
canvas.drawImage(
image,
Offset.zero,
Paint()..filterQuality = FilterQuality.high,
);
if (canvasPaths.isNotEmpty) {
for (var canvasPath in canvasPaths) {
if (canvasPath.drawPoints.isNotEmpty) {
var eraserPaint = Paint()
..strokeWidth = 50
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..strokeJoin = StrokeJoin.round
..blendMode = BlendMode.clear;
for (int i = 0; i < canvasPath.drawPoints.length; i++) {
Offset drawPoint = canvasPath.drawPoints[i];
if (canvasPath.drawPoints.length > 1) {
if (i == 0) {
canvas.drawLine(drawPoint, drawPoint, eraserPaint);
} else {
canvas.drawLine(
canvasPath.drawPoints[i - 1], drawPoint, eraserPaint);
}
} else {
canvas.drawLine(drawPoint, drawPoint, eraserPaint);
}
}
}
}
}
canvas.restore();
}
#override
bool shouldRepaint(covariant EraserPainter oldDelegate) => true;
}
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final imageEditProvider =
StateNotifierProvider.autoDispose<ImageEditService, ImageEditState>((ref) {
return ImageEditService();
});
class ImageEditService extends StateNotifier<ImageEditState> {
ImageEditService()
: super(ImageEditState(
editType: EditType.eraser, eraserPath: [], paintPath: []));
PlaygroundEraserCanvasPath _currentPath =
PlaygroundEraserCanvasPath(drawPoints: []);
void startEdit(Offset position) {
_currentPath = PlaygroundEraserCanvasPath(drawPoints: [position]);
if (state.editType == EditType.eraser) {
_editingHistory.add(EditType.eraser);
List<PlaygroundEraserCanvasPath> tempList = List.from(state.eraserPath);
tempList.add(_currentPath);
state = state.copyWith(eraserPath: tempList);
} else {
_editingHistory.add(EditType.paint);
List<PlaygroundEraserCanvasPath> tempList = List.from(state.paintPath);
tempList.add(_currentPath);
state = state.copyWith(paintPath: tempList);
}
}
void updateEdit(Offset position) {
_currentPath.drawPoints.add(position);
if (state.editType == EditType.eraser) {
List<PlaygroundEraserCanvasPath> tempList = List.from(state.eraserPath);
tempList.last = _currentPath;
state = state.copyWith(eraserPath: tempList);
} else {
List<PlaygroundEraserCanvasPath> tempList = List.from(state.paintPath);
tempList.last = _currentPath;
state = state.copyWith(paintPath: tempList);
}
}
List<EditType> _editingHistory = [];
void undo() {
if (_editingHistory.isEmpty) return;
final historyLast = _editingHistory.last;
if (historyLast == EditType.eraser) {
List<PlaygroundEraserCanvasPath> tempList = List.from(state.eraserPath);
tempList.removeLast();
state = state.copyWith(eraserPath: tempList);
} else {
List<PlaygroundEraserCanvasPath> tempList = List.from(state.paintPath);
tempList.removeLast();
state = state.copyWith(paintPath: tempList);
}
_editingHistory.removeLast();
}
void updateEditType() {
state = state.copyWith(
editType:
state.editType == EditType.eraser ? EditType.paint : EditType.eraser,
);
}
}
class PlaygroundEraserCanvasPath {
final List<Offset> drawPoints;
PlaygroundEraserCanvasPath({
required this.drawPoints,
});
}
#immutable
class ImageEditState {
EditType editType;
List<PlaygroundEraserCanvasPath> eraserPath;
List<PlaygroundEraserCanvasPath> paintPath;
ImageEditState({
required this.editType,
required this.eraserPath,
required this.paintPath,
});
ImageEditState copyWith({
EditType? editType,
List<PlaygroundEraserCanvasPath>? eraserPath,
List<PlaygroundEraserCanvasPath>? paintPath,
}) {
return ImageEditState(
editType: editType ?? this.editType,
eraserPath: eraserPath ?? this.eraserPath,
paintPath: paintPath ?? this.paintPath,
);
}
}
enum EditType {
eraser,
paint,
}
image example
What you need to do is not really straight forward but you can try image package out. So many things can be done with it.
I am trying to transfer the result of a query to a list but it is not working properly.
Below you will find the source code, it will be more clear.
I'm getting this error "type 'List' is not a subtype of type 'List'"
if the error is clear, I do not understand how to fix that.
I would like to get _allResults (contextName) into the list _context.
Many thanks for your help.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:gtd_official_sharped_focused/models/context.dart';
import 'package:multi_select_flutter/multi_select_flutter.dart';
String taskImportant;
String taskUrgent;
class EngagePage_Sept_2021 extends StatefulWidget {
EngagePage_Sept_2021({Key key, }):super(key:key);//this.title}) : super(key: key);
// final String title;
#override
_EngagePage_Sept_2021State createState() => _EngagePage_Sept_2021State();
}
class _EngagePage_Sept_2021State extends State<EngagePage_Sept_2021> {
TextEditingController _searchController = TextEditingController();
Future resultsLoaded;
List _allResults = [];
List _resultsList = [];
#override
void initState() {
super.initState();
_selectedContext = _allResults;//_context;
_searchController.addListener(_onSearchChanged);
}
#override
void dispose(){
_searchController.removeListener(_onSearchChanged);
_searchController.dispose();
super.dispose();
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
resultsLoaded = getUsersListOfTasksStreamSnapshots();
}
_onSearchChanged() {
searchResultsList();
}
/*static List<Contexts> _monTest = [
Contexts(contextName: ),
];
*/
static List<Contexts> _context = [. //Here, I would prefer to store the data.docs
Contexts(id: '1', contextName: "name 1"),
Contexts(id: '2', contextName: "name 2"),
Contexts(id: '3', contextName: "name 3"),
];
// static List<Contexts> _test = _allResults;
final _itemsContext = _context
.map((context) => MultiSelectItem<Contexts>(context, context.contextName))
.toList();
List<Contexts> _selectedContext = [];
final _multiSelectKeyContext = GlobalKey<FormFieldState>();
final _multiSelectKeyStatus = GlobalKey<FormFieldState>();
final _multiSelectKey4 = GlobalKey<FormFieldState>();
final _multiSelectKeyTime = GlobalKey<FormFieldState>();
searchResultsList() {
var showResults = [];
if(_searchController.text != "") {
for(var taskSnapshot in _allResults){
var title = Contexts.fromSnapshot(taskSnapshot).contextName.toLowerCase();
if(title.contains(_searchController.text.toLowerCase())) {
showResults.add(taskSnapshot);
}
}
} else {
showResults = List.from(_allResults);
}
setState(() {
_resultsList = showResults;
});
}
getUsersListOfTasksStreamSnapshots() async {
var data = await FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('contexts')
.get();
setState(() {
_allResults = data.docs;
print(_allResults);
});
searchResultsList();
return 'complete';
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('TEST CHIP'),
),
drawer: MyMenu(),
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Container(
alignment: Alignment.center,
padding: EdgeInsets.all(20),
child: Column(
children: <Widget>[
//################################################################################################
// CONTEXT - MultiSelectBottomSheetField with validators
//################################################################################################
MultiSelectBottomSheetField<Contexts>(
key: _multiSelectKeyContext,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: Text("Context"),
buttonText: Text("Context",style: TextStyle(fontSize: 18),),
items: _itemsContext,
searchable: true,
validator: (values) {
if (values == null || values.isEmpty) {
return "";
}
List<String> names = values.map((e) => e.contextName).toList();
return null;
},
onConfirm: (values) {
setState(() {
_selectedContext = values;
});
_multiSelectKeyContext.currentState.validate();
},
chipDisplay: MultiSelectChipDisplay(
onTap: (item) {
setState(() {
_selectedContext.remove(item);
});
_multiSelectKeyContext.currentState.validate();
},
),
),
SizedBox(height: 40),
//################################################################################################
// STATUS - MultiSelectBottomSheetField with validators
//################################################################################################
],
),
],
),
),
),
);
}
}
Model context
import 'package:cloud_firestore/cloud_firestore.dart';
class Contexts {
String id;
String contextName;
Contexts({
this.id,
this.contextName,
});
// formatting for upload to Firebase when creating the trip
Map<String, dynamic> toJson() =>
{
'context_Name': contextName,
};
//creating a Task object from a firebase snapshot
Contexts.fromSnapshot(DocumentSnapshot snapshot) :
id = snapshot.id,
contextName = snapshot['context_Name'];
}
I'm trying to get value from mysql database into my flutter project(these using pagination). i'm add custom data and its work. but cant fetch my database value
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:http/http.dart'as http;
class AllQuestion extends StatefulWidget {
String fldPaperTypeID;
AllQuestion({this.fldPaperTypeID});
#override
_AllQuestionState createState() => _AllQuestionState();
}
List<Question> _question;
List<Question> populateData;
QuestionDataSource _questionDataSource = QuestionDataSource();
List<Question> paginatedDataSource = [];
class _AllQuestionState extends State<AllQuestion> {
bool showLoadingIndicator = true;
Future<List> GetAllQuestion() async{
final response = await http.post('http://eduapp.studysmile.lk/getquestion',body: {"fldPaperTypeID":widget.fldPaperTypeID});
return json.decode(response.body);
}
#override
void initState() {
// TODO: implement initState
super.initState();
_question = populateData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Question'),
),
body: LayoutBuilder(
builder: (context, constraints) {
return Row(children: [
Column(
children: [
SizedBox(
height: constraints.maxHeight - 60,
width: constraints.maxWidth,
child: buildStack(constraints)),
Container(
height: 60,
width: constraints.maxWidth,
child: SfDataPager(
rowsPerPage: 1,
direction: Axis.horizontal,
onPageNavigationStart: (int pageIndex) {
setState(() {
showLoadingIndicator = true;
});
},
delegate: _questionDataSource,
onPageNavigationEnd: (int pageIndex) {
setState(() {
showLoadingIndicator = false;
});
},
),
)
],
),
]);
},
),
);
}
Widget buildDataGrid(BoxConstraints constraint) {
return SfDataGrid(
source: _questionDataSource,
columnWidthMode: ColumnWidthMode.fill,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridNumericColumn(mappingName: 'salaryS', headerText: 'Salary'),
]);
}
Widget buildStack(BoxConstraints constraints) {
List<Widget> _getChildren() {
final List<Widget> stackChildren = [];
stackChildren.add(buildDataGrid(constraints));
if (showLoadingIndicator) {
stackChildren.add(Container(
color: Colors.black12,
width: constraints.maxWidth,
height: constraints.maxHeight,
child: Align(
alignment: Alignment.center,
child: CircularProgressIndicator(
strokeWidth: 3,
),
),
));
}
return stackChildren;
}
return Stack(
children: _getChildren(),
);
}
/* List<Question> populateData() {
return [
Question(10001, 'James', 20000),
Question(10002, 'Kathryn', 30000),
Question(10001, 'James', 20000),
Question(10002, 'Kathryn', 30000),
Question(10001, 'James', 20000),
Question(10002, 'Kathryn', 30000),
Question(10001, 'James', 20000),
Question(10002, 'Kathryn', 30000),
Question(10001, 'James', 20000),
Question(10002, 'Kathryn', 30000),
];
}*/
Future<List<Question>> populateData()async{
final response = await http.post('http://eduapp.studysmile.lk/getquestion',body:
{"fldPaperTypeID":widget.fldPaperTypeID});
List<Question> populateData = json.decode(response.body);
return populateData;
}
}
/*
class SendallQuestion extends StatelessWidget {
List list;
SendallQuestion({this.list});
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: list == null?0:list.length,
itemBuilder: (ctx,i){
return Container(
alignment: Alignment.center,
margin: EdgeInsets.all(20),
child: FlatButton(
child: Align(
alignment: Alignment(0.2, 0.6),
child: Text(list[i]['fldQuestion'], style: TextStyle(fontSize: 20.0),)
),
color: Color(0xff7c4dff),
textColor: Colors.white,
onPressed: (){
},
),
);
}
);
}
}*/
class Question{
final int fldQuestionID;
final int fldPaperTypeID;
final String fldQuestion;
Question(this.fldPaperTypeID,this.fldQuestion,this.fldQuestionID);
}
class QuestionDataSource extends DataGridSource<Question> {
#override
List<Question> get dataSource => paginatedDataSource;
#override
Object getValue(Question question, String columnName) {
switch (columnName) {
case 'id':
return question.fldPaperTypeID;
break;
case 'name':
return question.fldQuestionID;
break;
case 'salaryS':
return question.fldQuestion;
break;
default:
return ' ';
break;
}
}
#override
int get rowCount => _question.length;
#override
Future<bool> handlePageChange(int oldPageIndex, int newPageIndex,
int startRowIndex, int rowsPerPage) async {
int endIndex = startRowIndex + rowsPerPage;
if (endIndex > _question.length) {
endIndex = _question.length - 1;
}
await Future.delayed(Duration(milliseconds: 2000));
paginatedDataSource = List.from(
_question.getRange(startRowIndex, endIndex).toList(growable: false));
notifyListeners();
return true;
}
}
this was my error message **lib/allquestionview.dart:42:17: Error: A value of type 'Future<List>' can't be assigned to a variable of type 'List'.
'Future' is from 'dart:async'.
'List' is from 'dart:core'.
'Question' is from 'package:studysmile/allquestionview.dart' ('lib/allquestionview.dart').
_question = populateData();
^**
in your case i guess this will do the trick :
List _question = List();
Future GetAllQuestion() async{
final response = await http.post('http://eduapp.studysmile.lk/getquestion',body: {"fldPaperTypeID":widget.fldPaperTypeID});
var data = json.decode(response.body);
setState(() {
_question= data;
});
}
void initState() {
// TODO: implement initState
super.initState();
this.GetAllQuestion();
}
Try this code. It works.
import 'package:http/http.dart' as http;
import 'package:json_helpers/json_helpers.dart';
Future main() async {
final list = await populateData();
print(list[0].fldQuestion);
}
Future<List<Question>> populateData() async {
final typeID = '1';
final response = await http.post(
Uri.parse('http://eduapp.studysmile.lk/getquestion'),
body: {'fldPaperTypeID': typeID});
if (response.statusCode == 200) {
return response.body.jsonList((e) => Question.fromJson(e));
} else {
throw 'Bad response';
}
}
class Question {
final String fldQuestionID;
final String fldPaperTypeID;
final String fldQuestion;
Question({this.fldPaperTypeID, this.fldQuestion, this.fldQuestionID});
factory Question.fromJson(Map<String, dynamic> json) {
return Question(
fldPaperTypeID: json['fldPaperTypeID'] as String,
fldQuestion: json['fldQuestion'] as String,
fldQuestionID: json['fldQuestionID'] as String);
}
}
Output:
1. දත්ත සැකසීමට පෙර වලංගුතාවය පරික්ෂා කිරීමේදී අනුගමනය කළ යුතු වඩාත් නිවැරදි අනුපිළිවෙල වන්නේ
i will display linechart from the database using datajson with flutter. but the reference that I can use is hardcode data. Please help
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:charts_flutter/flutter.dart' as charts;
int dataTotal = 0;
class GrafikSpbj extends StatefulWidget {
final List<charts.Series> seriesList;
final bool animate;
GrafikSpbj(this.seriesList, {this.animate});
/// Creates a [LineChart] with sample data and no transition.
factory GrafikSpbj.withSampleData() {
return new GrafikSpbj(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
#override
_GrafikSpbjState createState() => _GrafikSpbjState();
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
print(dataTotal);
final desktopSalesData = [
new LinearSales(0, 10),
new LinearSales(1, 50),
new LinearSales(2, 70),
new LinearSales(3, 100),
];
final tableSalesData = [
new LinearSales(0, 20),
new LinearSales(1, 40),
new LinearSales(2, 80),
new LinearSales(3, 100),
];
return [
new charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: desktopSalesData,
),
new charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: tableSalesData,
),
];
}
}
class _GrafikSpbjState extends State<GrafikSpbj> {
List data;
Timer timer;
int jumlahData = 0;
Future<List> _getData() async {
final response = await http.get("xxxxxxxxxxxxx");
setState(() {
data = json.decode(response.body);
jumlahData =data.length;
print(data[0]['id_spbj']);
print(data[0]['minggu_ke']);
print(data[0]['hasil']);
print(data[0]['target_grafik']);
});
return json.decode(response.body);
}
// makeRequest() async {
// var response = await http.get(
// 'xxxxxxxxxxxxxxxxxxxxxxx',
// headers: {'Accept': 'application/json'},
// );
// setState(() {
// data = json.decode(response.body);
// jumlahData =data.length;
// });
// }
#override
void initState() {
_getData();
dataTotal = jumlahData;
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: new Text("Input Pelanggan hal 2"),
),
body: Column(
children: <Widget>[
SizedBox(
width: 600.0,
height: 250.0,
child: new charts.NumericComboChart(widget.seriesList,
animate: widget.animate,
defaultRenderer: new charts.LineRendererConfig(),
customSeriesRenderers: [
new charts.PointRendererConfig(customRendererId: 'customPoint')
]),
),
new Text("data"),
new Text("data"),
new Text("data")
],
),
);
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}
values
[{"id_spbj":"1","minggu_ke":"1","hasil":"13.4353337","target_grafik":"25.00"},{"id_spbj":"1","minggu_ke":"2","hasil":"28.2629147","target_grafik":"25.00"},{"id_spbj":"1","minggu_ke":"3","hasil":"85.3285762","target_grafik":"25.00"},{"id_spbj":"2","minggu_ke":"1","hasil":"32.0184122","target_grafik":"25.00"},{"id_spbj":"2","minggu_ke":"2","hasil":"53.5296934","target_grafik":"25.00"}]
You can use FL_chart plugin library in flutter, where you draw all types of charts.
please find guideline to use FL_Chart