当布尔值为true时,我正试图激活一个按钮。我有一个类,它包含一个设置为false的bool。然后我有一个自定义的小部件,其中有一个最终的bool,当我在主应用程序中调用小部件时,我会将其设置为true。当最后一个bool为true时,我将类中的bool设置为true。然后我在按钮上使用三元运算符。我想做的是,当用户回答最后一个问题时,应该启用提交按钮。即使类bool设置为true,按钮也不会激活。如果我刷新页面,按钮就会激活。我认为这是一个州问题
附言:我删除了一些不必要的代码。
得分等级
class Score {
static int score = 0;
static bool allQuestionsAnswered = false; //THIS VARIABLE WILL BE CHANGED BASED ON THE FINAL VARIABLE
}
带有提交按钮的主小工具
class Quiz extends StatefulWidget {
const Quiz({Key? key}) : super(key: key);
@override
_QuizState createState() => _QuizState();
}
class _QuizState extends State<Quiz> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back_rounded),
onPressed: () {
var route = ModalRoute.of(context);
var name = route?.settings.name;
if (name == null) {
Score.score = 0;
Navigator.push(context,
MaterialPageRoute(builder: (context) => Homepage()));
}
},
),
title: const Text('CyberQuiz'),
),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Text('Score: ' + Score.score.toString()),
SizedBox(
height: 150,
),
Text(
'Online Behaviour Questions',
style: TextStyle(
fontSize: 35,
color: Colors.white,
),
),
SizedBox(
height: 20,
),
Text(
'Scale based answers, Strongly Disagree (1) to Agree (5)',
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
),
SizedBox(
height: 50,
),
OnlineBehaviour(
'6. I tend to use similar passwords for multiple accounts',
'Using the same password accross all online accounts, users give '
'hackers easy access to their whole digital life. It is like leaving '
'the keys under the doormat. If a hacker gains access to one user account,'
' he or she can easily take over all online account and impersonate them',
false),
SizedBox(
height: 80,
),
OnlineBehaviour(
'7. I like posting stuff on social media to socialise with my friends',
'While it may seem like'
'the information is being share with your friends and family,'
'it can also be share with hackers and scammers who troll the social media sites',
false),
SizedBox(
height: 80,
),
OnlineBehaviour(
'8. I have a lot of accounts, thus I am using a notebook to write them down',
'Anyone can take your notebook '
'and access all of your personal data including bank account credentials'
'.There are many programs out there that act as a safe "journal for passwords"',
false),
SizedBox(
height: 80,
),
OnlineBehaviour(
'9. I tend to ignore requests from apps to access my location, files, camera etc.',
'Ignoring these requests might be very dangerous'
"as many online predators are in a continuous hunt of new people's location and their personal data."
'E.g. They can check whether your are home or not and they can schedule a potential robbery',
false),
SizedBox(
height: 80,
),
OnlineBehaviour(
'10. I accept all terms & conditions of all apps/websites without reading them',
'All of us are guilty for this one because a lot of websites/apps have loads of pages '
'talking about their conditions when accessing their services. If you ignore these they might'
'use the data stored on you in bad ways such as selling it to other '
'dodgy companies who might use your data in malicious ways',
true), //THIS IS WHERE I SET THE FINAL VARIABLE TO TRUE
ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.orange)),
onPressed: Score.allQuestionsAnswered == true //THIS IS WHERE I USED TERNARY OPERATOR
? () {
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Well done!'),
content: Text(
'Score: ' + Score.score.toString()),
elevation: 24.0,
shape: RoundedRectangleBorder(),
actions: [
TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
Homepage()));
},
child: Text('OK'))
],
);
});
}
: null,
child: Text('Submit'))
],
)));
}
}
自定义小工具
class OnlineBehaviour extends StatefulWidget {
final String behaviourQuestion;
final String explanation;
final bool lastQuestionAnswered;
bool buttonTapped = false;
bool questionsAnswered = false;
OnlineBehaviour(
this.behaviourQuestion,
this.explanation,
this.lastQuestionAnswered,
);
@override
_OnlineBehaviourState createState() => _OnlineBehaviourState();
}
class _OnlineBehaviourState extends State<OnlineBehaviour> {
disableButton() {
setState(() {
widget.questionsAnswered = true;
});
}
activateSubmitButton() {
setState(() {
if (widget.lastQuestionAnswered == true) {
Score.allQuestionsAnswered = true; //FUNCTION THAT SETS THE BOOL IN THE SCORE CLASS TO TRUE
}
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text(
widget.behaviourQuestion,
style: TextStyle(fontSize: 30, color: Colors.white),
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Color(0xFF45687b))),
onPressed: widget.questionsAnswered == false
? () {
setState(() {
Score.score += 5;
activateSubmitButton();
widget.buttonTapped = true;
});
if (widget.buttonTapped == true) {
disableButton();
print(Score.allQuestionsAnswered);
}
}
: null,
child: Text(
'1',
style: TextStyle(
color: Color(0xFFe5e0e4),
fontSize: 15,
fontWeight: FontWeight.bold,
),
)),
我猜问题是,即使在更新了静态类的值之后,按钮仍然处于禁用状态。
如果这就是问题所在,那么这可能不是因为您未能更改值,也不是因为您的三元运算符错误,而是因为您没有告诉主窗口小部件再次检查静态类的值。为了做到这一点,您应该更改setState
方法中的值(您这样做了,但您使用自定义小部件的setState
方法来完成,这不会更新主小部件(。
有很多方法可以尝试和更改这一点,但我要做的是向您的自定义小部件onAllQuestionsAnswered
:声明一个新参数
在自定义小部件上
final String behaviourQuestion;
final String explanation;
final bool lastQuestionAnswered;
final VoidCallback onAllQuestionsAnswered; // <--
然后,当你设置静态类的值时,你可以这样做:
if (widget.lastQuestionAnswered == true) {
onAllQuestionsAnswered();
}
最后,在您的主窗口小部件上,您将传递以下回调:
OnlineBehaviour(
...
onAllQuestionsAnswered: () => setState(() =>Score.allQuestionsAnswered = true),
);
通常,您也可以完全去掉静态变量,只将状态存储在主小部件上,但这超出了这个答案的范围。
问题就在这里,你的Button onQuiz
小部件,但你正在更新OnlineBehaviour
小部件的状态,这就是为什么ui没有更新,我建议你使用state-management
,现在你可以使用回调方法。
在你的OnlineBehaviour
上,我添加了另一个可以为null的回调函数,这样你就只能使用一次,而不用使用其他的
class OnlineBehaviour extends StatefulWidget {
final String behaviourQuestion;
final String explanation;
final bool lastQuestionAnswered;
final Function? callBack;
bool buttonTapped = false;
bool questionsAnswered = false;
OnlineBehaviour(
this.behaviourQuestion,
this.explanation,
this.lastQuestionAnswered, {
this.callBack = null,
});
点击
onPressed: widget.questionsAnswered == false
? () {
if (widget.callBack != null) { // -<this
widget.callBack!();
}
setState(() {
Score.score += 5;
activateSubmitButton();
widget.buttonTapped = true;
});
if (widget.buttonTapped == true) {
disableButton();
print(Score.allQuestionsAnswered);
}
}
: null,
就在最后一个问题上,你想更新用户界面,请使用
OnlineBehaviour(
'10. I accept all terms & conditions of all apps/websites without reading them',
'All of us are guilty for this one because a lot of websites/apps have loads of pages '
'talking about their conditions when accessing their services. If you ignore these they might'
'use the data stored on you in bad ways such as selling it to other '
'dodgy companies who might use your data in malicious ways',
true,
callBack: () {
setState(() {});
},
), //THIS Is
问题不在于更新"所有问题都已回答";。您面临的问题是,您需要在初始化主窗口小部件后更新UI。您可以通过将其添加到主窗口小部件中来实现这一点,不需要来自其他类的回调:
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) =>
setState(() {});
}
此代码将确保您的小部件在完成初始化后将获得其UI的额外更新。