Home > Blockchain >  How to call method of StatefulWidget from onPressed which is in Stateless class?
How to call method of StatefulWidget from onPressed which is in Stateless class?

Time:07-12

I´m learning flutter and as a first app I chose to make a calculator. I have got the layout set and now I need to do some work with data. The core of the problem is that I would like to change output (which is StatefullWidget) every time I press a button.

This is my main.dart where I use my custom widgets OutputWindow and 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 is there just to make the code more readable and its only purpose is to fill rows with another custom class 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 {}
  }
}

And here comes the problem. I have my TextButtons and from onPressed I need to call outputText method which is property of StatefullWidget OutputWindow. I would ideally like to change OutputWindow every time a button is tapped.

**Button

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)),
          ),
        ));
  }
}

**OutputWindow

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,
        ));
  }
}

I have tried importing all packages and files but still couldn´t call the method and instantiation of my OutputWindow and calling the method via Instance.method(). Another thing that came my to mind is to pass function via pointer to constructor but that works only down the widget tree and I can´t get the method from OutputWindow to main.dart.

Thank you so much for your help.

CodePudding user response:

I have added some code so it will work.

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,
        ));
  }
}
  • Related