我试图创建一个Gesture_detector,当按下一个图标时,该Gesture_detector会调用将来的函数。从下面的代码中调用包含这个action_detector的窗口小部件生成器。
`class MyHomePageState extends State<MyHomePage> {
File contentimage, style_image;
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('Neural Style transfer'),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
//I am calling the builder from here.
imagepreview_state().build_imagepreview(context, contentimage,'Content Image'),
imagepreview_state().build_imagepreview(context, style_image,'Style Image')
],
),
floatingActionButton: FloatingActionButton(
onPressed: (){
// image = await getImage_gallery(image);
},
tooltip: 'Pick Image',
child: Icon(Icons.add_a_photo),
),
),
);
}
}
`
以下包含构建器。
class imagepreview extends StatefulWidget {
imagepreview_state createState() => imagepreview_state();
}
class imagepreview_state extends State<imagepreview> {
noSuchMethod(Invocation i) => super.noSuchMethod(i);
File image;
final picker = ImagePicker();
//These future functions get the images from the respective sources when an icon is pressed
Future getImage_gallery(File _image) async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
_image = File(pickedFile.path);
setState(() {
_image = File(pickedFile.path);
});
return _image;
}
Future<File> getImage_camera(File _image) async {
final pickedFile = await picker.getImage(source: ImageSource.camera);
setState(() {
_image = File(pickedFile.path);
});
return _image;
}
Widget build_imagepreview(BuildContext context, File image, String title) {
return (Container(
padding: EdgeInsets.only(top: 30),
child: Column(children: <Widget>[
GestureDetector(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => MyDetailPage(image)));
},
child: Container(
height: 150,
width: 150,
child: image == null
? Text('No image selected.')
: Column(children: <Widget>[
Text(title),
SizedBox(
height: 5,
),
Container(
height: 120.0,
width: 120.0,
decoration: BoxDecoration(
image: DecorationImage(
image: FileImage(image),
fit: BoxFit.cover,
),
shape: BoxShape.rectangle,
),
)
]),
),
),
Container(
padding: EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
GestureDetector(
onTap: () async{
image = await getImage_camera(image);
},
child: Icon(
Icons.camera_alt,
color: Colors.blue,
size: 40.0,
semanticLabel: 'Text to announce in accessibility modes',
),
),
SizedBox(
width: 10,
),
GestureDetector(
onTap: () async{
image = await getImage_gallery(image);
},
child: Icon(
Icons.settings_system_daydream,
color: Colors.blue,
size: 40.0,
),
),
],
),
)
])));
}
}
问题:
有没有什么方法可以刷新构建而无需调用setstate()并在按下图标时做出反应?
答案 0 :(得分:0)
我认为您希望避免在此处调用setState()
的原因是您决定使用自己的构建器函数。我建议将build_imagepreview
替换为build
的{{1}}函数,以便您可以从imagepreview_state
调用setState()
。通过为GestureDetector
创建构造函数,您仍然可以通过content_image
的{{1}}属性传递style_image
和image
。此外,您可以将imagepreview_state
从异步功能中移出。
答案 1 :(得分:0)
您将需要使用setState()再次调用构建函数。问题是您没有使用继承的Build()函数。我猜这是因为您要将参数传递到imagepreview小部件中。解决此问题的一种方法是将参数作为类属性直接传递到小部件中,而不传递给自定义构建函数。附带说明,从技术上讲,这是正确构建窗口小部件树的方法,并且您不应在要创建的状态内调用方法。
然后您可以创建窗口小部件:
imagepreview(contentimage,'Content Image'),
imagepreview_(style_image,'Style Image')
然后您可以使用widget.propertyName在子级中访问这些文件。
现在确保使用
@override
Widget build(BuildContext context) {}
方法,然后setState()应该起作用。
如果您随后需要更新父窗口小部件中的所有内容,则还可以传入一个函数,包括在父窗口中调用setState()的函数。
希望这会有所帮助!