#๐Ÿ”’ (tkinter) How to get the name of a function assigned to a button?

76 messages ยท Page 1 of 1 (latest)

celest ferry
#

I know i could call function.__name__ for this, but im trying specificly to get the name of a function a button has if i dont always know before hand what that function is. my current code (which im building as a template for future use, hence the redundant class) is this:

class main:
  def __init__(self):

    class MainWindow(tk.Tk):
      def __init__(self):
        tk.Tk.__init__(self)

        Window = ttk.Frame(self, padding=10)
        Window.grid(sticky="news")

        def TestFunc1():
          x = TestButton.cget('text')
          y = TestButton.cget('command')
          print(f'This is the "{x}" button which runs the "{y}" function!')

        TestLabel = ttk.Label(Window, text="Test Label")
        TestLabel.grid(column=1, row=1)

        TestButton = ttk.Button(Window, text="Test Button", command=TestFunc1)
        TestButton.grid(column=1, row=2)

    app = MainWindow()
    app.mainloop()

if __name__ == "__main__":
  main()

which prints: This is the "Test Button" button, which runs the "1649907075392TestFunc1" function.

mint aspenBOT
#

@celest ferry

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

celest ferry
#

ive trie da couple things, i recall something i used to use like TestButton.['text'].get() or something, but couldn't find that command and may have imagined it

celest ferry
#

ive been thinking on it, and it calling tiself didnt seem to be an issue. it did that whether the function i was using called itself or a different button with a different function attatched to it

#

crying

median steppe
#

Won't tkinter pass some sort of event context to the callback function?

#

from which you can refer to whatever widget invoked the event

#

@celest ferry

drifting dagger
#

thats horrifying

#

please, don't so that

median steppe
#

yes that is also concerning

celest ferry
#

as for the class thing its in a bid to not use global variables

#

the gui i was making, at my level of experience, needed a place to store variables set by the user for later use, and as less of a "this is definitly the best way to do it "and more of a "i want to get out of the habit of using global variables for anything besides constants" i ended up doing something like this, which in my actual application has a section for pseudo globals

#

ive removed everything nonessential for it to function for this test so it looks a bit stupid

#

but in any case thats not what im askin abt here

median steppe
#

If you're wrapping everything in a local scope to avoid using the global scope but change nothing else, then you didn't really do anything to solve your problem

celest ferry
#

i think i understand what youre saying, but in practice i think it works decent enough. its a way for me to have ""globals"" on a per level basis

#

yknow these are "globals" for everything below it, and then further down are ""globals"" for everything below that, etc

#

i wont pretend its ideal but i really need a lot of visual help (what im making is in essence an accessibility tool for myself for the reasons this nightmare of comments' purpose is to solve)

median steppe
#

Why not use the MainWindow class for that then?

celest ferry
#

because i need functions above the main window class that it can call on

median steppe
#

That's already the top-level class for your app. You can store whatever state you want there

celest ferry
#

yeah i know

median steppe
celest ferry
#

but i wanted to recreate the behavior defining a variable in the global field, and then calling it with global var does

#

where you can read it and write it as if its on the same level

#

to be quite honest, im positive theres many improvements and techniques i could use to better this code on that front, but for now it works well enough and solves the problems i need it to

#

ive rewritten this code many times as practice and each time is significantly better than the last, but its not a big enough project that i wanna devote more time to crunching variables and restructuring it from the ground it

#

right now im pretty much just trying to get the name of a function thats the command assigned to a button, without all the number nonsense like "1649907075392TestFunc1"

median steppe
#

Well, that in itself is sort of indicative to poor architecture anyways

celest ferry
#

ive only been coding for a week

#

so id say its pretty decent

median steppe
#

why do you need this function name and where do you need it?

median steppe
#

A lot of times the answer to "how do i do X" is "well you can, but you probably shouldn't"

celest ferry
#

dont i know it

#

i just learned about os.splitext and lemme tell you that would save about 50 lines of dumb reacharound code

#

for something else i mean

#

in any case, in a completely barebones tkinter gui with only a single button (or two if for some reason it cant reference itself), whos purpose is to print the test message as listed in my code at the top

#

"This is the {button] button and it runs the [function] function!"
im trying to print the function name where [function] is

#

its less i have a further goal in mind and more "this command doesnt work like i expected it to, what gives and how would i do it properly?"
in this case, TestButton.cget('command') was expected to literally print what comes after command= in TestButton, which would be TestFunc1, but as it stands it adds a long string of numbers (that i HAVE seen before, but only when i enter a function reference wrong or some such, whereas here i cant figure out how i would be supposed to do this)

#

@median steppe :0?

median steppe
celest ferry
#

n00b question but ive tried looking into it multiple times and never been clear, what is a callback function like in stricter terms than "a function that calls back something"

#

in any case though, my goal is to retrieve the name of a function assigned to a button with the assumption that all i know for sure is which button im trying to get at a given moment. i really have no preffy for HOW i do it, and if it were something where i could only do it if it wasn't calling itself thatd be fine, its more of a "shouldnt this be possible in ANY way, not just the one im currently trying?" thing

median steppe
celest ferry
#

gotcha, ty :)

#

maybe later i can post the code to my current build of the real project im alnost done with (which doesnt req this button command get nonsense)

proper viper
#

why not just use an index system on the buttons and pass index number in parameters?

celest ferry
#

the simple answer is because thats not a system ive thought of

#

i do tend to get ๐Ÿ‘Œ slightly tunnelvisioned when i find a way to do something that doesnt present any immediete issues

#

but thats what restructuring and rewriting (i think its called refactoring? idk) code is for

#

still, my philosophy is that learning how to do smth will always be helpful even if its a bad way to do this. whats your basic visualization of that anyway? likeeee this?

def Func1():
  print("TestFunc1")

Functions = {
  1:"Func1",
  2:"Func2"
}

TestButton = ttk.Button(Window, text="Test", command=Functions[1]).grid()

after typing it out i can just feel that its not what you meant but from where i come from (sheets) an index is just a list/tuple/whatever, and this is just my instinct

proper viper
#
import tkinter as tk

class Window(tk.Tk):
    def __init__(self):
        super().__init__()
        self.button_names = []
        self.title("Button Name")
        self.geometry("300x150")

        label = tk.Label(self, text="Hello, Tkinter!")
        label.pack(pady=20)

        mystery_button_name = tk.Button(self, text="Click Me", command=lambda : self.on_click(0))
        #variables get added after button made
        self.button_names.append(f"{mystery_button_name=}".split("=")[0])

        mystery_button_name.pack()

    def on_click(self, number):
        print(self.button_names[number])

if __name__ == "__main__":
    app = Window()
    app.mainloop()```
#

heres a mock up idea

#

so once buttons created on that function however their made ad a elf button_name with an index

celest ferry
#

oh no its not the button name i want, i mean it could be useful to have this and may even be part of the solution to what im looking for, but im trying to get the name of the function listed in the command

proper viper
#

oh so the on click? in this scenario

celest ferry
#

like imagine a second button who looks at mystery_button_name and returns lambda : self.on_click(0)

#

i suppose yeah, though thats not a req

#

i made a version of my codeblock at the start of the thread that includes a second button whos soul purpose is to print the function name of whatever the first button has

#

which is a clearer vision to what im trying to do

proper viper
#

well here I just joined voice chat 1 if ya can talk through it

#

I cna throw up some mock ups

#

sounds almost like you just want a logging system

celest ferry
#

gimme one sec

#

(whats a logging system in this context)

proper viper
#

a logging system just refers to a way to know when something in a codebase is called so like writing to a file with a time stamp with some bit of informatin or another, often a database but just some wayt ot monitor when something is called

celest ferry
#

ah yeah i dont need anything that complex

#

yet anyway

#

im not even trying to "make" anything this is more just "shouldnt this be possible? why isnt it. i will devote my entire day to solving this problem i dont need the answer to"

mint aspenBOT
#
Python help channel closed for inactivity

This help channel has been closed. Feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.