I’m a beginner in flutter and I’m trying to make new project for fun: A chess clock.
Once one of the buttons is pressed it should start running down but it doesn’t. Please take a look and tell me what I’m doing wrong. Try to just point it out and not code it because I don’t want to just copy and paste but figuring things out. I guess it must be something related to the variable scope…
Here is the main.dart file:
import 'package:flutter/material.dart';
import 'Clock.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Chessclock(),
),
Expanded(
child: Chessclock(),
)
]
)))
);
}
}
and here is the Clock.dart file:
import 'dart:io';
import 'package:flutter/material.dart';
class Chessclock extends StatefulWidget {
final tim;
Chessclock({Key? key,required this.tim}): super({});
var minutes = this.tim~/60;
var seconds = this.tim % 60;
var inGame = false;
var dur = const Duration(seconds: 1);
void runtime(t,b){
if(b){
sleep(dur);
_tim--;
}else{
return;
}
}
bool inswitch(inGam){
return !inGam;
}
@override
State<Chessclock> createState() => new _ChessclockState();
}
class _ChessclockState extends State<Chessclock>{
@override
// TODO: implement runtimeType
Widget build(BuildContext context) {
runtime(tim,inGame);
return TextButton(
child: Text('$minutes:$seconds',
style: TextStyle(fontSize: 30)
),
onPressed: () {
setState(() {
inGame = inswitch(inGame);
});
},
style: TextButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: (inGame? Colors.green : Colors.grey),
)
);
}
}
I know you will be nice because Dart coders are great guys…. 😀
2
Answers
All this stuff should be in _ChessclockState:
Moreover, you may need use state lifecycle method that will triggered first time and once after widget is created:
You should look deeper at state lyfecycle
https://flutterbyexample.com/lesson/stateful-widget-lifecycle#3-initstate
First of all, it’s not reasonable to claim
tim
as a final since you need to update it’s value in your case.If I don’t misunderstand your meaning, then you actually want to set a timer (in your case is the
ChessClock
which can countdown the time when triggered)For the countdown logic,we can directly use
Timer.periodic
class in Dart instead ofsleep()
, also notice the dart doc ofsleep()
Besides, in your code you want to call
runtime()
method in the state class, which in my opinion will not work and IDE should report error, if you really want to access property of the widget class from it’s state (in your example is accessingruntime()
inChessclock
inside the state class_ChessclockState
, you should use the keywordwidget
,for examplewidget.runtime()
in your state class)Also, in this part of your code
You use setState to call
inswitch()
method, which should handle the countdown logic and decresetim
inChessClock
every sec, as I mention above, the countdown logic in your code may cause some problem because of usingsleep()
Let’s assume that you have modified the code to use
Timer
and the countdown logic works well, but the UI will still not change every sec as intend in this time. This is because you have only callsetState()
one time when the button was pressed inonPressed
callback, however the tim actually is changing continuously.For this problem, there has one solution that you move the countdown logic into state class, then you can do something like:
Since you can access
setState()
inside the state class, now you can create a method calledtriggerCounting
which callssetState()
every time thewidget.tim
has been updated, this time the UI will be supposed to update every secHere is the full code (Notice my code is completely a new app which created just for example)
main.dart
clock.dart
I’m also learning Flutter now and maybe my solution is not the best one, and actually my solution still has some problems, like that the parent widget can not directly access the value of the timer, notice that not only
ClockExample
need to access and show thetim
info, the other part of the app may also need to know the value of the countdown, for example, the app may need to stop the game and show dialog when times ran out, so you may need to condsider pulling up the state to the widget above all widgets which need to access the state in the widgets tree, or you could consider using some state management package likeprovider
(Provider on pub.dev)