Tkinter. Press Enter in Entry box. Append to Text box. How? - python

I am making a chat program and decided to use Tkinter for the interface.
What I wanna do is a breeze in C# but Tkinter is new to me.
Basically I have a form with a Entry control and a Text control.
I want to know how to append text from the Entry control to the Text control after the user presses Enter.
Here's my code so far:
from tkinter import *
class Application:
def hello(self):
msg = tkinter.messagebox.askquestion('title','question')
def __init__(self, form):
form.resizable(0,0)
form.minsize(200, 200)
form.title('Top Level')
# Global Padding pady and padx
pad_x = 5
pad_y = 5
# create a toplevel menu
menubar = Menu(form)
#command= parameter missing.
menubar.add_command(label="Menu1")
#command= parameter missing.
menubar.add_command(label="Menu2")
#command= parameter missing.
menubar.add_command(label="Menu3")
# display the menu
form.config(menu=menubar)
# Create controls
label1 = Label(form, text="Label1")
textbox1 = Entry(form)
#command= parameter missing.
button1 = Button(form, text='Button1')
scrollbar1 = Scrollbar(form)
textarea1 = Text(form, width=20, height=10)
textarea1.config(yscrollcommand=scrollbar1.set)
scrollbar1.config(command=textarea1.yview)
textarea1.grid(row=0, column=1, padx=pad_x, pady=pad_y, sticky=W)
scrollbar1.grid(row=0, column=2, padx=pad_x, pady=pad_y, sticky=W)
textbox1.grid(row=1, column=1, padx=pad_x, pady=pad_y, sticky=W)
button1.grid(row=1, column=2, padx=pad_x, pady=pad_y, sticky=W)
form.mainloop()
root = Tk()
Application(root)

So you're using a tkinter.Text box, which supports the .insert method. Let's use it!
def __init__(self,form):
# Lots of your code is duplicated here, so I'm just highlighting the main parts
button1 = Button(form, text='Button1', command = self.addchat)
self.textbox = textbox1 # to make it accessible outside your __init__
self.textarea = textarea1 # see above
form.bind("<Return>", lambda x: self.addchat())
# this is the magic that makes your enter key do something
def addchat(self):
txt = self.textbox.get()
# gets everything in your textbox
self.textarea.insert(END,"\n"+txt)
# tosses txt into textarea on a new line after the end
self.textbox.delete(0,END) # deletes your textbox text

Related

Tkinter - Python, how do I cause a button click to assign a value to a variable?

Using Tkinter and Python. Already created a window for the buttons to be placed on. I want there to be four buttons to appear, and I want to be able to click one of the four buttons, and be able for it to set the selection variable = "whatever I clicked", so that I can then use this variable later to call an API. When I run the program and click on the "General knowledge" button and print the selection, it does correctly print "General knowledge", but then when I try to return this selection variable it just doesn't work and I don't know why.
def select1():
selection = "General Knowledge"
print(selection)
def select2():
selection = "Science"
def select3():
selection = "Entertainment"
def select4():
selection = "Miscellaneous"
button1 = tk.Button(text = "General Knowledge", command = select1)
button1.place(x=100, y=100)
button2 = tk.Button(text = "Science", command = select2)
button2.place(x=100, y=140)
button3 = tk.Button(text = "Entertainment", command = select3)
button3.place(x=100, y=180)
button4 = tk.Button(text = "Miscellaneous", command = select4)
button4.place(x=100, y=220)
There are several ways to accomplish your goal.
One way is to write a single function that will take a value to assign to your variable. This way you can have as many buttons as you like and only a single function.
Not if you are using functions you have to either pass the variable to the function or let the function know it is in the global namespace.
import tkinter as tk
root = tk.Tk()
selection = ''
def assign_value(value):
global selection
selection = value
lbl["text"] = value
print(selection)
lbl = tk.Label(root, text='Selection Goes Here')
lbl.grid(row=0, column=0)
tk.Button(text="General Knowledge", command=lambda: assign_value("General Knowledge")).grid(row=1, column=0)
tk.Button(text="Science", command=lambda: assign_value("Science")).grid(row=2, column=0)
tk.Button(text="Entertainment", command=lambda: assign_value("Entertainment")).grid(row=3, column=0)
tk.Button(text="Miscellaneous", command=lambda: assign_value("Miscellaneous")).grid(row=4, column=0)
root.mainloop()
Or you can assign the value directly from the button.
import tkinter as tk
root = tk.Tk()
selection = tk.StringVar()
selection.set('Selection Goes Here')
lbl = tk.Label(root, textvariable=selection)
lbl.grid(row=0, column=0)
tk.Button(text="General Knowledge", command=lambda: selection.set("General Knowledge")).grid(row=1, column=0)
tk.Button(text="Science", command=lambda: selection.set("Science")).grid(row=2, column=0)
tk.Button(text="Entertainment", command=lambda: selection.set("Entertainment")).grid(row=3, column=0)
tk.Button(text="Miscellaneous", command=lambda: selection.set("Miscellaneous")).grid(row=4, column=0)
root.mainloop()
I am sure if I spent more time on this I could think up something else but the idea is basically write your code in a more DRY (Don't Repeat Yourself) fashion and make sure you are assigning the value to the variable in the global namespace or else it will not work as you expect.

Tkinter PopUp window not taking the textvariable values from Entry and Combobox

I used Tkinter in Python3 to create a GUI and one of the functions is a pop up window after a button click. This is how my popup window looks like this. The pop up window will take the user inputs and update a variable from the class object (self). Everything works fine except the part in the function UpdateValues() as shown in the code below.
After inputting and updating the Frequency (variable freq in the code) and Iterations (variable loop in code) values in the popup window, they fail to print on the terminal and give a blank screen. Thus the self.freq and self.loop are unable to get updated.
I'm a newbie to python-classes and tkinter and have been struggling with this problem for a while now. Any help will be much appreciated. Thank you!
CODE:
'''Class and other attributes here'''
# Blinking light ssh command
self.freq = "500"
self.loop = "10"
def RunCode():
cmd = "sshpass -p \"raspberry\" ssh -to StrictHostKeyChecking=no pi#pi ./led "+self.freq+" "+self.loop
os.system(cmd)
def PopUpBox1():
popup = tk.Tk()
popup.title("Edit Parameters")
w = 325
h = 75
x = (ws/2) - w/2
y = (hs/2) - h/2
popup.geometry('%dx%d+%d+%d' % (w,h,x,y))
popup.resizable(False,False)
# Adding widgets to PopUpBox
# Modified Button Click Function for Update
def UpdateValues():
update.configure(text='Updated')
print(freq.get())
print(loop.get())
self.freq = str(freq.get())
self.loop = str(loop.get())
popup.destroy()
# Frequency and Iterations label
ttk.Label(popup, text="Frequency:",font='200').grid(column=0, row=0, padx=4, pady=4, sticky='w')
ttk.Label(popup, text="Iterations:",font='200').grid(column=1, row=0, padx=4, pady=4, sticky='w')
# Adding a Textbox Entry widget for frequency values
freq = tk.StringVar()
name_entered = tk.Entry(popup, width=12, textvariable=freq)
name_entered.grid(column=0, row=1, padx=4, pady=4)
# Adding a Combobox for iteration values
loop = tk.StringVar()
number_chosen = ttk.Combobox(popup, width=12, textvariable=loop)
number_chosen['values'] = (1, 2, 4, 42, 100)
number_chosen.grid(column=1, row=1, padx=4, pady=4)
number_chosen.current(0)
# Adding a Button for Updation
update = ttk.Button(popup, text="Update", command = UpdateValues)
update.grid(column=2, row=1, padx=4, pady=4)
# Place cursor into name Entry
name_entered.focus()

python 3 Tkinter ComboBox don't get value

I am trying to get the value of from a combobox in tkinter using python 3.6, i been looking to many tutorials but i don't see the problem yet.
every time i press the button don't show anything.
but also there is not errors.
so to clarify ... I am trying to get the value of the tk.combobox when i press ttk.Button.
thank you in advance for any ideas or comments.
this is what i have so far.
import tkinter as tk
from tkinter import ttk
def combo_box_updater():
total_location = ['linden', 'mineola', 'brooklyn']
return total_location
def start_analisys(event=None):
site = jobsite_name.get()
print(site)
# this is part of a definition that automatically will update the names in later versions
job_site = combo_box_updater()
# basic gui setup
unified = tk.Toplevel()
unified.title('Unified 1 Week Timesheet')
unified.configure(background="#00012f")
unified.geometry("650x200")
unified.resizable(width=False, height=False)
entry_width = 30
# basic frame
frame1 = tk.Frame(unified)
frame1.grid(row=0, column=0, sticky='w')
# combo box in the fourth row
jobsite_name = tk.StringVar()
combo_box = ttk.Combobox(frame1, font="none 12 bold", width=20, textvariable=jobsite_name, text="choose location")
combo_box.grid(row=0, column=1, sticky="wesn")
combo_box['values'] = [x for x in job_site]
# Left button side
ttk.Button(frame1, text='Run', command=start_analisys, ).grid(row=0, column=2, sticky='nsew', rowspan=3)
unified.mainloop()
Made three minor edits to your code: added a label to display the result, added a line to combo box setup, and changed the creation of the main window.
import tkinter as tk
from tkinter import ttk
def combo_box_updater():
total_location = ['linden', 'mineola', 'brooklyn']
return total_location
def start_analisys(event=None):
site = jobsite_name.get()
aLabel["text"] = site
print(site)
# this is part of a definition that automatically will update the names in later versions
job_site = combo_box_updater()
# basic gui setup
unified = tk.Tk()
unified.title('Unified 1 Week Timesheet')
unified.configure(background="#00012f")
unified.geometry("650x200")
unified.resizable(width=False, height=False)
entry_width = 30
# basic frame
frame1 = tk.Frame(unified)
frame1.grid(row=0, column=0, sticky='w')
# combo box in the fourth row
jobsite_name = tk.StringVar()
combo_box = ttk.Combobox(frame1, font="none 12 bold", width=20, textvariable=jobsite_name)
combo_box.grid(row=0, column=1, sticky="wesn")
combo_box['values'] = [x for x in job_site]
combo_box.current(0)
# Left button side
ttk.Button(frame1, text='Run', command=start_analisys, ).grid(row=0, column=2, sticky='nsew', rowspan=3)
# add a label
aLabel = ttk.Label(frame1, text='My Label')
# place the label
aLabel.grid(column=3, row=0)
unified.mainloop()
if __name__ == '__main__':
pass
When you add the values as an afterthought like that you need to add the corresponding commands as well. It's much better to add the values through the init method so the commands are automatically added:
jobsite_name = tk.StringVar(value="choose location")
combo_box = ttk.Combobox(frame1, textvariable=jobsite_name, values=job_site, font="none 12 bold", width=20)

Focus Events (or lack thereof)

I am having a hard time understanding the focus events for Entry and Textbox fields in Python version 3 using Tk. I eventually need to validate an Entry box on lost focus if I click a radio option or a button.
If you run the code below then (which serves only to demonstrate Focus issues not the validation i require elsewhere), place the cursor in either of the top row Entry boxes and click between the other widgets, the only time FocusIn and Focus out events occur are on the widgets that accept input ie Text/Entry boxes.
Clicking the button or the radio options, the cursor remains in the Entry or Textbox widgets. Why when i have clearly focused on a radio option or the button.
I have tried .bind FocusIn/Out events and still no joy. if anyone has an explanation I would be intrigued to know why and possibly how i can overcome it.
from tkinter import *
root = Tk()
root.title("My Widgets")
root.update_idletasks()
root.geometry("350x200+10+300")
root.attributes("-toolwindow",1)
root.resizable(width=FALSE, height=FALSE)
root.config(bg="blue")
# function below output to the console and label the focus results
def Validate(a,b,c,d,e,f,g,h):
text = g + ' on ' + h
lblOutputVar.set(text)
print(f,g,h)
return True
var = IntVar()
lblOutputVar = StringVar()
vcmd=(root.register(Validate),'%d','%i','%P','%s','%S','%v','%V','%W')
entryOne = Entry(root, name = 'entryBoxOne')
entryOne.config(validate = 'all',vcmd=vcmd)
entryOne.grid(row=1, column=1,padx=(0,0),pady=(10,10),ipady=(1), sticky=E+W)
entryTwo = Entry(root, name = 'entryBoxTwo')
entryTwo.config(validate = 'all',vcmd=vcmd)
entryTwo.grid(row=1, column=2,padx=(10,0),pady=(10,10),ipady=(1), sticky=E+W)
txtBox = Text(root, name = 'textBox', width=10, height=1, takefocus = 0)
txtBox.grid(row=5, column=1, sticky=E+W)
aButton = Button(root, text = 'Click Me!', takefocus=1)
aButton.grid(row=5, column=2)
lblOutput = Label(root, name = 'labelOutput', width=20, height=2, textvariable=lblOutputVar)
lblOutput.grid(row=10, column=1, columnspan =2, pady=(5,0), sticky=E+W)
radioOne = Radiobutton(root, anchor = 'w', text = 'One', variable = var, value = 1, takefocus = 1)
radioOne.grid(row=2, column=1, sticky=E+W)
radioTwo = Radiobutton(root, anchor = 'w', text = 'Two', variable = var, value = 2, takefocus = 1)``
radioTwo.grid(row=3, column=1, sticky=E+W)
root.mainloop()
The explanation is simply that tkinter buttons and radiobuttons aren't given focus when you click on them. If you want that to happen, you need to set up a binding to explicitly give them the focus.
Your other option is to use a ttk radiobutton which does get focus. It's unfortunate that the two different radiobuttons have different behavior.

tkinter grid alignment: Python 2.7

I'm having a problem with the grid alignment when I add in a text box.
I've set up a simple GUI with a 3 column wide display. As part fo the GUI I have a text box for entering notes, and a spinbox for a defined number range.
If I remove the text box from the active code my spinbox aligns correctly with all other entries, but when I place the text box in the grid my spinbox is moved over to the right.
Doesn't seem to matter where the spinbox code is in relation to the text box, once the text box is present the spin box moves over to the right.
At this stage I just can't see what is causing the problem.
I'll admit I'm new to Tkinter (and stackoverflow).
This is the particular line of code that causes the problem:
self.newText.grid(row=display_row, column=0, columnspan=4, padx=10, pady=10).
Sample code below. If I comment out the above line the spin box aligns correctly, if its present then the spinbox is offset. Its only the spinbox that is affected, neither Label, Entry, RadioButton or Text widgets are affected, but Spinbox is. These are the only widgets needed for my GUI.
Any help appreciated.
#-------------------------------------------------------------------------------
# Name: MyGUI
# Purpose: Problem Sample
#
#-------------------------------------------------------------------------------
from Tkinter import *
#===============================
# GUI Class
#===============================
class GUIClass():
'''
GUI class
'''
def __init__(self):
self.displayframe = 0
self.NameVar = StringVar()
self.NumVar = StringVar() # shouldn't be but it works
self.ButtonVar = BooleanVar()
#===============================
# Function for standard button
def StandardEntry(self, display_row,labeltext,entryvar):
'''
Standard 'Entry' feature for GUI.
'''
Label(self.displayframe, text=labeltext).grid(row=display_row, column=0, sticky=W)
name = Entry(self.displayframe, textvariable=entryvar)
name.grid(row=display_row, column=1, sticky=W)
display_row+=1
def BooleanRadioButton(self, display_row, labeltext, entryvar):
'''
Boolean true/false radio button function
'''
Label(self.displayframe, text=labeltext).grid(row=display_row, column=0, sticky=W)
ButtonOn = Radiobutton(self.displayframe, text="Enabled", variable=entryvar, value=True)
ButtonOn.grid(row=display_row, column=1, sticky=W)
ButtonOn = Radiobutton(self.displayframe, text="Disabled", variable=entryvar, value=False)
ButtonOn.grid(row=display_row, column=2, sticky=W)
def StandardSpinBox(self, display_row, labeltext, min_value, max_value, variablename):
'''
Standard spinbox for this project.
'''
Label(self.displayframe, text=labeltext).grid(row=display_row, column=0, sticky=W)
spinboxwidget = Spinbox(self.displayframe, from_=min_value, to=max_value, textvariable=variablename)
spinboxwidget.grid(row=display_row, column=1)
def AddFreeTextForm(self, display_row, notes):
'''
Standard widget for free text entry
'''
self.newText = Text(self.displayframe, width=50, height=8, takefocus=0)
self.newText.grid(row=display_row, column=0, columnspan=4, padx=10, pady=10)
def movesettingstoclass(self, dataclass):
dataclass.NameVar = self.NameVar.get()
dataclass.NumVar = int(self.NumVar.get())
dataclass.ButtonVar = self.ButtonVar.get()
def populate(self, dataclass):
'''
Takes the data in the data structure and populates the GUI.
'''
self.NameVar.set(dataclass.NameVar)
self.NumVar.set(str(dataclass.NumVar))
self.ButtonVar.set(dataclass.ButtonVar)
#===============================
# Data Class
#===============================
class DataClass():
def __init__(self):
self.NameVar = 'SomeName'
self.NumVar = 11
self.ButtonVar = False
def showvalues(self):
'''
Debug function/method for checking values are set correctly.
'''
msg += 'NameVar : %s\n' %self.NameVar
msg += 'NumVar : %d\n' %self.NumVar
msg += 'KVVar : %d\n' %self.KVVar
if self.ButtonVar == True:
msg += 'ButtonVar: True\n'
else:
msg += 'ButtonVar: False\n'
print msg
#=============================================
# Main window
#=============================================
root = Tk()
MyData = DataClass()
mainGUI = GUIClass()
root.title('Problem Example')
menu = Menu(root)
root.config(menu=menu)
#==============================================================================
# text fields to be entered by the user...
display_row = 0
Notes = ''
mainGUI.displayframe = Frame(root)
#==============================================================================
# Some entry input parameter
mainGUI.StandardEntry(display_row, "Some Label", mainGUI.NameVar)
display_row+=1
#==============================================================================
# Some spinbox input parameter
mainGUI.StandardSpinBox(display_row, "Some Label", 3, 21, mainGUI.NumVar)
display_row+=1
#==============================================================================
# Some Radiobutton input parameter
SwitchOn = mainGUI.BooleanRadioButton(display_row, "Button Label", mainGUI.ButtonVar)
display_row+=1
Label(mainGUI.displayframe, text="Configuration Notes").grid(row=display_row, column=1, sticky=W)
display_row += 1
#notes = mainGUI.AddFreeTextForm(display_row, "Configuration Notes", MyData.Notes)
notes = mainGUI.AddFreeTextForm(display_row, Notes)
display_row+=1
mainGUI.displayframe.pack(anchor='w')
#==============================================================================
# and the magic all happens here
mainloop()
You forgot to set the sticky parameter when calling the spinbox' grid method.
spinboxwidget.grid(row=display_row, column=1, sticky=W)

Categories