Python Forum

Full Version: how to add two numbers and pass the result to the next page in tkinter?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I am new to tkinter. I want to add two numbers and pass the result to the second page. in my code, I don't understand why instead of adding the numbers, it attaches them and shows them on the second page. I have introduced them as integers, but it still recognizes them as strings.

import tkinter as tk
from tkinter import *

Title_Font = ("Helvetica", 16, "bold")
Label_Font = ("Helvetica", 10)


class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)
        self.title("Summation App")
        container.pack()

        self.frames = {}
        for F in (PageOne, PageTwo):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
            self.geometry("400x400")

        self.show_frame(PageOne)

    def show_frame(self, c):
        frame = self.frames[c]
        frame.tkraise()


class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        self.frame1 = tk.LabelFrame(self, text="This is page one", font=Title_Font)
        self.frame1.pack(padx=10, pady=10)

        label1 = tk.Label(self.frame1, text= "First No.", font = Label_Font)
        label1.grid(row=0, column=0)

        label2 = tk.Label(self.frame1, text= "Second No.", font = Label_Font)
        label2.grid(row=1, column=0)

        first_no = IntVar()
        second_no = IntVar()

        self.entry1 = tk.Entry(self.frame1, textvariable=first_no)
        self.entry1.grid(row=0, column=1)

        self.entry2 = tk.Entry(self.frame1, textvariable=second_no)
        self.entry2.grid(row=1, column=1)

        button1 = tk.Button(self.frame1, text="Go to Page Two", command=lambda: self.go_to_page_two(), font=Label_Font)
        button1.grid(row=4, column=0, padx=10, pady=10)

    def go_to_page_two(self):
        self.controller.SomeVar = self.entry1.get() + self.entry2.get()
        print(self.controller.SomeVar)
        self.controller.frames[PageTwo].correct_label()
        self.controller.show_frame(PageTwo)


class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        self.frame2 = tk.LabelFrame(self, text="This is page two", font=Title_Font)
        self.frame2.pack()

        self.label3 = tk.Label(self.frame2)
        self.label3.pack()

    def correct_label(self):
        self.label3.config(text=self.controller.SomeVar)


app = SampleApp()
app.mainloop()
Try changing line 56 to:
        self.controller.SomeVar = int (self.entry1.get()) + int (self.entry2.get())
Here's the whole thing.
import tkinter as tk
from tkinter import *
 
Title_Font = ("Helvetica", 16, "bold")
Label_Font = ("Helvetica", 10)
 
 
class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)
        self.title("Summation App")
        container.pack()
 
        self.frames = {}
        for F in (PageOne, PageTwo):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
            self.geometry("400x400")
 
        self.show_frame(PageOne)
 
    def show_frame(self, c):
        frame = self.frames[c]
        frame.tkraise()
 
 
class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
 
        self.frame1 = tk.LabelFrame(self, text="This is page one", font=Title_Font)
        self.frame1.pack(padx=10, pady=10)
 
        label1 = tk.Label(self.frame1, text= "First No.", font = Label_Font)
        label1.grid(row=0, column=0)
 
        label2 = tk.Label(self.frame1, text= "Second No.", font = Label_Font)
        label2.grid(row=1, column=0)
 
        first_no = IntVar()
        second_no = IntVar()
 
        self.entry1 = tk.Entry(self.frame1, textvariable=first_no)
        self.entry1.grid(row=0, column=1)
 
        self.entry2 = tk.Entry(self.frame1, textvariable=second_no)
        self.entry2.grid(row=1, column=1)
 
        button1 = tk.Button(self.frame1, text="Go to Page Two", command=lambda: self.go_to_page_two(), font=Label_Font)
        button1.grid(row=4, column=0, padx=10, pady=10)
 
    def go_to_page_two(self):
        self.controller.SomeVar = int (self.entry1.get()) + int (self.entry2.get())
        print(self.controller.SomeVar)
        self.controller.frames[PageTwo].correct_label()
        self.controller.show_frame(PageTwo)
 
 
class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
 
        self.frame2 = tk.LabelFrame(self, text="This is page two", font=Title_Font)
        self.frame2.pack()
 
        self.label3 = tk.Label(self.frame2)
        self.label3.pack()
 
    def correct_label(self):
        self.label3.config(text=self.controller.SomeVar)
 
 
app = SampleApp()
app.mainloop()
Oh, thank you so much.
You don't need a lambda expression for something like this:
command=lambda: self.go_to_page_two()
Instead use:
command=self.go_go_page_two
Only use a lambda if you want to specify arguments for the method call.

In this code you are creating a string by concatenating the strings in entry1 and entry2.
self.controller.SomeVar = self.entry1.get() + self.entry2.get()
I do not like Page1 having to know about things in Page2. For something small like this it is ok, but if you had several windows that share information, this way of keeping everything current quickly becomes unmaintainable. A better design splits out all the information you are working with into it's own entity. Frame 1 would change a value in this data entity. If Frame 2 has a display for that data, registers a function to call when the value of the data changes.
import tkinter as tk

class Data:
    """I an a data entity shared by the forms"""
    def __init__(self):
        self.first_no = tk.IntVar()
        self.second_no = tk.IntVar()
        self.someVar = tk.IntVar()


class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.title("Summation App")
        container = tk.Frame(self)
        container.pack()

        self.data = Data()
  
        self.frames = {}
        for F in (PageOne, PageTwo):
            frame = F(container, self.data)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
  
        # I knob about all the frames, so it is ok for me to reference parts of their API
        self.frames[PageOne].page_button.config(command=self.go_to_page_two)
        self.show_frame(PageOne)

    def go_to_page_two(self):
        # I do not update the the label.  There are limits
        self.data.someVar.set(self.data.first_no.get() + self.data.second_no.get())
        self.show_frame(PageTwo)
  
    def show_frame(self, c):
        frame = self.frames[c]
        frame.tkraise()
  
  
class PageOne(tk.Frame):
    def __init__(self, parent, data):
        super().__init__(parent)
        self.data = data
  
        self.frame1 = tk.LabelFrame(self, text="This is page one")
        self.frame1.pack(padx=10, pady=10)
  
        label1 = tk.Label(self.frame1, text= "First No.")
        label1.grid(row=0, column=0)
  
        label2 = tk.Label(self.frame1, text= "Second No.")
        label2.grid(row=1, column=0)
  
        self.entry1 = tk.Entry(self.frame1, textvariable=data.first_no)
        self.entry1.grid(row=0, column=1)
  
        self.entry2 = tk.Entry(self.frame1, textvariable=data.second_no)
        self.entry2.grid(row=1, column=1)
  
        self.page_button = tk.Button(self.frame1, text="Go to Page Two")
        self.page_button.grid(row=4, column=0, padx=10, pady=10)
  
  
class PageTwo(tk.Frame):
    def __init__(self, parent, data):
        super().__init__(parent)
        self.data = data
  
        self.frame2 = tk.LabelFrame(self, text="This is page two")
        self.frame2.pack()
  
        self.label3 = tk.Label(self.frame2)
        self.label3.pack()

        # When someone changes someVar I need to update the label
        data.someVar.trace('w', lambda a, b, c: self.correct_label())
  
    def correct_label(self):
        self.label3.config(text=self.data.someVar.get())
  
  
app = SampleApp()
app.mainloop()
(Feb-14-2022, 05:37 AM)deanhystad Wrote: [ -> ]You don't need a lambda expression for something like this:
command=lambda: self.go_to_page_two()
Instead use:
command=self.go_go_page_two
Only use a lambda if you want to specify arguments for the method call.

In this code you are creating a string by concatenating the strings in entry1 and entry2.
self.controller.SomeVar = self.entry1.get() + self.entry2.get()
I do not like Page1 having to know about things in Page2. For something small like this it is ok, but if you had several windows that share information, this way of keeping everything current quickly becomes unmaintainable. A better design splits out all the information you are working with into it's own entity. Frame 1 would change a value in this data entity. If Frame 2 has a display for that data, registers a function to call when the value of the data changes.
import tkinter as tk

class Data:
    """I an a data entity shared by the forms"""
    def __init__(self):
        self.first_no = tk.IntVar()
        self.second_no = tk.IntVar()
        self.someVar = tk.IntVar()


class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.title("Summation App")
        container = tk.Frame(self)
        container.pack()

        self.data = Data()
  
        self.frames = {}
        for F in (PageOne, PageTwo):
            frame = F(container, self.data)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
  
        # I knob about all the frames, so it is ok for me to reference parts of their API
        self.frames[PageOne].page_button.config(command=self.go_to_page_two)
        self.show_frame(PageOne)

    def go_to_page_two(self):
        # I do not update the the label.  There are limits
        self.data.someVar.set(self.data.first_no.get() + self.data.second_no.get())
        self.show_frame(PageTwo)
  
    def show_frame(self, c):
        frame = self.frames[c]
        frame.tkraise()
  
  
class PageOne(tk.Frame):
    def __init__(self, parent, data):
        super().__init__(parent)
        self.data = data
  
        self.frame1 = tk.LabelFrame(self, text="This is page one")
        self.frame1.pack(padx=10, pady=10)
  
        label1 = tk.Label(self.frame1, text= "First No.")
        label1.grid(row=0, column=0)
  
        label2 = tk.Label(self.frame1, text= "Second No.")
        label2.grid(row=1, column=0)
  
        self.entry1 = tk.Entry(self.frame1, textvariable=data.first_no)
        self.entry1.grid(row=0, column=1)
  
        self.entry2 = tk.Entry(self.frame1, textvariable=data.second_no)
        self.entry2.grid(row=1, column=1)
  
        self.page_button = tk.Button(self.frame1, text="Go to Page Two")
        self.page_button.grid(row=4, column=0, padx=10, pady=10)
  
  
class PageTwo(tk.Frame):
    def __init__(self, parent, data):
        super().__init__(parent)
        self.data = data
  
        self.frame2 = tk.LabelFrame(self, text="This is page two")
        self.frame2.pack()
  
        self.label3 = tk.Label(self.frame2)
        self.label3.pack()

        # When someone changes someVar I need to update the label
        data.someVar.trace('w', lambda a, b, c: self.correct_label())
  
    def correct_label(self):
        self.label3.config(text=self.data.someVar.get())
  
  
app = SampleApp()
app.mainloop()

Thank you very much. this method was perfect. I wondered to know if I had a function in my page one then how should I pass that to the next page. For example in this code I have added a function to open a text file and read that, and I want to pass those lines to the next page

import tkinter as tk
from tkinter import filedialog

class Data:

    def __init__(self):
        self.first_no = tk.IntVar()
        self.second_no = tk.IntVar()
        self.summ = tk.IntVar()


class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.title("Summation App")
        container = tk.Frame(self)
        container.pack()

        self.data = Data()

        self.frames = {}
        for F in (PageOne, PageTwo):
            frame = F(container, self.data)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.frames[PageOne].page_button.config(command=self.go_to_page_two)
        self.show_frame(PageOne)

    def go_to_page_two(self):
        self.data.summ.set(self.data.first_no.get() + self.data.second_no.get())
        self.show_frame(PageTwo)

    def show_frame(self, c):
        frame = self.frames[c]
        frame.tkraise()


class PageOne(tk.Frame):
    def __init__(self, parent, data):
        super().__init__(parent)
        self.data = data

        frame1 = tk.LabelFrame(self, text="This is page one")
        frame1.pack(padx=10, pady=10)

        label1 = tk.Label(frame1, text="First No.")
        label1.grid(row=0, column=0)

        label2 = tk.Label(frame1, text="Second No.")
        label2.grid(row=1, column=0)

        self.entry1 = tk.Entry(frame1, textvariable=data.first_no)
        self.entry1.grid(row=0, column=1)

        self.entry2 = tk.Entry(frame1, textvariable=data.second_no)
        self.entry2.grid(row=1, column=1)

        self.page_button = tk.Button(frame1, text="Go to Page Two")
        self.page_button.grid(row=3, column=0, padx=10, pady=10)

        label_1 = tk.Label(frame1, text="Import the file")
        label_1.grid(row=2, column=0, padx=10)

        def opentext():
            my_file = filedialog.askopenfilenames(initialdir="/pycharm", title="Select your file")
            with open(my_file, 'r') as infile1:
                lines = infile1.read()
                

        button1 = tk.Button(frame1, text="Open file(s)", command=opentext)
        button1.grid(row=2, column=1, padx=10, pady=10)

class PageTwo(tk.Frame):
    def __init__(self, parent, data):
        super().__init__(parent)
        self.data = data

        self.frame2 = tk.LabelFrame(self, text="This is page two")
        self.frame2.pack()

        self.label3 = tk.Label(self.frame2)
        self.label3.pack()

        # When someone changes summ, I need to update the label
        data.summ.trace('w', lambda a, b, c: self.correct_label())

    def correct_label(self):
        self.label3.config(text=self.data.summ.get())


app = SampleApp()
app.mainloop()
and in the textfile also there are a couple of numbers such as 1 2 3 4 5
It is not good user interface design to have controls in one "page" change displays in a second "page". It is not an absolute, but should give you pause. If you don't immediately see the results of your actions, how do you know that you performed the action correctly? For your example I would put a button in frame 2 that draws a dialog to enter values for first_no and second_no which are applied when you press the "Ok" button in the dialog, or ignored if you press the "Cancel" button.

I cannot tell you what is a good design for your application (I don't know what you are trying to achieve), but I can say you should be spending most of your programming time thinking about the user experience and relatively little time writing code.
(Feb-14-2022, 08:17 PM)deanhystad Wrote: [ -> ]It is not good user interface design to have controls in one "page" change displays in a second "page". It is not an absolute, but should give you pause. If you don't immediately see the results of your actions, how do you know that you performed the action correctly? For your example I would put a button in frame 2 that draws a dialog to enter values for first_no and second_no which are applied when you press the "Ok" button in the dialog, or ignored if you press the "Cancel" button.

I cannot tell you what is a good design for your application (I don't know what you are trying to achieve), but I can say you should be spending most of your programming time thinking about the user experience and relatively little time writing code.

You are right. I am a little new to tkinter. with this code for summation and the one I just said to open a textfile, I am trying to learn.
I want to make an app to get variables (from entry boxes, or from importing a file), and pass these variables through pages. This was an easy example I just created to learn the basics and then move to the harder cases.
Thank you
(Feb-14-2022, 08:17 PM)deanhystad Wrote: [ -> ]It is not good user interface design to have controls in one "page" change displays in a second "page". It is not an absolute, but should give you pause. If you don't immediately see the results of your actions, how do you know that you performed the action correctly? For your example I would put a button in frame 2 that draws a dialog to enter values for first_no and second_no which are applied when you press the "Ok" button in the dialog, or ignored if you press the "Cancel" button.

I cannot tell you what is a good design for your application (I don't know what you are trying to achieve), but I can say you should be spending most of your programming time thinking about the user experience and relatively little time writing code.

I am still working on this problem. I am so confused. could you please help me with that. imagine I have a text file with a few numbers in that, and I want to pass it as a string to the next page. I updated my code. I created a new attribute in Data class as a string (new_Var). I cannot figure out how to make the connection between my opentext() function and the new_Var.

import tkinter as tk
from tkinter import filedialog

class Data:

    def __init__(self):
        self.first_no = tk.IntVar()
        self.second_no = tk.IntVar()
        self.summ = tk.IntVar()
        self.new_Var = tk.StringVar()


class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.title("Summation App")
        container = tk.Frame(self)
        container.pack()

        self.data = Data()

        self.frames = {}
        for F in (PageOne, PageTwo):
            frame = F(container, self.data)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.frames[PageOne].page_button.config(command=self.go_to_page_two)
        self.show_frame(PageOne)

    def go_to_page_two(self):
        self.data.summ.set(self.data.first_no.get() + self.data.second_no.get())
        self.show_frame(PageTwo)


    def show_frame(self, c):
        frame = self.frames[c]
        frame.tkraise()


class PageOne(tk.Frame):
    def __init__(self, parent, data):
        super().__init__(parent)
        self.data = data

        frame1 = tk.LabelFrame(self, text="This is page one")
        frame1.pack(padx=10, pady=10)

        label1 = tk.Label(frame1, text="First No.")
        label1.grid(row=0, column=0)

        label2 = tk.Label(frame1, text="Second No.")
        label2.grid(row=1, column=0)

        self.entry1 = tk.Entry(frame1, textvariable=data.first_no)
        self.entry1.grid(row=0, column=1)

        self.entry2 = tk.Entry(frame1, textvariable=data.second_no)
        self.entry2.grid(row=1, column=1)

        self.page_button = tk.Button(frame1, text="Go to Page Two")
        self.page_button.grid(row=3, column=0, padx=10, pady=10)

        label3 = tk.Label(frame1, text="Import the file")
        label3.grid(row=2, column=0, padx=10)

        def opentext():
            my_file = filedialog.askopenfilenames(initialdir="/pycharm", title="Select your file")
            for T in my_file:
                with open(T, 'r') as infile1:
                    lines = infile1.read()
                    label4.config(text=lines)
                    return lines

        self.button1 = tk.Button(frame1, text="Open file(s)", command=opentext)
        self.button1.grid(row=2, column=1, padx=10, pady=10)

        label4 = tk.Label(frame1)
        label4.grid(row=3, column=1)

class PageTwo(tk.Frame):
    def __init__(self, parent, data):
        super().__init__(parent)
        self.data = data

        self.frame2 = tk.LabelFrame(self, text="This is page two")
        self.frame2.pack()

        self.label5 = tk.Label(self.frame2)
        self.label5.pack()

        self.label6 = tk.Label(self.frame2)
        self.label6.pack()

        # When someone changes summ, I need to update the label
        data.summ.trace('w', lambda a, b, c: self.correct_label())

    def correct_label(self):
        self.label5.config(text=self.data.summ.get())
        self.label6.config(text=self.data.new_Var)


app = SampleApp()
app.mainloop()