ricky6991
ricky6991

Reputation: 53

how to call event from another module in tkinter

i made a test app for reasons like this. I am trying to have the ButtonRelease-1 event call a function inside another file. I am getting a syntax when trying to run the app.

TypeError: listb() takes exactly 2 arguments (1 given)

this is pretty strait forward syntax but i cannot fix it in this specific situation. I am basically just having the event get the clicked info printed. It's the event that is no working because function inside other file is not reconizing the event?

anyways, curious how to fix this code so it works. The function has to stay in another file. This would be easy if it was in same file but it cannot be.

start.py

from Tkinter import *
import example_funcs as EF


class Page_three(Frame):

    def __init__(self):
        Frame.__init__(self)
        self.pack()
        self.listboxs()

    def listboxs(self):
        self.z = Listbox(self)
        self.z.grid()
        for item in range(1,10):
            self.z.insert(END, item)
        self.z.bind("<ButtonRelease-1>", EF.listb(self))

root = Tk()
app = Page_three()
app.mainloop()

example_funcs.py

from Tkinter import *
import Tkinter as tk

def listb(self, event):
    selection = self.z.curselection()
    print selection

self is used so variables can be called inside the function, if do not call self as instance it will have syntax of not finding my listbox variable.

Upvotes: 1

Views: 1034

Answers (1)

Blckknght
Blckknght

Reputation: 104682

Passing EF.listb(self) doesn't do what you want it to do. It doesn't partially bind the self parameter to the instance you're calling it from, then let the event paramter get filled in by the callback. Instead, it just calls the function immediately (before the bind call is made) and you get an error about using the wrong number of arguments.

There are a few different ways you could fix this issue.

One option would be to manually bind the self parameter to the listb function using functools.partial:

import example_funcs as EF
import functools

class Page_three(Frame):
    ...
    def listboxs(self):
        ...
        self.z.bind("<ButtonRelease-1>", functools.partial(EF.listb, self))   # bind self

Another approach would be to make listb an actual method in your class, so that you can reference it as a method on self. That could look like this:

import example_funcs as EF

class Page_three(Frame):
    ...
    def listboxs(self):
        ...
        self.z.bind("<ButtonRelease-1>", self.listb)   # refer to a method without calling it

    listb = EF.listb   # add the function from the other module as a method on this class

If listb isn't used anywhere else though, then defining it in another module and copying it over here would be pretty silly. You should just move the definition into this class instead of adding a reference to it after the fact. On the other hand, if listb is being used in several different classes, it suggests that the classes should be using some kind of inheritance to share the method, rather than crudely copying references to the one definition around.

Upvotes: 1

Related Questions