I have a number of test files in a single directory. I'm trying to write a GUI to allow me to select and run one of them.
So, I have a loop that scans the directory and creates buttons:
for fnm in glob.glob ('Run*.py'):
tstName = fnm[3:-3] # Discard fixed part of filename
btn = Button (self, text=tstName,
command=lambda: self.test(tstName))
btn.grid (row=rowNum, column=0, pady=2)
rowNum += 1
This creates my GUI correctly, with buttons labelled say, A and B but when I press on the button labelled A it passes B to the test method.
I've looked around and found this question How can I pass arguments to Tkinter button's callback command? but the answer doesn't go on to use the same variable name, with a different value, to configure another widget. (In fact, by tying the variable name to the widget name it almost implies that the technique won't work in this case, as I've found.)
I'm very new to Python, but am quite familiar with creating this kind of GUI using Tcl/TK and I recognise this problem - the value of tstName is being passed when I press the button, but I want it to pass the value the variable had when I created it. I know how I'd fix that in Tcl/Tk - I'd define a command string using [list] at creation time which would capture the value of the variable.
How do I do the same in Python?
You need to bind the current value of tstName at the time you define the button. The way you're doing it, the value of tstName will whatever it is at the time you press the button.
To bind the value at the time that you create the button, use the value of tstName as the default value of a keyword parameter to the lambda, like so:
btn = Button(..., command=lambda t=tstName: self.test(t))
Related
When I run the following code, I receive the following error: NameError: name 'barE' is not defined.
Does Tkinter's Entry work from one function to another? I have a global window and frame in this program and it passes the user's input without error using the same syntax as below.
def newSearchForm():
window2=Tk()
window2.geometry("650x400")
frame = Frame(window2)
frame.pack(side="top", expand=True, fill="both")
barcode=Label(frame,text="Please Enter The Barcode", font='time 15')
barcode.place(x=10,y=90)
barE=Entry(frame)
barE.place(x=250,y=90)
isbn=Label(frame,text="Please Enter The ISBN", font='time 15')
isbn.place(x=10,y=130)
isbE=Entry(frame)
isbE.place(x=250,y=130)
repeatSearchButton=Button(frame,text="Enter", command=newSearch,width=12,bg='gray')
repeatSearchButton.place(x=150,y=170)
window.mainloop()
def newSearch():
uB = barE.get()
uI = isbE.get()
carlSearch(uB, uI)
itemTitle=workspace.find_element_by_xpath('//*[#id="mainContent"]/div[2]/div[2]/div[2]/div[1]/div[1]/div').text
ingramSearch()
fantasticFictionSearch(itemTitle)
outputMetadata()
I tried using the lambda command to explicitly pass the variables and that didn't work.
I tried using anexising window and that didn't work, so I destroyed it and created a new one.
I would suggest you to use text variable. You can create a text variable by StringVar and assign it in the entry widget.
For more details on why to use text variable see Should I use Entry's .get() or its textvariable's for Tkinter in Python?
Usage:
barE_var=StringVar()
barE=Entry(frame,textvariable=barE_var)
barE.place(x=250,y=90)
To get value use barE_var.get().
Does Tkinter's Entry work from one function to another?
It does work, but have to use global keyword to access them.
def newSearch():
global barE_var
I am currently working on a calculator and I was coding the C Button (C button is the button which erases the current operation) however, My idea was to make the C Button return all Variables used during the operation to their starting state so we can start a new operation after pressing C. The problem is there is something called StringVar() in Tkinter that I used after reading an answer on StackOverflow. It is used to update the label every time I hit a new Button. it works but when trying to return it to its normal state when pressing the C button it doesn't work. They are still the same. so how can I reset the StringVar?
solution: Turns out I didn't assign the global variables used in the function, but any way to reset the stringVar you can just do this : (variable name).set("")
It should be variableName.set("")
s = StringVar()
# here getting textvariable
value = s.get()
print(value) # input value
s.set("") # reset it
Edit: After below comment, I am adding this structure to show how to keep desired item clean
# getting input
sFaculty = StringVar()
combo = ttk.Combobox(tab1, ..., textvariable=sFaculty, ...)
# assing it to function
Button(tab1, text="Insert", command=lambda: guiActions.insertStudent(..., sFaculty, ...))
# process and clean in a function
def insertStudent(..., faculty, ...):
# process here
# cleaning after insert
faculty.set("")
I have a list of frames that each have an optionmenu with the same list of choices. When a choice is made in that specific optionmenu, I've only been able to get the last entry widget to change, not the corresponding one. In other widgets I've been able to use something like "lambda F=F:function(args)" but that isn't working here.
I've tried a trace on the variable in the option menu, I've tried wrapper functions, I've tried every combination of a lambda in the command section of the optionmenu widget. Most approaches create errors, some, like the one attached, modify the bottom frame/entry but not the correct corresponding one.
This doesn't seem like it should be too hard. If the option for the top frame selected is "Continuous" or "Discrete", the entry next to it should be 'normal' state with "?..?" in the box, if it is categorical, it should change to be 'disabled' with no contents. I could do this easily if I could somehow pass the Frame dictionary key to the "updateOnChange" function, but I can't, it only allows a single argument to be passed and that is the string value of mType[F].
from tkinter import *
def updateOnChange(type):
print(type)
if type.upper()=='CATEGORICAL':
rangeEntry[F].delete(0,END)
rangeEntry[F].config(state='disabled')
print("runCat")
else:
rangeEntry[F].config(state='normal')
rangeEntry[F].delete(0,END)
rangeEntry[F].insert(0,'?..?')
print("runCont")
mType={}
frame={}
om={}
rangeEntry={}
root=Tk()
Frames=['FrameOne','FrameTwo']
miningTypes=['Continuous','Categorical','Discrete']
for F in Frames:
mType[F]=StringVar(root)
if F=='FrameOne':
mType[F].set("Continuous")
else:
mType[F].set("Categorical")
frame[F]=Frame(root,borderwidth=3,relief=SUNKEN)
frame[F].pack(side=TOP,fill=X)
rangeEntry[F]=Entry(frame[F],width=20,font=("Arial",12))
om[F]=OptionMenu(frame[F],mType[F],*miningTypes,command=updateOnChange)
om[F].pack(side=LEFT)
rangeEntry[F].pack(side=LEFT)
mainloop()
``
Your updateOnChange function hard-coded the entry to be changed as rangeEntry[F], which points to the last Entry widget created in your for loop. To properly associate each entry, you should pass the widget as a parameter:
def updateOnChange(type, entry):
if type.upper()=='CATEGORICAL':
entry.delete(0,END)
entry.config(state='disabled')
print("runCat")
else:
entry.config(state='normal')
entry.delete(0,END)
entry.insert(0,'?..?')
print("runCont")
And then pass the parameter in your command:
om[F]= OptionMenu(frame[F],mType[F],*miningTypes,command=lambda e, i=rangeEntry[F]: updateOnChange(e, i))
I have just now begun with GUI programming in Python 2.7 with Tkinter.
I want to have a button Browse, which when clicked opens the Windows File Explorer and returns the path of file selected to a variable. I wish to use that path later.
I am following the code given here. It outputs a window displaying 5 buttons, but the buttons do nothing. On clicking the first button, it doesn't open the selected file.
Likewise, on clicking the second button, the askopenfilename(self) function is called and it should return a filename. Like I mentioned, I need that filename later.
How to I get the value returned by the function into some variable for future use?
There is no point in using return inside a callback to a button. It won't return to anywhere. The way to make a callback save data is to store it in a global variable, or an instance variable if you use classes.
def fetchpath():
global filename
filename = tkFileDialog.askopenfilename(initialdir = 'E:')
FWIW (and unrelated to the question): you're making a very common mistake. In python, when you do foo=bar().baz(), foo takes the value in baz(). Thus, when you do this:
button = Button(...).pack()
button will take the value of pack() which always returns None. You should separate widget creation from widget layout if you expect to save an actual reference to the widget being created. Even if you're not, it's a good practice to separate the two.
Am learning Gtk. I wanted to build a calculator, in which i want to display the number pressed , in the textbox. I have completed it, by calling different functions for different buttons clicked, and appending the value in the textbox with the value of the button pressed. Using python 2.7.3
Is there a way to obtain the label value of the button pressed so that i can use a single function instead of 10 functions from 0 to 9?
Thanks in advance
Button callbacks include the widget itself, and you can also pass data. See here.
instead of reading the label of the GtkButton, which is pretty much error prone, you should associate the value represented by the button to the button instance itself, e.g.:
button = Gtk.Button(label='1')
button._value = 1
# add button to the container
button.connect('clicked', on_button_clicked)
button = Gtk.Button(label='2')
button._value = 2
# add button to the container
button.connect('clicked', on_button_clicked)
and then read the value from the button instance inside the signal handler, e.g.:
def on_button_clicked(button):
print 'you pressed the button of value: %d' % (button._value)
GtkWidget instances in Python are Python object, and thus behave like any other Python object.