flutter - 如何从Stateless类中的onPressed调用StatefulWidget的方法?

标签 flutter button statefulwidget

我正在学习 flutter,作为第一个应用程序,我选择制作一个计算器。我已经设置了布局,现在需要对数据进行一些处理。问题的核心是我想在每次按下按钮时更改输出(即 StatefullWidget)。

这是我的 main.dart,我在其中使用自定义小部件 OutputWindow 和 Numberlane。

import 'package:flutter/material.dart';
import 'package:study_project/NumberLane.dart';
import 'NumberLane.dart';
import 'OutputWindow.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.

  var custom = OutputWindow();
  //Function f = custom.outputText;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(
                centerTitle: true,
                title: const Text("calculator"),
                titleTextStyle: const TextStyle(
                  fontWeight: FontWeight.bold,
                  fontSize: 25,
                )),
            body: Column(
                //mainAxisAlignment: MainAxisAlignment.center,'
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  //textoutput
                  Expanded(child: OutputWindow()),
                  //input
                  Expanded(
                    child: NumberLane(4),
                  ),
                  Expanded(
                    child: NumberLane(3),
                  ),
                  Expanded(
                    child: NumberLane(2),
                  ),
                  Expanded(
                    child: NumberLane(1),
                  ),
                ])));
  }
}

Numberlane 的存在只是为了使代码更具可读性,其唯一目的是使用另一个自定义类 Button 填充行

import 'package:flutter/material.dart';
import 'Button.dart';

class NumberLane extends StatelessWidget {
  int positioning = 0;

  NumberLane(this.positioning);

  @override
  Widget build(BuildContext context) {
    if (positioning == 1) {
      return Row(
        //crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(child: Button(".")),
          Expanded(child: Button("0")),
          Expanded(child: Button("=")),
          Expanded(child: Button("/")),
        ],
      );
    } else if (positioning == 2) {
      return Row(
        //crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(child: Button("1")),
          Expanded(child: Button("2")),
          Expanded(child: Button("3")),
          Expanded(child: Button("+")),
        ],
      );
    } else if (positioning == 3) {
      return Row(
        //crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(child: Button("4")),
          Expanded(child: Button("5")),
          Expanded(child: Button("6")),
          Expanded(child: Button("-")),
        ],
      );
    } else if (positioning == 4) {
      return Row(
        //crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(child: Button("7")),
          Expanded(child: Button("8")),
          Expanded(child: Button("9")),
          Expanded(child: Button("*")),
        ],
      );
    } else {}
  }
}

问题来了。我有我的 TextButtons,并且从 onPressed 中我需要调用 outputText 方法,该方法是 StatefullWidget OutputWindow 的属性。理想情况下,我希望每次点击按钮时都更改 OutputWindow。

**按钮

import 'package:flutter/material.dart';
import 'OutputWindow.dart';

class Button extends StatelessWidget {
  String description;
  //final Function outputText;
  Button(this.description) {}

  @override
  Widget build(BuildContext context) {
    return Container(
        width: double.infinity,
        height: double.infinity,
        child: TextButton(
          onPressed: () => {/*****here********/ },
          style: TextButton.styleFrom(
              primary: const Color.fromARGB(255, 227, 100, 61)),
          child: Text(
            description,
            style: const TextStyle(color: Color.fromARGB(255, 235, 88, 43)),
          ),
        ));
  }
}

**输出窗口

import 'package:flutter/material.dart';
import 'package:study_project/Button.dart';
import 'NumberLane.dart';
import 'main.dart';

class OutputWindow extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState

    return OutputWindowState();
  }
}

class OutputWindowState extends State<OutputWindow> {
  String output = "0";

  void outputText(String write) {
    setState(() {
      if (output == "0" ||
          write == "." ||
          write == "+" ||
          write == "-" ||
          write == "*" ||
          write == "/" ||
          write == "=") {
        output = write;
      } else if (write != "." &&
          write != "+" &&
          write != "-" &&
          write != "*" &&
          write != "/" &&
          write != "=") {
        output += write;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Text(output,
        style: const TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 35,
          color: Colors.black87,
        ));
  }
}

我已尝试导入所有包和文件,但仍然无法调用 OutputWindow 的方法和实例化以及通过 Instance.method() 调用该方法。我想到的另一件事是通过指针传递函数到构造函数,但这只适用于小部件树,我无法从 OutputWindow 获取方法到 main.dart。

非常感谢您的帮助。

最佳答案

我添加了一些代码,因此它可以工作。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: Home());
  }
}

String outputText = "";

class Home extends StatefulWidget {
  const Home({
    Key? key,
  }) : super(key: key);

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  String output = '';

  @override
  void initState() {
    super.initState();
    outputText = output;
  }


  changeOutut(String value) {
    outputText = value;
    setState(() {
      output = value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            centerTitle: true,
            title: const Text("calculator"),
            titleTextStyle: const TextStyle(
              fontWeight: FontWeight.bold,
              fontSize: 25,
            )),
        body: Column(
            //mainAxisAlignment: MainAxisAlignment.center,'
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              //textoutput
              Expanded(
                  child: OutputWindow(
                output: output,
              )),
              //input
              Expanded(
                child: NumberLane(4, changeOutut),
              ),
              Expanded(
                child: NumberLane(3, changeOutut),
              ),
              Expanded(
                child: NumberLane(2, changeOutut),
              ),
              Expanded(
                child: NumberLane(1, changeOutut),
              ),
            ]));
  }
}

class NumberLane extends StatelessWidget {
  final int positioning;
  final dynamic changeOutut;
  const NumberLane(this.positioning, this.changeOutut, {Key? key})
      : super(key: key);

  add(String value) {
    changeOutut(outputText + value);
  }

  @override
  Widget build(BuildContext context) {
    if (positioning == 1) {
      return Row(
        //crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(child: Button(".",add)),
          Expanded(child: Button("0",add)),
          Expanded(child: Button("=",add)),
          Expanded(child: Button("/",add)),
        ],
      );
    } else if (positioning == 2) {
      return Row(
        //crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(child: Button("1",add)),
          Expanded(child: Button("2",add)),
          Expanded(child: Button("3",add)),
          Expanded(child: Button("+",add)),
        ],
      );
    } else if (positioning == 3) {
      return Row(
        //crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(child: Button("4",add)),
          Expanded(child: Button("5",add)),
          Expanded(child: Button("6",add)),
          Expanded(child: Button("-",add)),
        ],
      );
    } else if (positioning == 4) {
      return Row(
        //crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(child: Button("7",add)),
          Expanded(child: Button("8",add)),
          Expanded(child: Button("9",add)),
          Expanded(child: Button("*",add)),
        ],
      );
    } else {
      return SizedBox();
    }
  }
}

class Button extends StatelessWidget {
  final String description;
  final dynamic add;
  const Button(this.description,this.add, {Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
        width: double.infinity,
        height: double.infinity,
        child: TextButton(
          onPressed: () => {
            add(description),
          },
          style: TextButton.styleFrom(
              primary: const Color.fromARGB(255, 227, 100, 61)),
          child: Text(
            description,
            style: const TextStyle(color: Color.fromARGB(255, 235, 88, 43)),
          ),
        ));
  }
}

class OutputWindow extends StatelessWidget {
  final String output;
  const OutputWindow({Key? key, required this.output}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(output,
        style: const TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 35,
          color: Colors.black87,
        ));
  }
}

关于flutter - 如何从Stateless类中的onPressed调用StatefulWidget的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72947889/

相关文章:

flutter - 为什么Flutter PageView在setState后重置为第0页

dart - 有没有办法从 setMethodCallHandler 获取 Future?

ios - 如何用swift添加一个圆形按钮?

dart - 如何在 StatelessWidget 中更改 StatefulWidget 的状态?

flutter - 我几乎每次都将 Stateless Widget 与 BLoC 一起使用。我错了吗?

flutter - 如果 Flutter 中的有状态小部件可以实现同样的功能,为什么我们需要无状态小部件?

flutter - SliverAppBar (Flutter) 中的最小高度?

flutter - 警告 : Operand of null-aware operation '!' has type 'PaintingBinding' which excludes null

javascript - 按钮单击触发下面的文本

java - 如何使按钮每秒在布局中随机移动