0

I'll be short. I created a tkinter GUI, which I need to call as an object or a window that appears on button click. code is:

class Test(Frame):

    def __init__(self,master = None):
        Frame.__init__(self, master)
        self.master =  master
        self.win()

    def win(self):
        self.pack()

        self.label = Label(self, text="hello World!").pack()
        self.quit = Button(self, text= "quit", command = self.master.destroy).pack()

the code works fine when I call the class in the same file. ie, by adding

root=Tk()
Test()

but I want it to be called at a button click, but outside in other gui.

what I tried:

1) applying the same root = Tk() as it is.

2) calling it in a class as object by: self.test = Test() and applying command self.test.win in the button.

Problem:'module' object is not callable.

code of other gui, where I want the button to call Test class and show gui of that class:

import Test
class Wtf(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master = master
        self.btn()
        self.test = Test()

    def btn(self):
        self.pack()

        self.test = Test()

        self.btn = Button(self, text = "Call", command = self.test.win).pack()

root=Tk()
app = Wtf(root)

Thanks in advance. Hope I defined as much as required.

for those who did not understand:all i'm trying to here is to link the class data to the button 'btn', so that when I press the button I could get the class Test gui displayed either in the same window root or a different window.

please note: i'm a newbie at python and this program might not make sence to you, but all i'm trying here is to call the class Test on a buttonclick of 'btn'.

3 Answers3

0

I think I know, in this version you can call a function in Test() class from the main class of the program.

After run the script click on Open button then click on Call and watch what happen.

import tkinter as tk
from tkinter import messagebox

class Test(tk.Toplevel):

    def __init__(self, parent):
        super().__init__()

        self.parent =  parent
        self.title("I'm a new toplevel.")
        self.init_ui()

    def init_ui(self):

        self.label = tk.Label(self, text=self.title()).pack()
        self.close_me = tk.Button(self, text= "Close me", command = self.on_close_me).pack()
        self.close_parent = tk.Button(self, text= "Close parent", command = self.on_close_parent).pack()

    def on_close_me(self):
        self.destroy()        

    def on_close_parent(self):
        self.parent.on_close()

    def callback(self):
        msg = "I come from parent toplevel"
        messagebox.showwarning(self.master.title(), msg, parent=self)




class App(tk.Frame):

    def __init__(self,):

        super().__init__()

        self.master.title("Hello World")

        self.obj = None

        self.init_ui()

    def init_ui(self):

        self.pack(fill=tk.BOTH, expand=1,)

        f = tk.Frame()

        w = tk.Frame()

        tk.Button(w, text="Open", command=self.callback).pack()
        tk.Button(w, text="Call", command=self.call_child_function).pack()
        tk.Button(w, text="Close", command=self.on_close).pack()

        f.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)
        w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=0)

    def callback(self):
        self.obj = Test(self)

    def call_child_function(self):
        self.obj.callback()


    def on_close(self,evt=None):
        self.master.destroy()

if __name__ == '__main__':
    app = App()
    app.mainloop()
1966bc
  • 1,148
  • 1
  • 6
  • 11
0

I don't understand exactly what you're trying to accomplish, but there are numerous problems with your code, some of which I already pointed-out in a comment.

The 'module' object is not callable problem is because you have a module called Test which defines a class named Test inside it, so the problem can be avoided by using Test.Test when referring to the class.

Here are working versions of the main script and the Test.py module:

main.py:

from tkinter import *
import Test


class Wtf(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master = master
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        self.test = Test.Test(self.master)
        self.btn = Button(self, text="Call", command=self.test.win)
        self.btn.pack()

root = k()
app = Wtf(root)
app.mainloop()

Test.py:

from tkinter import *

class Test(Frame):

    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master = master
        self.pack()

    def win(self):
        self.label = Label(self, text="Hello World!")
        self.label.pack()
        self.quit = Button(self, text= "quit", command=self.master.destroy)
        self.quit.pack()

Update

Based on your comment about what you really want to do, I've adapted the accepted answer to the question Switch between two frames in tkinter to your needs:

main.py

import tkinter as tk
import Test


class App(tk.Tk):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (Wtf, Test.Test):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame("Wtf")

    def show_frame(self, page_name):
        """ Show a frame for the given page name. """
        frame = self.frames[page_name]
        frame.tkraise()


class Wtf(tk.Frame):

    def __init__(self, parent, controller):
        super().__init__(parent)
        self.parent =  parent
        self.controller = controller
        self.create_widgets()

    def create_widgets(self):
        self.test = Test.Test(self.parent, self.controller)
        self.btn = tk.Button(self, text="Call",
                             command=lambda: self.controller.show_frame("Test"))
        self.btn.pack()


if __name__ == "__main__":

    app = App()
    app.mainloop()

Test.py:

import tkinter as tk


class Test(tk.Frame):

    def __init__(self, parent, controller):
        super().__init__(parent)
        self.parent =  parent
        self.controller = controller
        self.create_widgets()

    def create_widgets(self):
        self.label = tk.Label(self, text="Hello World!")
        self.label.pack()
        self.quit = tk.Button(self, text= "Quit", command=self.controller.destroy)
        self.quit.pack()
martineau
  • 119,623
  • 25
  • 170
  • 301
  • sir ! it is a great program. I did understand it easily. I have changed it to control various buttons and provide more than 1 GUIs. the problem i'm occurring with it is that i'm no able to reverse it. to explain it more specifically, in this case the flow is from main to test but I want to add a back button in test which can take me back from test to main without exiting the main window. – Andrious Prime Apr 15 '19 at 08:40
-1

I am not sure to have understood well the question, anyway look below.

Particularly to

self.close_me = tk.Button(self, text= "Close me", command = self.on_close_me).pack()

self.close_parent = tk.Button(self, text= "Close parent", command = self.on_close_parent).pack()

You can even put the class Test on another file and input it.

import tkinter as tk

class Test(tk.Toplevel):

    def __init__(self, parent):
        super().__init__()

        self.parent =  parent
        self.title("I'm a new toplevel.")
        self.init_ui()
          
    def init_ui(self):

        self.label = tk.Label(self, text=self.title()).pack()
        self.close_me = tk.Button(self, text= "Close me", command = self.on_close_me).pack()
        self.close_parent = tk.Button(self, text= "Close parent", command = self.on_close_parent).pack()

    def on_close_me(self):
        self.destroy()        
    
    def on_close_parent(self):
        self.parent.on_close()
        
        
class App(tk.Frame):
   
    def __init__(self,):
        
        super().__init__()

        self.master.title("Hello World")

        self.init_ui()
          
    def init_ui(self):

        self.pack(fill=tk.BOTH, expand=1,)

        f = tk.Frame()

        w = tk.Frame()

        tk.Button(w, text="Open", command=self.callback).pack()
        tk.Button(w, text="Close", command=self.on_close).pack()

        f.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)
        w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=0)
        

    def callback(self):
        obj = Test(self)
        
    def on_close(self,evt=None):
        self.master.destroy()
    
if __name__ == '__main__':
    app = App()
    app.mainloop()
Community
  • 1
  • 1
1966bc
  • 1,148
  • 1
  • 6
  • 11