Python: Get information after link binding partial Tkinter - python

import functools
from tkinter import *
win = Tk()
def func(win,name):
print (name)
mylist = ['item1','item2','item3']
for item in mylist:
link1=Label(win,text=item)
link1.bind("<Button-1>",functools.partial(func,item))
link1.pack()
win.mainloop()
My code currently outputs "ButtonPress event num=1 x=10 y=10>" whereas it should output item 1,2 or 3 when the label is pressed.
When buttons are used instead it works perfectly fine but once it's a binded Label it gives a different output

A Button command calls a function with no parameters func(). Any function bound to a "<Button-1>" event is passed the event, func(event).
In the original code:
def func(win,name):
print (name)
functools.partial(func,item)
# This sets the **win** parameter to item. When the new function is called
# the **event** is passed to the next 'available' parameter, name.
This works when the partial is called from a button command as no parameters are passed. When called from a bound event an event parameter is passed. This is what is printed when the Label is clicked.
import functools
from tkinter import *
win = Tk()
def func( event, name ):
print ("Event: ", event, "Name: ", name)
mylist = ['item1','item2','item3']
for item in mylist:
link1=Label(win,text=item)
link1.bind("<Button-1>",functools.partial(func,name = item))
# set the name parameter explicitly
link1.pack()
win.mainloop()

Related

How to pass the value from function inside function to main module?

i need help for below codes, I trying to create a software using tkinter and i have a issue on passing the value from inside function inside sub function to main module. how to get the return result use in main module and insert in mylist.
Here's the codes:
main module: test.py
from button_screener import screener
button created to open screen. command = screener
mylist = [ ]
mylist.insert(END, result)`
sub module: button_screener
def screener():
code.... (create tkinter layout code)
OK_button created to execute function execute() - command = execute
def execute():
code... after several calculation..get result below
result = list [a,b,c]
return result
Needs help and let me know if needed further clarifications.
Thank you
When you call a new function, you can think of it as creating a stack (of operations).
The function that is called latest will be at the top of the stack, and once it finishes executing it will return back to the calling function (and also return any value if you have specified in the return statement).
which means : when you do return result in your execute() function, it will provide that result to it's calling function : screener()
since you are calling screener() from your main module, you should capture the output of execute() in screener(), and then return that to the screener() 's calling function - which is main.
def screener():
code.... (create tkinter layout code)
#OK_button created to execute function execute() - command = execute
def execute():
code... after several calculation..get result below
result = list [a,b,c]
return result
result_from_execute = execute() #capturing response from execute()
return result_from_execute #return the result to the main module
Since those functions are executed by a button click, whatever returned from those functions will be discarded.
As the result you want to return is a list, you can pass the required list variable to screener() as an argument which will be updated inside the function.
Below is a simple example:
import tkinter as tk
def screener(result):
def execute():
# do some calculation
a, b, c = 1, 2, 3
# then update result
result[:] = [a, b, c]
win.destroy()
win = tk.Toplevel()
tk.Button(win, text='OK', command=execute).pack(padx=50, pady=50)
win.grab_set()
mylist = []
root = tk.Tk()
tk.Button(root, text='Sceener', command=lambda:screener(mylist)).pack()
tk.Button(root, text='Show', command=lambda:print(mylist)).pack()
root.mainloop()

Binding and returning values from a function within a function (Tkinter)

I have simplified the issue I am having with my code.
I have several functions within functions and I am finding it difficult to capture a return value from a function which is trigged from a binding.
from tkinter import *
root = Tk()
root.title("Test example")
root.geometry("500x500")
def funcl(event):
print("funcl")
def inner_funcl():
print("inner fucntion")
x = 15
return x
x=inner_funcl()
return x
def ppprinter(x):
print(x)
z=funcl(event)
ppprinter(z)
my_button = Button(root,text="Button")
my_button.pack()
my_button.bind("<Button-1>",funcl)
root.mainloop()
z = funcl(event)
The event variable you are passing to the function is not declared. And the event passed in the function funcl is not used anywhere.
I do not get the point of this code and its functionality.
Solution:
You could create a variable event with any value (for example: event = "Hello").
This will allow you to run the script.

How to get the value of an Entry created in a def?

I'm working on a project and i would like to get the Value of an Entry created in a def (turned on by a button on Tkinter)
So I have my main tkinter menu, with a button which will call the def "panier".
The def "panier" is creating the Entry "value" and another button to call a second def "calcul".
The second def "calcul" will do things with the value of Entry...
But then, in the def "calcul", when i'm trying to do value.get() it tells "NameError: name 'value' is not defined"
Here is the code, btw the Entry must be created by the def...
from tkinter import *
def panier():
value=Entry(test)
value.pack()
t2=Button(test,text="Validate",command=calcul)
t2.pack()
def calcul(value):
a=value.get()
#here will be the different calculations I'll do
test=Tk()
t1=Button(test,text="Button",command=panier)
t1.pack()
test.mainloop()
Appreciate every feedback :)
You can make the variable global like this:
from tkinter import *
def panier():
global value
value = Entry(test)
value.pack()
t2 = Button(test, text="Validate", command=calcul)
t2.pack()
def calcul():
a = value.get()
print(a)
#here will be the different calculations I'll do
test = Tk()
t1 = Button(test, text="Button", command=panier)
t1.pack()
test.mainloop()
The global value line makes the variable global so you can use it anywhere in your program.
You can also pass in the variable as an argument like what #JacksonPro suggested
t2 = Button(test, text="Validate", command=lambda: calcul(value))
This is one way to do it. Globally create a collection (list or dictionary) to hold a reference to the Entry. When you create the Entry, add it to the collection. I made it with either a list or dictionary for holding the references, so toggle the commented variations in all three places to try it both ways.
import tkinter as tk
def panier():
for item in ('value', ):
ent = tk.Entry(test)
collection.append(ent)
# collection[item] = ent
ent.pack()
t2 = tk.Button(test,text="Validate",command=calcul)
t2.pack()
def calcul():
a = collection[0].get()
# a = collection['value'].get()
print(a)
collection = []
# collection = {}
test = tk.Tk()
t1 = tk.Button(test, text="Button", command=panier)
t1.pack()
test.mainloop()

Tkinter - How to change the value of an argument for an event binding with lambda function?

I have a list named chosenTestHolder (imported from the my_config file) that consists of several objects each with the attribute 'sentence'.
When pressing the button 'Press' for the first time, the attribute 'sentence' of the first object in the chosenTestHolder should be displayed in the text widget. The next time the button 'Press' is pressed the attribute 'sentence' of the second object in chosenTestHolder should be displayed and so on.
I am using lambda event for binding the 'Press' button and tries to use a new sentences as its first arguments after each pressing of the 'Press' button. However, it keeps showing the first sentence.
When searching Stackoverflow I have seen in
Using lambda function to change value of an attribute that you can't use assignments in lambda expressions but by reading that I still have not figured out how to solve my problem.
Grateful for help! Code is below!
main.py
from tkinter import font
import tkinter as tk
import tkinter.ttk as ttk
import my_config
import Testlist as tl
class TestWidgetTest:
def __init__(self):
ram = tk.Frame(root)
ram.grid(in_=root,row=0, column=0)
self.myText = tk.Text(ram, height = 5)
self.myText.grid(row=0,column=1)
my_config.counter = 0
self.myButton = tk.Button(ram, text = 'Press')
self.myButton.grid(row =1, column =0, columnspan =2)
indata =[my_config.chosenTestHolder[my_config.counter] , self.myText]
self.myButton.bind('<ButtonRelease-1>',lambda event, arg=indata : self.TagConfigure(event, arg))
def TagConfigure(self, event, arg):
arg[1].delete('1.0',tk.END)
arg[1].insert('1.0',arg[0].sentence)
my_config.counter += 1
root = tk.Tk()
TestWidgetTest()
root.mainloop()
my_config.py
import Testlist as tl
testListHolder = [ ['Fabian was very tired'],
['Thomas light the fire'],
['Anna eat a red apple ']]
chosenTestHolder = []
count = 0
while count <(len(testListHolder)):
chosenTestHolder.append(tl.Testlist(testListHolder[count][0]))
count += 1
counter = 0
Testlist.py
class Testlist:
def __init__(self, sentence):
self.sentence = sentence
Your issue is the assignment of indata.
You do only assign in init.
To get your code working you need to re-configure your sentecte...
indata =[my_config.chosenTestHolder[my_config.counter] , self.myText]
self.myButton.bind('&ltButtonRelease-1&gt',lambda event, arg=indata : self.TagConfigure(event, arg))
I would advise to keep track of the current sentence as an instance variable.
class Test_widget(tk.Frame):
def __init__(self, *args, **kwargs):
tk.Frame.__init__(self, args, kwargs)
self.sentences=["a", "b", "c", "d"] # the data
self.show = tk.StringVar() # the current displayed data
self.show.set("NULL")
self.counter=0 # the indexer
tk.Label(self, textvariable=self.show).grid(row=0)
tk.Button(self, command=self.click).grid(row=1)
def click(self, event):
self.show.set("%s"%self.sentences[self.counter]) # use the indexer to access the data
self.counter = self.counter + 1 # modify the indexer
if self.counter = len(self.sentences): # make sure you dont run in index-err
self.counter = 0
As you see, there is no need at all for the lambdas.
Edit
As to your questions:
The change in your original code was not intended.
I do not see a use case where you can use a lambda for its use inside your code.
At least none where a lambda is necessary.
Please remember to use lambda only and exclusively if there are
no ( == NULL ) other options.
Using inheritance (thats what the mechanism is called), you can inherit functions, "default" behaviour from other classes. It is a common mechanism in programming and not exclusive to python.
It is used like any normal object except you have to call the constructor of the base class (what I do using tk.Frame.__init__(self, args, kwargs) inside the init method. For more information on inheritance please refer to the uncounted manuals and tutorials available for that topic (google is your friend now that you know what the mechanism is called).

How to get content of ScrolledText?

I'm trying to get content of a ScrolledText but so far success is not with me :)
I don't understand where i'm wrong.
Here a very simple example of not working code...
from Tkinter import Tk
from ScrolledText import ScrolledText
def returnPressed(value):
print "CONTENT: " + value
root = Tk()
st = ScrolledText(root)
st.bind("<Return>", lambda event, i=st.get("1.0", "end-1c"): returnPressed(i))
st.insert("insert", "TEST")
st.pack()
root.mainloop()
Ok this is because of lambda definition.
By this way, function is created with constant "i" value, which is the value at declaration of function.
By rewording lambda as it, it works!
st.bind("<Return>", lambda event: returnPressed(st.get("1.0", "end-1c")))
You are getting the value at the time you create the button, which means the value will always be empty. You need to get the value at the time that the event is processed.
You should avoid using lambda, it is a somewhat advanced concept that in this case adds complexity without adding any value. Simply get the value from within the function:
def returnPressed(event):
value = event.widget.get("1.0", "end-1c")
print "CONTENT: " + value
...
st.bind("<Return>", returnPressed)

Categories