简体   繁体   English

如果 Dart/Flutter 中的 onPressed() 属性中的 Else 条件问题

[英]If Else condition problem in onPressed() property in Dart/Flutter

I'm looking to highlight a button from a grid when it's pushed.我希望在按下时突出显示网格中的按钮。 Unfortunately, when I do so, the whole column lights up.不幸的是,当我这样做时,整个列都亮了。 As I'm new to flutter/Dart and to coding in general, I'm not sure if my problème is my lack of logic or something that I wouldn't know about that coding language?由于我是 flutter/Dart 和一般编码的新手,我不确定我的问题是我缺乏逻辑还是我对这种编码语言不了解?

The home page :主页:

import 'package:flutter/material.dart';
import 'package:sequencer_n_lignes/utilities/sequence_class.dart';

class Home extends StatefulWidget {
  @override
  _Home createState() => _Home();
}

class _Home extends State<Home> {
  int i = 0, y = 0, indexTempo = 0;
  int countChanel = 0, countBtn = 0;
  bool isPlaying = false;
  List<Button> btnList = List();
  List<Chanel> chanelList = List();

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        backgroundColor: Colors.grey[800],
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Container(
              margin: EdgeInsets.fromLTRB(20, 10, 20, 10),
              decoration: BoxDecoration(
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black,
                      blurRadius: 5,
                      spreadRadius: 1,
                    )
                  ],
                  color: Colors.grey[900],
                  border: Border.all(
                    color: Colors.white,
                    width: 0.5,
                  )),
              child: Row(
                children: <Widget>[
/*__________________________________________ADD/REMOVE BUTTONS___________________*/
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      IconButton(
                        icon: Icon(Icons.remove),
                        onPressed: () {
                          for (i = 0; i < 4; i++) {
                            btnList.removeLast();
                            countBtn--;
                          }
                          setState(() {});
                        },
                      ),
                      Text('BUTTONS: $countBtn'),
                      IconButton(
                        icon: Icon(
                          Icons.add,
                        ),
                        onPressed: () {
                          for (i = 0; i < 4; i++) {
                            btnList.add(Button(
                                id: countBtn,
                                onColor: Colors.blue,
                                offColor: Colors.grey[900],
                                state: false));
                            countBtn++;
                          }
                          setState(() {});
                        },
                      ),
                    ],
                  ), //
/*_________________________________________ADD/REMOVE CHANEL___________________*/
                  Row(
                    children: <Widget>[
                      IconButton(
                        icon: Icon(Icons.remove),
                        onPressed: () {
                          chanelList.removeLast();
                          countChanel--;
                          setState(() {});
                        },
                      ),
                      Text('CHANEL: $countChanel'),
                      IconButton(
                        icon: Icon(Icons.add),
                        onPressed: () {
                          chanelList.add(
                              Chanel(id: countChanel, buttonList: btnList));
                          countChanel++;
                          setState(() {});
                        },
                      ),
                    ],
                  ),
                  SizedBox(
                    width: 30,
                  ),
/*_____________________________________________CONTROLS___________________*/
                  Row(
                    children: <Widget>[
                      IconButton(
                        icon: Icon(
                          Icons.play_arrow,
                          color: (isPlaying) ? Colors.green : Colors.white,
                        ),
                        onPressed: () {
                          if (isPlaying)
                            isPlaying = false;
                          else
                            isPlaying = true;
                          setState(() {});
                        },
                      ),
                      IconButton(
                        icon: Icon(
                          Icons.stop,
                          color: (isPlaying) ? Colors.white : Colors.red[900],
                        ),
                        onPressed: () {
                          if (isPlaying)
                            isPlaying = false;
                          else
                            isPlaying = true;
                          setState(() {});
                        },
                      ),
                      IconButton(
                        icon: Icon(
                          Icons.refresh,
                          color: Colors.white,
                        ),
                        onPressed: () {
                          for (i = 0; i < chanelList.length; i++) {
                            for (y = 0; y < btnList.length; y++) {
                              chanelList[i].buttonList[y].state = false;
                            }
                          }
                          setState(() {});
                        },
                      ),
                      RaisedButton.icon(
                        icon: Icon(
                          Icons.details,
                          color: Colors.white,
                        ),
                        label: Text('OK'),
                        color: Colors.red[900],
                        onPressed: () {
                          setState(() {});
                        },
                      )
                    ],
                  ),
                ],
              ),
            ),
/*__________________________________________ GRID ___________________*/

            Column(
              children: List.generate(countChanel, (indexChanel) {
                return Padding(
                  padding: const EdgeInsets.fromLTRB(0, 5, 0, 5),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: List.generate(countBtn, (indexBtn) {
                      return Padding(
                        padding: EdgeInsets.fromLTRB(3, 0, 3, 0),
                        child: Container(
                          decoration: BoxDecoration(
                            boxShadow: [
                              BoxShadow(
                                color: Colors.black,
                                blurRadius: 0.1,
                                spreadRadius: 0.1,
                              ),
                            ],
                            border: Border.all(
                              color: Colors.white,
                              width: 0.5,
                            ),
                          ),
                          width: 80,
                          height: 80,
//THATS WHERE THE PROBLEM IS///////////////////////////
                              child: FlatButton(
    //                            child: Text(
    //                                '${chanelList[indexChanel].id.toString()} \n${chanelList[indexChanel].buttonList[indexBtn].id.toString()}\n$indexChanel-$indexBtn\n${chanelList[indexChanel].buttonList[indexBtn].state}'),
                                color: (chanelList[indexChanel]
                                        .buttonList[indexBtn]
                                        .state)
                                    ? chanelList[indexChanel]
                                        .buttonList[indexBtn]
                                        .onColor
                                    : chanelList[indexChanel]
                                        .buttonList[indexBtn]
                                        .offColor,
                                onPressed: () {
                                  if (chanelList[indexChanel]
                                      .buttonList[indexBtn]
                                      .state) {
                                    chanelList[indexChanel]
                                        .buttonList[indexBtn]
                                        .state = false;
                                  } else {
                                    chanelList[indexChanel]
                                        .buttonList[indexBtn]
                                        .state = true;
                                  }
                                  setState(() {});
                                },
                              ),
                            ),
                          );
                        }),
                      ),
                    );
                  }),
                ),
              ],
            ),
          ),
        );
      }
    }

The class班上

class Button {
  int id;
  Color onColor = Colors.red[900], offColor = Colors.grey[900];
  Color actualColor;
  bool state = false;

  Button({this.id, this.onColor, this.offColor, this.state});
}

class Chanel {
  int id;
  List<Button> buttonList;
  Chanel({this.id, this.buttonList});
}

Screen shot of the app应用程序的屏幕截图

Pretty big code but I think the problem is that whenever you add a new Channel, you are giving it an existen buttonList.相当大的代码,但我认为问题是每当你添加一个新频道时,你都会给它一个现有的按钮列表。 Try creating a new buttonList when you add a new Channel添加新频道时尝试创建新的 buttonList

chanelList.add(
    Chanel(
        id: countChanel,
        // Here is your problem, the reference to the buttons is the same
        // in all channels. Try creating new buttons for every channel
        buttonList: btnList,
    ),
);

I'll go over some of the programming logic improvements 1st and then explain why you are getting unexpected results.我将首先回顾一些编程逻辑的改进,然后解释为什么你会得到意想不到的结果。

1) Color actualColor inside Button class is never used, remove it. 1) Button 类中的颜色 actualColor 从未使用过,将其删除。

2) Unless each button is going to have different onColor and offColor I suggest moving those two out of the Button class or at least declare them as static. 2) 除非每个按钮都有不同的 onColor 和 offColor,否则我建议将这两个从 Button 类中移出,或者至少将它们声明为静态。 You are needlessly instantiating them over and over again when I'm guessing you only need those once, this is a very tiny memory improvement (especially since you won't have thousands of buttons) but more importantly removing those from the Button class or making them static will make your code easier to read and understand, as well as cut down the number of arguments needed to pass to the constructor (again cleaner code).当我猜你只需要一次时,你不必要地一遍又一遍地实例化它们,这是一个非常小的内存改进(特别是因为你不会有数千个按钮)但更重要的是从 Button 类中删除它们或制作它们静态将使您的代码更易于阅读和理解,并减少传递给构造函数所需的参数数量(再次更清晰的代码)。

3) Your loop counters "i" and "y", declare them where they are needed. 3)你的循环计数器“i”和“y”,在需要的地方声明它们。 Reduce the scope of the variable so that it is only visible in the scope where it is used.缩小变量的范围,使其仅在使用它的范围内可见。 There are many... many reasons for doing so, in a nutshell when a larger scope than necessary is used, code becomes less readable, harder to maintain, and more likely to reference unintended variables.这样做有很多...很多原因,简而言之,当使用的范围大于必要时,代码变得不那么可读,更难维护,并且更有可能引用非预期的变量。


Now for your actual problem.现在针对您的实际问题。 The problem isn't with if/else statements it has to do with lists and how they are handled in memory.问题不在于 if/else 语句,它与列表以及它们在内存中的处理方式有关。 Going back to my 3rd point above, always use the smallest scope possible.回到我上面的第三点,始终使用尽可能小的范围。 You are declaring your btnList here你在这里声明你的 btnList

class _Home extends State<Home> {
  int i = 0, y = 0, indexTempo = 0;
  int countChanel = 0, countBtn = 0;
  bool isPlaying = false;
  List<Button> btnList = List();
  List<Chanel> chanelList = List();

Later on you are adding that same btnList to different Channels here:稍后您将在此处将相同的 btnList 添加到不同的频道:

              Text('CHANEL: $countChanel'),
              IconButton(
                icon: Icon(Icons.add),
                onPressed: () {
                  chanelList.add(
                      Chanel(id: countChanel, buttonList: btnList));
                  countChanel++;
                  setState(() {});
                },

I suggest going back to basics and learn in general about arrays , lists and pointers .我建议回归基础并大体了解数组、列表和指针 You should also search for deep and shallow copying.您还应该搜索深拷贝和浅拷贝。 What you've done in the code block above is setting the same btnList to all of the chanelList items.您在上面的代码块中所做的是为所有 chanelList 项目设置相同的 btnList。

Lets say you create btnList that has 4 items.假设您创建了具有 4 个项目的 btnList。 Lets say you create channelList that has 2 items.假设您创建了具有 2 个项目的 channelList。 Then channelList[ 0 ].buttonList[ 0 ].state will always be the same as channelList[ 1 ].buttonList[ 0 ].state because they are both pointing to the same Button.那么 channelList[ 0 ].buttonList[ 0 ].state 将始终与 channelList[ 1 ].buttonList[ 0 ].state 相同,因为它们都指向同一个 Button。

To get this:要得到这个:

工作代码示例

Quick and easy fix would be to do something like this:快速简便的解决方法是做这样的事情:

              IconButton(
                icon: Icon(Icons.add),
                  onPressed: () {
                  List<Button> tmpBtnList = new List<Button>();  
                  for(int i=0; i<btnList.length; i++){
                    tmpBtnList.add(new Button(id: i,state: false));
                  }
                  chanelList.add(
                      Chanel(id: countChanel, buttonList: tmpBtnList));
                  countChanel++;
                  setState(() {});
                },
              ),

Complete code on DartPad. DartPad 上的完整代码。

PS I would also refrain from manually counting list items like you've done, just use the the provided .length. PS 我也不会像你所做的那样手动计算列表项,只需使用提供的 .length。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM