Abdullah Al Mubin
Abdullah Al Mubin

Reputation: 133

Python/Tkinter Lambda Event Argument Issue

I have been trying to call the function showframe which takes two aurgument. When i call it from Button command in HomePage it shows an error. TypeError: showframe() missing 1 required positional argument: 'frame_name'. I can't understand why? As I called by class name so it should automatically get self, then frame_name will get the SignIn class. But thats not happening.

class Culpture(Frame):
    def __init__(self, root):
        Frame.__init__(self, root)
        fhome = HomePage(root)
        fsignin = SignIn(root)
        self.showframe(fhome)
        fhome.grid(row=0, column=0, sticky='nsew')
        fsignin.grid(row=0, column=0, sticky='nsew')
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)

    def showframe(self, frame_name):
        frame_name.tkraise()
class HomePage(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        Label(self, text="Homepage").grid()
        Button(self, text='SignIn', command=lambda: Culpture.showframe(SignIn), width=20).grid()

If I do this way,

Button(self, text='SignIn', command=lambda: Culpture.showframe(parent, SignIn), width=20).grid()

then it shows another error message.TypeError: tkraise() missing 1 required positional argument: 'self' So I tried to look some question I got one which is close to my solutionPython/Tkinter Event Argument Issue but not same. If I try another way Button(self, text='SignIn', command=lambda: Culpture.showframe(parent, SignIn(parent)), width=20).grid() then it shows no error but button does not open the new frame.

class SignIn(Frame):
def __init__(self, parent):
    Frame.__init__(self, parent)
    Label(self, text="SignIn").grid()
    Button(self, text='Submit', width=20).grid()

So it would be really helpfull if any of you can help me out.

Upvotes: 0

Views: 474

Answers (2)

Eshita Shukla
Eshita Shukla

Reputation: 811

You are doing things the wrong way. Ideally, you are supposed to make different classes for different pages which will make the code less messy.

So, make a different class for SignIn and a different one for home.

Following is written in python3:

import tkinter as tk
from tkinter import *

class Culpture(tk.Tk):
    def __init__(self,*args,**kwargs):
    tk.Tk.__init__(self,*args,**kwargs)

    F1=tk.Frame(self)
    F1.pack(side="top",fill="both",expand=True)

    F1.grid_rowconfigure(0,weight=1)
    F1.grid_columnconfigure(0,weight=1)

    self.frames={}

    for F in (Home,SignIn):                                       # Looping between the pages: Home, SignIn (if they are interconnected through buttons)
        frame=F(F1,self)                                          # If they are all not interconnected, make different loops for different sets all containg the same element Home

        self.frames[F]=frame
        frame.grid(row=0,column=0,sticky="nsew")


    self.show_frame(Home)

    def show_frame(self,cont):

    frame=self.frames[cont]
    frame.tkraise()

class Home(tk.Frame):                                                   # Home page

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

    label=Label(self,text="Home",foreground="blue")
    label.pack(pady=10,padx=10)

    signB=Button(self,text="SignIn",command=lambda:controller.show_frame(SignIn),foreground="snow", background="blue")

    signB.pack()
    #trajectory.tkinter.tix.balloon



class SignIn(tk.Frame):                                                # SignIn

    def __init__(self,parent,controller):
    tk.Frame.__init__(self,parent)
    label=Label(self,text="Enter datails",foreground="red")
    label.pack(pady=10,padx=10)

    home=Button(self,text="Home",command=lambda:controller.show_frame(Home),foreground="snow", background="red")
    home.pack()


root=Culpture()

root.mainloop()

Let me know, if this does not work. Also,to add more pages:

If they are interconnected- add the names of the classes to the same loop.

If they are connected to some page in common- make a new lop, with the names.

Upvotes: 1

Bryan Oakley
Bryan Oakley

Reputation: 385980

Somewhere in your code you need to create an instance of Culpture. You need to use that instance to call show_frame. When you do that, the instance will be automatically passed as the self parameter, and the argument you pass will be frame_name.

culpture = Culpture(root)
...
culpsure.show_frame(fsignin)

You didn't show where you create the instance of Culpture so it's hard to be any more specific than that.

Upvotes: 1

Related Questions