-2

The code for changing pages was derived from: Switch between two frames in tkinter

Hello, I've been trying to figure out how to convert this code for changing pages into something that I could use, but I had no luck with that :( . I've been trying to make these buttons not only switch page, but do 1 more simple command at the same time, I guess that somehow i should make 1 function that would do both things, instead of 2 separate functions, but I'm still quite new to python, and even more to tkinter and everytime when i try to change these buttons commands or functions i get some kind of error, it seems that i can't find a way to do it, could you help me with that? Thanks in advance.

Edit: I have deleted some some code which wasn't needed, rest is needed i think. As for my failed attempts, I will add some tries below this code.

from tkinter import *

class App(Tk):

    def __init__(self):
        Tk.__init__(self)

        container = Frame(self)
        container.pack(side="top", fill="both", expand = True)
        self.frames = {}

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

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

class StartPage(Frame):

    def __init__(self, parent, controller):
        Frame.__init__(self,parent)
        label = Label(self, text="Start Page")
        label.pack(pady=10,padx=10)
        button = Button(self, text="Visit Page 1",
                            command=lambda: controller.show_frame(PageOne))
        button.pack()

class PageOne(Frame):

    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        label = Label(self, text="Page One!!!")
        label.pack(pady=10,padx=10)
        button1 = Button(self, text="Back to Home",
                            command=lambda: controller.show_frame(StartPage))
        button1.pack()


    app = App()
    app.mainloop()

I've been trying to combines these 2 functions:

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

def calculate(self):
    e1 = self.v1.get()
    e2 = self.v2.get()
    entry1 = int(self.entry1.get())
    entry2 = int(self.entry2.get())
    k = entry1 * entry2
    print(k)

tried to make 1 function out of theses two:

def run_all(self, cont):
    frame = self.frames[cont]
    frame.tkraise()
    e1 = self.v1.get()
    e2 = self.v2.get()
    entry1 = int(self.entry1.get())
    entry2 = int(self.entry2.get())
    k = entry1 * entry2
    print(k)

Wasn't sure what to put under parameters. Also I tried changing this buttons command:

    button = Button(self, text="Visit Page 1",
                    command=lambda: controller.show_frame(PageOne))
    button.pack()

Tried to write this command with and without lambda, but nothing worked.

Community
  • 1
  • 1
Arkadijus
  • 29
  • 5
  • "I get some kind of error" what kind, exactly? The error with stack trace please. And can you post your attempt at solving the problem, since you've already tried something, please? And while your code post is readable (thank you), it would be easier to address this with a "minimal example," which I don't believe this is – en_Knight Mar 25 '16 at 20:24
  • Why the comment about the license? The code you copied has no explicit license, and simply uses the license that governs the whole site. Also, please read http://www.stackoverflow.com/help/mcve. You've included more code than you need to illustrate your problem. For example, are three pages necessary or can the problem be illustrated with two? – Bryan Oakley Mar 25 '16 at 20:37
  • Edited post a little bit. I was getting various errors, most of the time it said that object has no attribute 'Show_frame". I took this code from one youtube, and there was this license, so i didnt bother deleting it. – Arkadijus Mar 25 '16 at 21:20

1 Answers1

1

There are a few ways to do multiple things with a button. I'd review this effbot page, for example, before moving much further, or another Tkinter tutorial

    def callback():
        controller.show_frame(PageOne)
        doSomethingElse()

    button = Button(root, command=callback)

In this case, we are creating a function that calls two other functions. This is the intuitive solution. Note that functions generated with the lambda keyword are the same as any other functions - don't let that confuse you.

Here's Something You Shouldn't Do, Although it Might Work

Alternatively, it may be tempting to write

    button = Button(root, command=lambda : [foo(), bar()]

In this case the lambda function will return a list of two values, which need to be computed by calling the two functions. That list is ignored, of course, since you're not using the return value.

Reasons why this is worse:

  • funcs = [foo,bar]; lambda : (f for f in funcs) May, or may not work. In python 2, the tuple will be fully evaluated, but in python3 you get a cryptic generator expression
  • It's less pythonic. Creating an anonymous list is not something I've seen done for any good reason. Related, anyone who sees method #1 (including future you) will know what you're doing. Anyone who sees method #2 will think you don't know what you're doing
  • In the first case, you have a handle to the actual function you're calling. In the second case, you have an anonymous list being returned by an anonymous function. There's no need for two layers of hidden-ness
  • It's significantly less extensible. If you decide later that you want to do something more complicated, or have the return values depend on each other, or short circuit (etc.) you have no way to do it with the list notation. You do if you're passing a generic function
Community
  • 1
  • 1
en_Knight
  • 5,301
  • 2
  • 26
  • 46
  • The first half of the answer is good. Personally I suggest removing the second half. I wouldn't recommend anyone ever do that second way, it simply has no benefit over the correct way. – Bryan Oakley Mar 25 '16 at 20:34
  • @BryanOakley is that sufficient; do you have other reasons I should add to the list? I'm averse to removing it entirely when it can be more concise, and there's imo something appealing about going for the most concise answer even if it isn't the most "pythonic" – en_Knight Mar 25 '16 at 20:46
  • I don't care about _pythonic_ nearly as much as I care about clarity of code. if I saw `lambda: [thing_one(), thing_two()]` my first thought would be "why are they doing that?" and then spend 5 minutes trying to understand if there's a reason for doing something so odd. I would have to assume the user had a reason to step off the beaten path, and I would be worried they are making incorrect assumptions about what is actually happening. It's simply the wrong tool for the job. – Bryan Oakley Mar 25 '16 at 20:53
  • I tried 1st method, it looks like a logical solution, but i didn't manage to get it work, keep getting error that says that controller is not defined, tried removing controller and changing up some stuff but nothing worked. – Arkadijus Mar 25 '16 at 21:33