質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Q&A

解決済

1回答

3450閲覧

CustomPaintのpaintをTimerで更新したい

Y__A

総合スコア10

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

0グッド

0クリップ

投稿2020/07/03 16:48

前提・実現したいこと

Flutter初心者で不明点失礼致します。

表題の通りCustomPaintのpaintをTimerで更新したいものの
ボタンを押すとpaintが呼ばれ更新されるのですが、
TimerのFunction内でボタンと同じコードを書いてもpaintが呼ばれなく
解決方法が分からず困っております。

コードは以下のような感じです。

該当のソースコード

dart

1import 'dart:async'; 2import 'package:flutter/cupertino.dart'; 3import 'package:flutter/material.dart'; 4 5class PaintScene extends StatefulWidget { 6 PaintScene({Key key, this.title}) : super(key: key); 7 final String title; 8 9 10 _PaintScene createState() => _PaintScene(); 11} 12 13class _PaintScene extends State<PaintScene> { 14 _MyPainter painter = new _MyPainter(); 15 16 17 Widget build(BuildContext context) { 18 return Scaffold( 19 appBar: AppBar( 20 title: Text( 21 'タイトルタイトルタイト', 22 overflow: TextOverflow.ellipsis, 23 ), 24 ), 25 body: Container( 26 child: CustomPaint( 27 painter: painter, 28 ), 29 ), 30 floatingActionButton: FloatingActionButton( 31 onPressed: (){ 32 //painter.countUp(); 33 startTimer(); 34 }, 35 ), 36 ); 37 } 38 39 void startTimer() { 40 Timer.periodic( Duration(seconds: 1), (Timer timer) { 41 painter.countUp(); 42 }); 43 } 44 45} 46 47class _MyPainter extends CustomPainter { 48 int _count = 0; 49 50 void countUp(){ 51 _count ++; 52 print('countUp'); 53 } 54 55 56 void paint(Canvas canvas, Size size) { 57 // 描画 58 print('paint:' + _count.toString()); 59 } 60 61 62 bool shouldRepaint(CustomPainter oldDelegate) { 63 return true; 64 } 65} 66

試したこと

onPressedの中のpainter.countUp();を呼ぶと

countUp paint:0 paint:0 paint:0 paint:0

のような形で思ったようにpaintが呼ばれて出力されるのですが、

onPressedの中のpainter.startTimer();のほうを呼ぶと

countUp countUp countUp countUp

のように、メソッドは呼ばれているもののpaintが呼ばれていない感じになり
何が問題なのかが分からず困っておりまして、ご教示頂ければ大変助かります。

補足情報(FW/ツールのバージョンなど)

Flutter 1.19.0-4.2.pre
Tools • Dart 2.9.0 (build 2.9.0-14.1.beta)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

paint関数を呼び出す為には再描画を行う必要があります。
※countUp()関数を呼んでも再描画はされません。

onPressedの中のpainter.countUp();を呼ぶとのような形で思ったようにpaintが呼ばれて出力されるのですが、

とありますが、実はcountUp()の呼び出しの有無に関わらず「ボタンを押せば」再描画処理が行われ、paint関数は呼び出されています。これはボタンを押した時にボタンアニメーションを表現する為に画面を再描画しているからです。

次に、CustomPainterを任意のタイミングで再描画する方法について
CustomPainterクラスは初期化にListenableオブジェクトを受け取ることができます。
これは「知らせを受けた時に再描画する」為のものなので、まさに質問にあるような使い方を想定して用意された仕組みかと思われます。

参考
https://api.flutter.dev/flutter/rendering/CustomPainter/CustomPainter.html
https://stackoverflow.com/questions/57633554/custompainter-redraw-with-listenable

やりたいことの最小限のコードはこんな感じかと思います。

class PaintScene extends StatefulWidget { PaintScene({Key key, this.title}) : super(key: key); final String title; @override _PaintScene createState() => _PaintScene(); } class _PaintScene extends State<PaintScene> { // *** 通知用の Listenable オブジェクト *** final _counter = ValueNotifier<int>(0); _MyPainter painter; @override void initState() { super.initState(); // *** _MyPainter に _counter(Listenable) を渡して初期化 *** painter = _MyPainter(repaint: _counter); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text( 'タイトルタイトルタイト', overflow: TextOverflow.ellipsis, ), ), body: Container( child: CustomPaint( painter: painter, ), ), floatingActionButton: FloatingActionButton( onPressed: (){ startTimer(); }, ), ); } void startTimer() { Timer.periodic( Duration(seconds: 1), (Timer timer) { print("Routine with timer"); // *** 値を更新すると通知が painter に届く *** _counter.value++; }); } } class _MyPainter extends CustomPainter { _MyPainter({Listenable repaint}) : super(repaint: repaint); @override void paint(Canvas canvas, Size size) { // 描画 print('paint: ${DateTime.now().toString()}'); } @override bool shouldRepaint(CustomPainter oldDelegate) { return true; } }

投稿2020/07/04 11:03

編集2020/07/04 11:09
Kapustin

総合スコア1186

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Y__A

2020/07/04 11:11

ご丁寧にご教示頂き誠にありがとうございます! ボタンを押しただけで再描画されるのですね・・ものすごく為になりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問