Possible to execute a command from Tkinter Entry widget? - python

I have a tkinter GUI which includes an Entry Widget (tk.Entry). At the moment this displays a numeric value, which can be incremented up/down by a couple of tkinter Buttons. In addition to incrementing the value displayed in the Entry Widget, whenever the Button is clicked it executes a command which updates the appropriate setting on a physical instrument with the new value from the Entry Widget.
I am wondering if it is possible at all to also have the option that if the user types a number into the Entry Widget to overwrite what is already there, that this can execute the same command as clicking the up/down buttons? For example, if the value is set to 10, and the user enters 100, then the command is executed to update the real instrument to 100.
I tried to add the code command=mycommandname to the Entry Widget (e.g. input_wavelength = tk.Entry(pwr_mtr_ctrl_frame, relief=tk.GROOVE, font=( "Ariel", 11), justify='center', validate='key', vcmd=pwr_vcmd, command=mycommandname) but get the error "unknown option "-command""
I guess this means that the Entry Widget does not have the option to execute a function, like a Button widget does? Are there ways to implement this somehow?

def print_something(*args):
print('hello world')
root = TK()
entry1 = Entry(root)
entry1.bind("<Return>", print_something)
# you can use other keys and replace it with "<Return>". EX: "f"
# by default, this function will pass an unknown argument to your function.
# thus, you have to give your function a parameter; in this case, we will use *args
root.mainloop()

According to what you described you would be better "served" by using a Spinbox.
This being said you need to bind a function to the <Return> event captured by the Entry if you want to execute something when the user enters something:
Here is how to do it:
input_wavelength = tk.Entry(pwr_mtr_ctrl_frame, relief=tk.GROOVE, font=( "Ariel", 11), justify='center', validate='key', vcmd=pwr_vcmd)
input_wavelength.bind("<Return>",mycommandname)
If mycommandname is also used as a command you need to declare it like this:
def mycommandname(event=None):
...

Related

Calling tk.StringVar.set() on a tk.Entry textvariable causes validate="focusout" to stop getting called

The question's in the title, essentially: how do I get the validatecommand callback to continue being called after setting the Entry's textvariable? Here's the Minimum Working Example (MWE):
import tkinter as tk
root = tk.Tk()
sv = tk.StringVar()
def callback():
print(sv.get())
sv.set('Set Text.')
return True
e = tk.Entry(root, textvariable=sv, validate="focusout",
validatecommand=callback)
e.grid()
e = tk.Entry(root)
e.grid()
root.mainloop()
Note that the second tk.Entry widget is there to allow the first one to lose focus, which is the event we're trying to capture.
As the code is now, when you run it, you can change the top Entry widget's text once. It'll correctly get set to Set Text. Then, if you try to change the Entry's text again, the new text will be in the widget, but the callback doesn't happen.
On the other hand, if you comment out the sv.set('Set Text.') code, this behavior completely disappears, and the callback gets called as many times as you wish.
How can I have the sv.set() functionality, while still maintaining the callback getting called every time the Entry widget loses focus?
This is discussed in the Tk manual page for entry:
The validate option will also set itself to none when you edit the entry widget from within either the validateCommand or the invalidCommand. Such editions will override the one that was being validated.
Presumably, this is done to avoid infinite recursion.
You can run this (instead of the given Tcl code, after idle {%W config -validate %v})
root.after_idle(lambda: e.config(validate="focusout"))
from the callback to schedule a reconfiguration of the widget to enable validation again (after changing your sources so that e is the right Entry widget, i.e. not the second one).

How to register values to ttk.Spinbox via keyboard entry?

Can a ttk.Spinbox widget allow a user to type in values to it's entry field and have it registered? If so, how can I do so?
I am aware that it is possible to use the .set() method on the ttk.Spinbox's textvariable to alter its value. But this isn't what I was thinking off. Instead, I would simply like to allow the user to click on the ttk.Entry widget of the ttk.Spinbox and manually type in values there and have it registered to its textvariable. Presently, I can type in values there but nothing happens when I press the Return key.
Thank you.
Can a ttk.Spinbox widget allow a user to type in values to it's entry field and have it registered? If so, how can I do so?
If you associate a variable with the textvariable attribute, there's nothing else you need to do. Anytime the user changes the value, whether by the arrows or by typing into the editable portion of the widget, the value in the variable will instantly be updated.
You can verify this yourself by creating a spinbox and a label, both associated with the same variable. You can then see the label being updated in real time when you edit the spinbox.
Example:
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
spinvar = tk.IntVar()
spinbox = ttk.Spinbox(root, from_=0, to=100, textvariable=spinvar)
label = ttk.Label(root, textvariable=spinvar)
spinbox.pack()
label.pack()
root.mainloop()
Presently, I can type in values there but nothing happens when I press the Return key.
If you want something to happen when the user presses the <Return> key, you have to add a binding to call a function.
Example:
def do_something(event):
print("do something:", spinvar.get())
spinbox.bind("<Return>", do_something)

Tkinter Entry returns float values regardless of input

I have some pretty simple code right now that I am having issues with.
root = Tk()
label1 = Label(root, text ="Enter String:")
userInputString = Entry(root)
label1.pack()
userInputString.pack()
submit = Button(root,text = "Submit", command = root.destroy)
submit.pack(side =BOTTOM)
root.mainloop()
print(userInputString)
When I run the code everything operates as I would expect except
print(userInputString)
for an input asdf in the Entry print will return something like 0.9355325
But it will never be the same value back to back always random.
I am using python 3.5 and Eclipse Neon on a Windows 7 Machine.
Ultimately the goal is to accept a string from the user in the box that pops up and then be able to use that value as string later on. For example, it might be a file path that needs to be modified or opened.
Is Entry not the correct widget I should be using for this? Is there something inherently wrong with the code here? I am new to python and don't have a lot of strong programming experience so I am not even certain that this is set up right to receive a string.
Thanks in advance if anyone has any ideas.
There are two things wrong with your print statement. First, you print the widget, not the text in the widget. print(widget) prints str(widget), which is the tk pathname of the widget. The '.' represents the root window. The integer that follows is a number that tkinter assigned as the name of the widget. In current 3.6, it would instead be 'entry', so you would see ".entry".
Second, you try to print the widget text after you destroy the widget. After root.destroy, the python tkinter wrapper still exists, but the tk widget that it wrapped is gone. The following works on 3.6, Win10.
import tkinter as tk
root = tk.Tk()
label = tk.Label(root, text="Enter String:")
entry = tk.Entry(root)
def print_entry(event=None):
print(entry.get())
entry.bind('<Key-Return>', print_entry)
entry.focus_set()
submit = tk.Button(root, text="Submit", command=print_entry)
label.pack()
entry.pack()
submit.pack()
root.mainloop()
Bonus 1: I set the focus to the entry box so one can start typing without tabbing to the box or clicking on it.
Bonus 2: I bound the key to the submit function so one can submit without using the mouse. Note that the command then requires an 'event' parameter, but it must default to None to use it with the button.
The NMT Reference, which I use constantly, is fairly complete and mostly correct.

How to create a combobox that includes checkbox for each item?

Fairly new to tkinter and python I was wondering how to achieve a button that would act like this :
Click on button drops down a list (so that's a combobox)
Each line of the list has a checkbox.
Finally if a checkbox is clicked run a function, or (even better) once combobox is no more dropped run a function with items checked as args.
UPDATE
The button/menuButton will have to act like a filter. When menu is dropped down user can uncheck multiple options (without the menu to disappear each time an item is clicked) he don't want. Therefore it's really important to be able to see checkboxes so as the user know which options are currently active.
I finally used the idea of Bryan by creating a top level frame. Here is what I have :
There is no widget to do what you want. You'll have to create a toplevel window with a bunch of checkbuttons. You can then trigger the appearance with a normal button.
I don't think the OptionMenu is intended to hold anything but strings. It sounds like you want the functionality of a Listbox, which has options to allow for multiple selections, get all selected items, and so on.
This gives you an OptionMenu with checkboxes in the contained Menu. Check whichever items you like, then right-click in the tkinter window to print the values of the checkboxes to the console.
from tkinter import *
master = Tk()
var = StringVar(master)
var.set("Check")
w = OptionMenu(master, variable = var, value="options:")
w.pack()
first = BooleanVar()
second = BooleanVar()
third = BooleanVar()
w['menu'].add_checkbutton(label="First", onvalue=True,
offvalue=False, variable=first)
w['menu'].add_checkbutton(label="Second", onvalue=True,
offvalue=False, variable=second)
w['menu'].add_checkbutton(label="Third", onvalue=1,
offvalue=False, variable=third)
master.bind('<Button-3>', lambda x: print("First:", first.get(), " Second:",
second.get(), " - Third:", third.get()))
mainloop()
See also this.

Tkinter add entry on basis of an answer of a OptionMenu

I'm using TKinter (I'm new with GUI tools), and I would like to know if it is possible to add (or activate) a entry with base on the answer of a option menu. Below is a part of the code
from Tkinter import *
win=Tk()
Label(win, text="Is This a Data Cube?",font='20').grid(row=14, column=0,sticky=W)
DataCubeValue = StringVar(win)
DataCubeValue.set("False")
DataCube = OptionMenu(win,DataCubeValue,"True","False")
DataCube.grid(row=15, column=0,sticky=W)
If the answer is True is choosen I would like to display this:
Label(win, text="X and Y values (x,y)",font='20').grid(row=14, column=1,sticky=W)
XYValue = StringVar(win)
XYValue.set("10,7")
XY = Entry(win,textvariable=XYValue)
XY.grid(row=15, column=1,sticky=W)
A central idea of GUI programming is to register code to be executed in reaction of user actions. Such code is usually named callback (the toolkit call it back depending on user actions on the interface).
You can bind to DataCubeValue changes with the following line. callback method (to be defined before) will be cause each time the value of DataCubeValue change.
DataCubeValue.trace("w", callback)
In the callback method, you can either choose to place the block of code with Label and Entry instantiation, but think that callback will be called every time the user change the OptionMenu value. You could either deactivate the OptionMenu once the user used it, but I would advise to instantiate your widgets in the initial run, and just display or hide them from the callback.
def callback(*args):
if DataCubeValue.get() == "True":
label.grid(row=14, column=1,sticky=W)
XY.grid(row=15, column=1,sticky=W)
else:
label.grid_forget()
XY.grid_forget()

Categories

Resources