gpt4 book ai didi

dart - 如何触摸 Canvas ?

转载 作者:IT王子 更新时间:2023-10-29 06:41:48 24 4
gpt4 key购买 nike

这里是 Flutter 新手。我目前正在尝试使用 Flutter 构建一个简单的触摸绘图应用程序,但不知道如何触发 Canvas 重绘。

我的是这样的:我有一个 CustomPaint 小部件,其中包含一个 GestureDetector 子部件。每当发生触摸事件时,CustomPaint 的画家都会收到一条消息,并存储触摸坐标以在重新绘制时绘制路径。问题是,永远不会调用 paint 方法。

这是我目前的代码:

import 'package:flutter/material.dart';

class WriteScreen extends StatefulWidget {
@override
_WriteScreenState createState() => new _WriteScreenState();
}


class KanjiPainter extends CustomPainter {
Color strokeColor;
var strokes = new List<List<Offset>>();

KanjiPainter( this.strokeColor );

void startStroke(Offset position) {
print("startStroke");
strokes.add([position]);
}

void appendStroke(Offset position) {
print("appendStroke");
var stroke = strokes.last;
stroke.add(position);
}

void endStroke() {
}

@override
void paint(Canvas canvas, Size size) {
print("paint!");
var rect = Offset.zero & size;
Paint fillPaint = new Paint();
fillPaint.color = Colors.yellow[100];
fillPaint.style = PaintingStyle.fill;
canvas.drawRect(
rect,
fillPaint
);

Paint strokePaint = new Paint();
strokePaint.color = Colors.black;
strokePaint.style = PaintingStyle.stroke;

for (var stroke in strokes) {
Path strokePath = new Path();
// Iterator strokeIt = stroke.iterator..moveNext();
// Offset start = strokeIt.current;
// strokePath.moveTo(start.dx, start.dy);
// while (strokeIt.moveNext()) {
// Offset off = strokeIt.current;
// strokePath.addP
// }
strokePath.addPolygon(stroke, false);
canvas.drawPath(strokePath, strokePaint);
}
}

bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}


class _WriteScreenState extends State<WriteScreen> {
GestureDetector touch;
CustomPaint canvas;
KanjiPainter kanjiPainter;

void panStart(DragStartDetails details) {
print(details.globalPosition);
kanjiPainter.startStroke(details.globalPosition);
}

void panUpdate(DragUpdateDetails details) {
print(details.globalPosition);
kanjiPainter.appendStroke(details.globalPosition);
}

void panEnd(DragEndDetails details) {
kanjiPainter.endStroke();
}

@override
Widget build(BuildContext context) {
touch = new GestureDetector(
onPanStart: panStart,
onPanUpdate: panUpdate,
onPanEnd: panEnd,
);

kanjiPainter = new KanjiPainter( const Color.fromRGBO(255, 255, 255, 1.0) );

canvas = new CustomPaint(
painter: kanjiPainter,
child: touch,
// child: new Text("Custom Painter"),
// size: const Size.square(100.0),
);

Container container = new Container(
padding: new EdgeInsets.all(20.0),
child: new ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: new Card(
elevation: 10.0,
child: canvas,
)
)
);

return new Scaffold(
appBar: new AppBar(
title: new Text("Draw!")
),
backgroundColor: const Color.fromRGBO(200, 200, 200, 1.0),
body: container,
);
}
}

最佳答案

根据 CustomPainter docs每当需要重绘时,你必须通知 paint widget

The most efficient way to trigger a repaint is to either extend this class and supply a repaint argument to the constructor of the CustomPainter, where that object notifies its listeners when it is time to repaint, or to extend Listenable (e.g. via ChangeNotifier) and implement CustomPainter, so that the object itself provides the notifications directly. In either case, the CustomPaint widget or RenderCustomPaint render object will listen to the Listenable and repaint whenever the animation ticks, avoiding both the build and layout phases of the pipeline.

例如KanjiPainter 应该扩展 ChangeNotifier 并实现 CustomPainter。当您更改笔触时,调用 notifyListeners

而且 build 函数总是创建新的 KanjiPainter,这将删除所有旧数据。您可以在 initState 中初始化 painter 一次。

工作示例:

class WriteScreen extends StatefulWidget {
@override
_WriteScreenState createState() => _WriteScreenState();
}

class KanjiPainter extends ChangeNotifier implements CustomPainter {
Color strokeColor;
var strokes = <List<Offset>>[];

KanjiPainter(this.strokeColor);

bool hitTest(Offset position) => true;

void startStroke(Offset position) {
print("startStroke");
strokes.add([position]);
notifyListeners();
}

void appendStroke(Offset position) {
print("appendStroke");
var stroke = strokes.last;
stroke.add(position);
notifyListeners();
}

void endStroke() {
notifyListeners();
}

@override
void paint(Canvas canvas, Size size) {
print("paint!");
var rect = Offset.zero & size;
Paint fillPaint = Paint();
fillPaint.color = Colors.yellow[100]!;
fillPaint.style = PaintingStyle.fill;
canvas.drawRect(rect, fillPaint);

Paint strokePaint = new Paint();
strokePaint.color = Colors.black;
strokePaint.style = PaintingStyle.stroke;

for (var stroke in strokes) {
Path strokePath = new Path();
// Iterator strokeIt = stroke.iterator..moveNext();
// Offset start = strokeIt.current;
// strokePath.moveTo(start.dx, start.dy);
// while (strokeIt.moveNext()) {
// Offset off = strokeIt.current;
// strokePath.addP
// }
strokePath.addPolygon(stroke, false);
canvas.drawPath(strokePath, strokePaint);
}
}

bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}

@override
// TODO: implement semanticsBuilder
SemanticsBuilderCallback? get semanticsBuilder => null;

@override
bool shouldRebuildSemantics(covariant CustomPainter oldDelegate) {
// TODO: implement shouldRebuildSemantics
return true;
}
}

class _WriteScreenState extends State<WriteScreen> {
late GestureDetector touch;
late CustomPaint canvas;
late KanjiPainter kanjiPainter;

void panStart(DragStartDetails details) {
print(details.globalPosition);
kanjiPainter.startStroke(details.globalPosition);
}

void panUpdate(DragUpdateDetails details) {
print(details.globalPosition);
kanjiPainter.appendStroke(details.globalPosition);
}

void panEnd(DragEndDetails details) {
kanjiPainter.endStroke();
}

@override
void initState() {
super.initState();
kanjiPainter = new KanjiPainter(const Color.fromRGBO(255, 255, 255, 1.0));
}

@override
Widget build(BuildContext context) {
touch = new GestureDetector(
onPanStart: panStart,
onPanUpdate: panUpdate,
onPanEnd: panEnd,
);

canvas = new CustomPaint(
painter: kanjiPainter,
child: touch,
// child: new Text("Custom Painter"),
// size: const Size.square(100.0),
);

Container container = new Container(
padding: new EdgeInsets.all(20.0),
child: new ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: new Card(
elevation: 10.0,
child: canvas,
)));

return new Scaffold(
appBar: new AppBar(title: new Text("Draw!")),
backgroundColor: const Color.fromRGBO(200, 200, 200, 1.0),
body: container,
);
}
}

关于dart - 如何触摸 Canvas ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45578209/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com