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

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()

Related

Python: Get information after link binding partial Tkinter

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()

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.

Variable change does not update on 2nd file

Im using 2 files here. Say the variable is in the 1st file and Im using it on the 2nd. It has the initialized value of it but when I change its value the 2nd file does not recognize it. How can I update the variable so that the 2nd file reads its current value?
first module:
var = 0
def plus():
global var
var += 1
print(var)
second module(used tkinter for example)
from tkinter import *
from kk import *
root = Tk()
root.geometry("400x400+15+15")
btn = Button(root, text = "1", command = plus)
btn.pack()
def pr():
print(var)
btn1 = Button(root, text = "2", command = pr)
btn1.pack()
root.mainloop()
Following up from my comment, when you do from kk import var (or import *) you are effectively copying the variable value from the other module.
You need to copy a reference to the same object (instead of its value), you can achieve this using an object wrapper.
Try this:
class VarWrapper:
def __init__(self, initial_value):
self._value = initial_value
def __repr__(self):
return repr(self._value)
var = VarWrapper(0)
def plus():
global var
var._value += 1
print(var)
you need to import the first file function and execute it.
suppose first file name is first.py then import in second file.
from first import *
then it will work.
now you have access to first file. and to update variable use plus function.
it doesnt seem like you called plus(), if you call it it might work
#revision
perhaps if you do this?
def update ():
varInternal = var
def plusInternal ():
plus()
update()
I tried just importing again the wanted variable inside pr like so
def pr():
from kk import var
print(var)
It works, however I want to know if this way is appropriate to conventions

How to call function from external source from button. [Python]

I've been desperately trying to get this section of code to work in my program. I essentially want to read in several options from a file, and create Tkinter buttons from those options. Creating the buttons is no issue; currently, I just can't make the code run the functions I want.
from Lib import StegosaurMainCode as Steg
...
class App:
def __init__(self, master, menu):
buttons = []
for counter in range(0, len(menu[0])):
text = menu[0][counter]
func = menu[1][counter]
att = menu[2][counter]
buttons.append(Button(text=text, command=lambda: Steg.func(att)))
frame = Frame(master)
for item in buttons:
item.pack()
frame.pack()
In this class, func is the function I want to call, Steg is the external code in another file, and att are the attributes for the function. I can't seem to figure out why Steg.func won't tries to call a function in Steg called "func" rather than the one described in the variable func
Have your lambda rebind its att parameter at each call.
class App:
def __init__(self, master, menu):
buttons = []
for counter in range(0, len(menu[0])):
text = menu[0][counter]
func = menu[1][counter]
att = menu[2][counter]
buttons.append(Button(text = text, command = lambda att = att: Steg.func(att)))
frame = Frame(master)
for item in buttons:
item.pack()
frame.pack()
Assuming that menu[1][counter] contains a string rather than a reference to an actual function, you need to get a reference to the function which you can then use as the value for the command attribute. You can do that with getattr:
func = getattr(steg, menu[1][counter])
Once you've done that, you can use func as if it were an actual function. However, you need to bind the variables to their current values, so you need to pass them as arguments to the lambda:
button = Button(text=text, command=lambda func=func, attr=att: func(att)))

Tkinter, saving functions to a list and then running them

I'm working on a GUI for a project in school. All the buttons that I have in my GUI are bound with functions that I have created. These functions call for already predefined functions. For some of the predefined functions, I need one or two arguments and I have solved that with entries. I type in the arguments in the right entries that are connected to the specific button and when I press the button, the function will run with the corresponding arguments.
The thing I want to do is to in some way when I press a button, the function should be saved to a list instead of being executed right away. And when I push the "run" button(a new button that I will create) everything in my list will be executed. I have been thinking about using a list box but I don't know exactly how they work or if its even possible to run a list box that contains a number of functions. Does someone have any ideas or solutions for me? Can I use the list box for this or is there something else that is better to use?
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.entry1 = IntVar()
self.entry2 = IntVar()
def do_something():
value1 = self.entry1.get()
value2 = self.entry2.get()
self.listbox.insert(END, "predefined_function(value1, value2)")
def run_listbox_contents():
pass
self.button = Button(frame, text="Move", command=lambda: do_something())
self.button.pack(side=TOP)
self.entry1.set("value1")
self.entry = Entry(frame, textvariable=self.entry1)
self.entry.pack(side=TOP)
self.entry2.set("value2")
self.entry = Entry(frame, textvariable=self.entry2)
self.entry.pack(side=TOP)
self.listbox = Listbox(master)
self.listbox.pack(side=TOP)
root = Tk()
app = App(root)
root.title("Mindstorms GUI")
root.geometry("800x1200")
root.mainloop()
root.destroy()
Just use a standard list.
something like this
def hest(txt):
print "hest: " +txt
def horse(txt):
print "horse: " + txt
funcList = []
funcList.append(hest)
funcList.append(horse)
for x in funcList:
x("Wow")
This outputs
hest: Wow
horse: Wow
Was this what you wanted?
If I were you, I wouldn't want to save functions to a list. I would suggest another solution for you.
I suppose you have heard of the principle of MVC (Model-View-Controller). In your case, the list box is a part of view, and the process that saves functions and then calls them at once is a part of controller. Separate them.
You might want to save and display any string in the list box to let the users know that the corresponding functions have been enlisted and ready to run. For example, save a string "Function1 aug1 aug2 aug3" or "Funtion2 aug1 aug2" or whatever you like as a handle of the corresponding function.
And for the controller part, write a function (let's say conductor()). It reads the handle strings from the list, parses them and calls the corresponding functions. Where you want to run the enlisted functions, there you just call conductor().
Update:
Due to your comment I understand that you are pretty new to program. Let me show you how to write a simplest parser with your given variable names.
def run_listbox():
to_do_list = #get the list of strings
for handle_string in to_do_list:
#Let's say you got
#handle_string = "Predfined_function1 value1 value2"
#by here
handle = handle_string.split(" ")
#Split the string by space, so you got
#handle = ["Predfined_function1", "value1", "value2"]
#by here
if handle[0] == "Predfined_function1":
Predfined_function1(handle[1], handle[2]) #Call Predfined_function1(value1, value2)
elif handle[0] == "Predfined_function2":
Predfined_function2(handle[1], handle[2])
#elif ...
#...
#elif ...
#...
#elif ...
#...
This is not a perfect parser, but I hope it could let you know what does a parser look like.

Categories