Python - TKinter - Editing Widgets - python

I need a widget in TKinter to be a global widget, however, I need the text displayed in it to be different every time. I'm quite new with TKinter and haven't yet successfully managed to edit an option in a widget.
I assume it's something to do with widget.add_option() but the documentation is quite confusing to me and I can't figure out the command.
I specifically just need to edit the text = "" section.
Thanks
EDIT:
gm1_b_current_choice_label = Label(frame_gm1_b, text = "Current input is:\t %s"% str(save_game[6]))
I specifically need to update the save_game[6] (which is a list) in the widget creation, but I assume once the widget is created that's it. I could create the widget every time before I place it but this causes issues with destroying it later.

You can use the .config method to change options on a Tkinter widget.
To demonstrate, consider this simple script:
from Tkinter import Tk, Button, Label
root = Tk()
label = Label(text="This is some text")
label.grid()
def click():
label.config(text="This is different text")
Button(text="Change text", command=click).grid()
root.mainloop()
When the button is clicked, the label's text is changed.
Note that you could also do this:
label["text"] = "This is different text"
or this:
label.configure(text="This is different text")
All three solutions ultimately do the same thing, so you can pick whichever you like.

You can always use the .configure(text = "new text") method, as iCodez suggested.
Alternatively, try using a StringVar as the text_variable parameter:
my_text_var = StringVar(frame_gm1_b)
my_text_var.set("Current input is:\t %s"% str(save_game[6]))
gm1_b_current_choice_label = Label(frame_gm1_b, textvariable = my_text_var)
Then, you can change the text by directly altering my_text_var:
my_text_var.set("Some new text")
This can be linked to a button or another event-based widget, or however else you want to change the text.

Related

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 do I prepopulate a text field with suggested text in Tkinter?

I'm trying to prepopulate a text field based on the most recent entry. As this is not a Listbox, I don't see how to do it, and I'm not seeing any examples on the web. Thanks.
Update. I've managed to find a partial way of doing this. Still wondering, is it possible to supply suggested text in Tkinter which fades when the text box is clicked?
from Tkinter import *
app = Tk()
app.title("GUI Example")
app.geometry('560x460+200+200')
x = Text(app)
x.insert(END, "Before")
x.pack()
def replace():
x.delete(1.0, END)
x.insert(END, "After")
abutton = Button(app, text="Click me", command=replace)
abutton.pack()
app.mainloop()
Well, I personally don't know of any options to do this (any answers giving one will easily trump this one).
However, you can closely mimic this behavior with a little coding. Namely, you can bind the textbox to a function that will insert/remove the default text for you.
Below is a simple script to demonstrate:
import Tkinter as tk
tk.Tk()
textbox = tk.Text(height=10, width=10)
textbox.insert(tk.END, "Default")
textbox.pack()
# This is for demonstration purposes
tk.Text(height=10, width=10).pack()
def default(event):
current = textbox.get("1.0", tk.END)
if current == "Default\n":
textbox.delete("1.0", tk.END)
elif current == "\n":
textbox.insert("1.0", "Default")
textbox.bind("<FocusIn>", default)
textbox.bind("<FocusOut>", default)
tk.mainloop()
Notice how:
When you click in the top textbox, the default text disappears.
When you click in the bottom textbox, the top one loses focus and the default text reappears.
This behavior will only occur if there is nothing in the top textbox.

Validation on Tkinter.Text widget?

What are my options for getting validation with the Tkinter.Text widget? I don't require Text's advanced functionality, just its multiline attribute. Unfortunately, it lacks both textvariable and validate commands, so it seems that I cannot attach some kind of callback that checks things every time the text changes. I'd like to avoid having to bind to <KeyRelease>, as that looks to capture ALL keypresses, including the likes of Shift, Ctrl, etc, keys, and would appear to be a bit of a mess to work right.
I basically just need to check if the Text field is blank or not, and enable/disable an "Ok" button as appropriate (i.e., if no text, then the button is disabled).
In lieu of this, has anyone come across a decent subclass of Entry that adds multiline functionality that is written in Python? There is this, which adds textvariable to Text, but it is written in pure TCL, not Python, and seems like it would be difficult to integrate into my existing Python environment.
The binding to the <KeyRelease> button does not need to be messy, you don't have to check the value of the key pressed but fetch the content of the widget. Keep in mind that it always has a '\n' at the end, so when you retrive the contents don't forget to discard it:
content = text.get(1.0, "end-1c")
Then you just need to change the state of the button based on this value:
import Tkinter as tk
def configure_ok_button(event):
content = event.widget.get(1.0, "end-1c")
state = "active" if content else "disabled"
button.configure(state=state)
root = tk.Tk()
text = tk.Text(root)
button = tk.Button(root, text="Ok", state="disabled")
text.bind("<KeyRelease>", configure_ok_button)
text.pack()
button.pack()
root.mainloop()

Python, Tkinter: How to redirect the output of a function to a notebook tab?

I am wondering if it is possible to redirect the output of a function to a tab in the ttk notebook widget.
I assumed it would be similar to the listbox widget where you just used listbox.insert but I can not get this to work.
I apologize if this is a simple question but its really stumped me and I am unable to find any helpful material online to help me.
thanks in advance
Im using python 3.3
The Insert function works almost the same, the only difference is instead of taking a string it takes a frame. Add is a lot simpler though, you don't need to specify an index it just adds it to the end. All you need to do is create a frame, pack a Text element into it, and then pack the whole thing into the notebook. It would look something like this
noteb = ttk.Notebook( root, width=500, height=300 )
frame1 = tkinter.Frame( noteb )
textbox = tkinter.Text( frame1, put whatever you want to put here )
frame1.pack( expand=1, fill='both' )
noteb.add( frame1, whatever parameters you want )
noteb.pack( expand=1, fill='both' )
You should then be able to change the text in textbox directly.
Depends somewhat on what type of widgets you use as tabs, but basically it shouldn't be very different. Just keep track of your tab widgets and call the appropriate method.
Example with two Text tabs:
from Tkinter import *
from ttk import Notebook
def addText(tab):
tab.insert(END, "foo! ")
root = Tk()
nb = Notebook(root, height=240, width=480)
tabs = {"foo": [], "bar": []}
for tabname in tabs:
tab = Text(nb)
tabs[tabname] = tab
nb.add(tab, text= tabname)
nb.pack()
Button(root, text= "Add text!", command = lambda: addText(tabs["foo"])).pack()
root.mainloop()
Clicking the "Add text!" button appends some text to the first tab.

How to disable input to a Text widget but allow programmatic input?

How would i go about locking a Text widget so that the user can only select and copy text out of it, but i would still be able to insert text into the Text from a function or similar?
Have you tried simply disabling the text widget?
text_widget.configure(state="disabled")
On some platforms, you also need to add a binding on <1> to give the focus to the widget, otherwise the highlighting for copy doesn't appear:
text_widget.bind("<1>", lambda event: text_widget.focus_set())
If you disable the widget, to insert programatically you simply need to
Change the state of the widget to NORMAL
Insert the text, and then
Change the state back to DISABLED
As long as you don't call update in the middle of that then there's no way for the user to be able to enter anything interactively.
Sorry I'm late to the party but I found this page looking for the same solution as you.
I found that if you "disable" the Text widget by default and then "normal" it at the beginning of a function that gives it input and "disable" it again at the end of the function.
def __init__():
self.output_box = Text(fourth_frame, width=160, height=25, background="black", foreground="white")
self.output_box.configure(state="disabled")
def somefunction():
self.output_box.configure(state="normal")
(some function goes here)
self.output_box.configure(state="disable")
I stumbled upon the state="normal"/state="disabled" solution as well, however then you are unable to select and copy text out of it. Finally I found the solution below from: Is there a way to make the Tkinter text widget read only?, and this solution allows you to select and copy text as well as follow hyperlinks.
import Tkinter
root = Tkinter.Tk()
readonly = Tkinter.Text(root)
readonly.bind("<Key>", lambda e: "break")

Categories

Resources