Performing tasks on input given by entry and updating label constantly - python-2.7

So im a little new to tkinter and was making a gui. one of the problems i was having was that when i got a value from a entry widget. i could not get the labels that were associated with that entry widget to update after i had done some arithmetic to it. for example
var = tk.StringVar
entry1 = tk.Entry(root, textvariable = var)
entry1.pack()
then do something with var
label1 = tk.Label(root, text = var)
label1.pack()
i looked around before asking this and what i found was to connect the variables. i tried that but it still would not update after the first time.
How would i get the label to update everytime a new value was entered in entry. like if 2 was entered 4 would be displayed. then if i entered 5 then the label should update automatically and 10 should be dislplayed. in this case im just multiplying by two. the label should update until i close the program.
Thanks was having alot of trouble figuring this out any help is appreciated

def enter_hit(event):
do_something_with(var.get())
var = tk.StringVar
entry1 = tk.Entry(root, textvariable = var)
entry1.pack()
label1 = tk.Label(root, text = var)
label1.pack()
entry1.bind("<Return>",enter_hit)
When you hit Enter on entry1, then it calls enter_hit. Then var and it's text can be gotten, and you can do what you want with it to affect label1.
If this doesn't suit you, and you want it to change the moment a character is inputted, then try trace.
def traced_event(event):
do_something_with(var.get())
var = tk.StringVar
entry1 = tk.Entry(root, textvariable = var)
entry1.pack()
label1 = tk.Label(root, text = var)
label1.pack()
var.trace("w", traced_event)

Related

How can I save multiple entries to a list and then print a random entry from that list?

Hello i can only seem to print letters from an entry not the full entry (sentence).
I simply want to click a button using tkinter and after typing a sentence into a box, the button will store the sentences in a list.
Then I want to create a second button that will then print a random sentence from that list.
When I try this it only prints letters of the stored sentence.
Any ideas would be greatly appreciated as I’ve looked around for the last two days before asking.
Best wishes to you all
from tkinter import *
import random
def super_function():
out = map(Entry.get, entr)
clear_entry_1()
def clear_entry_1():
Entry_field.delete(0,END)
def super_function_2():
print(random.choice(entr))
root = Tk()
root.geometry('400x400')
entr = []
for i in range(10):
entr.append(Entry(root))
Entry_field = Entry()
Entry_field.pack()
Button1 = Button(root, text = 'Add your idea!', command =
super_function)
Button1.pack()
Button2 = Button(root, text='Generate an idea!',
command=super_function_2)
Button2.pack()
root.mainloop()
The for loop is useless and should be removed as it just appends 10 invisible entries.
What you need is to append the sentence inside super_function() instead:
def super_function():
# save the sentence
entr.append(Entry_field.get())
clear_entry_1()

Change text colour in Tkinter combobox, based on origin

I have two lots of computer names found in AD, all of which are sorted together and entered into a tkinter drop-down combobox. I would like to be able to change the text colour of the entries in the drop-down depending on which original list of computers it came from.
OPSpclist = []
OPS_pcs = active_directory.AD_object ("LDAP://OU=Locations - ...")
for OPSpc in OPS_pcs.search (objectCategory='Computer'):
OPSpc = str(OPSpc).upper()
OPSpc = OPSpc.split(",")[0].split("=")[1]
OPSpclist.append(OPSpc)
OSpclist = []
OS_pcs = active_directory.AD_object ("LDAP://OU=Locations - ...")
for OSpc in OS_pcs.search (objectCategory='Computer'):
OSpc = str(OSpc).upper()
OSpc = OSpc.split(",")[0].split("=")[1]
OSpclist.append(OSpc)
bothSchools = sorted(OSpclist) + sorted(OPSpclist)
optionList = sorted(bothSchools)
var1 = StringVar()
var1.set(optionList[0])
pcnameEntry = ttk.Combobox(entryframe, textvariable = var1, values = optionList, width=25)
pcnameEntry.focus_set()
pcnameEntry.grid(row=1, column=0, sticky=W, pady=(0, 10), padx=5)
Is it possible to have the items from the first list to appear in a different colour, all within the same, sorted, combobox drop-down list?
Thanks,
Chris.
Yes this is possible, the drop down is a listbox and therefore the items can be configured separately with the itemconfigure method. However, I don't know how to retrieve the combobox's listbox via Python but this can be done through tcl commands:
import Tkinter as tk
import ttk
root = tk.Tk()
l1 = [(name, 'computer 1') for name in 'ABCD']
l2 = [(name, 'computer 2') for name in 'ACEG']
l = sorted(l1 + l2)
combo = ttk.Combobox(root, values=[name for name, computer in l])
combo.pack()
combo.update_idletasks()
# I need to display the drop down once before setting the items' colors otherwise
# I get an error telling me the items don't exist, so I generate a click on the combobox button
combo.event_generate('<1>', x=combo.winfo_width() - 4, y=1)
colors = {'computer 1': 'blue', 'computer 2': 'red'}
# define the tcl variable corresponding to the drop down listbox
combo.tk.eval('set popdown [ttk::combobox::PopdownWindow %s]' % combo)
for i, (name, computer) in enumerate(l):
# set the color of each item (the background color can be changed too by adding '-background <color>')
combo.tk.eval('$popdown.f.l itemconfigure %i -foreground %s' % (i, colors[computer]))
root.mainloop()

Checkbuttons not properly aligning in Tkinter

I am a Biological Engineering student working on a Capstone project in my university, and part of this project requires a little bit of coding. None of our group members knew how to code, so I've taken it upon myself to learn python and attempt to create a GUI using Tkinter. Given the reason for coding, I am extremely new to programming and thus, as a forewarning, my code is probably rather poorly written.
So to get to the point; I am having a problem getting my Checkbuttons to properly align. Essentially what happens is that the first Checkbutton group is aligned on rows 3-6 (I think, not 100% sure but they are where I want them) in column 0. I then created a second Checkbutton group in column 1, and I want the Checkbuttons to begin back at row 3-whatever, but instead they start at row 7 and span until whenever. This happens for each subsequent Checkbutton group I make.
The code is as follows:
import sys
from Tkinter import *
import tkMessageBox
import tkFileDialog
from PIL import ImageTk, Image
root = Tk()
root.geometry('900x700')
root.title('IBID 2.0')
ilabel1 = Label(root, text=' Measurement',font=("Bold",18)).grid(row=1,column=0)
datatype = {'Joint Angle' : 0,
'Joint Acceleration' : 0,
'Ground Reaction Force' : 0,
'Muscle Activation' : 0
}
for measure in datatype:
datatype[measure] = IntVar()
dt_cb = Checkbutton(root, text=measure, variable=datatype[measure])
dt_cb.grid(column=0, sticky='W', padx=20)
ilabel2 = Label(root, text='Muscle Group(s)',font= ("Bold",18),padx=30).grid(row=1,column=1)
emg_groups = {'Quadriceps' : 0,
'Hamstrings' : 0,
'Calves' : 0
}
for measure in emg_groups:
emg_groups[measure] = IntVar()
emg_cb = Checkbutton(root, text=measure, variable=emg_groups[measure])
emg_cb.grid(column=1, sticky='W', padx=20)
ilabel3 = Label(root, text='Ground Reaction Force',font=("Bold",18),padx=30).grid(row=1,column=2)
grf_groups = {'Ground Reaction Force' : 0,
'Gait' : 0,
}
for measure in grf_groups:
grf_groups[measure] = IntVar()
grf_cb = Checkbutton(root, text=measure, variable=grf_groups[measure])
grf_cb.grid(column=2, sticky='W', padx=40)
I did find a workaround where instead of using lists to create my Checkbuttons, I went ahead and made each button individually. I thought I might be able to clean up the code a little bit using lists, though I cannot find a way to put them all on the same line, I suppose. If I specify a row in the .grid(), then the options overlap one another.
Every time you call grid() without supplying a row Tkinter is automatically assuming you want to add it to a new row at the bottom:
wdgt.grid(row=0, column=0)
wdgt.grid(column=1) # row=1 is assumed here
Instead, you'll need to supply the row numbers to the new widgets you're trying to grid:
for i, measure in enumerate(emg_groups):
emg_groups[measure] = IntVar()
emg_cb = Checkbutton(root, text=measure, variable=emg_groups[measure])
emg_cb.grid(column=1, row=i+2, sticky='W', padx=20)
and:
for i, measure in enumerate(grf_groups):
grf_groups[measure] = IntVar()
grf_cb = Checkbutton(root, text=measure, variable=grf_groups[measure])
grf_cb.grid(column=2, row=i+2, sticky='W', padx=40)
Using enumerate() we get a tuple on each loop of the iteration, i being a 0 indexed counter, and of course measure being the object itself. Since you started your Label() at row 1 (you may want to change to start at row 0), we'll need to add 2 to the index each time through and then grid to that row number.

How do I update my text in Tkinter?

I am currently making a monopoly game, and I want to display what my players roll in a label. I have a file dice.py, which has a function roll that rolls the dice (using random.randint(1,6) twice, and adding them). I use a while True just to test it out, but it gives me this error:
TypeError: 'int' object does not support item assignment
when I do
str = ''
strlabel = canvas.create_text(553, 275, text = str, fill='snow3', font=('Times New Roman', 24))
while True:
roll = dice.roll()
str = 'You just rolled a %d!' %(roll)
strlabel["text"] = "hey"
var2 = raw_input()
The raw_input just makes a pause in between each roll. I can't find much on Tkinter out there, so could someone tell me the update text syntax?
The canvas.create_text doesn't create a new label. It create a new item (text) in the canvas and return the id (an int) of the created item.
You have to use the itemconfigure method to configure the item :
canvas.itemconfigure(strlabel, text='You just rolled a %d!'%(roll))

Python 2.7 - Tkinter - Button to move to next item in listbox

def nextItem(self):
active = self.skill_list_listbox.get(tk.ACTIVE)
listbox_contents = self.skill_list_listbox.get(0, tk.END)
current_pos = listbox_contents.index(active)
if current_pos + 1 < len(listbox_contents):
new_pos = current_pos + 1
self.skill_list_listbox.activate(new_pos)
self.skill_list_listbox.selection_set(tk.ACTIVE)
From what I can see within documentation this should highlight and activate the next item in the listbox. If I omit the selection_set I get what I'm looking for but there's no indicator of what's active. Adding it highlights an item, but if you continue to click the "next" button it simply adds to the highlight instead of just highlighting one item creating a long section of highlighted items, which I don't want. I've tried several different methods and this has got me the closest. If there was a 'clear selection' method I suppose I could get my desired effect of just having the next item selected and highlighted, but 3 calls just to do that seems a bit much for a common task? Any thoughts, or suggestions?
Below is an example of what I think you are trying to accomplish, using a button to select the next item in a Listbox. The gist of it is in the button's callback function, which calls selection_clear then selection_set.
Updated the example, hopefully a bit clearer as to what it happening
import Tkinter
class Application(Tkinter.Frame):
def __init__(self, master):
Tkinter.Frame.__init__(self, master)
self.master.minsize(width=256, height=256)
self.master.config()
self.pack()
self.main_frame = Tkinter.Frame()
self.some_list = [
'One',
'Two',
'Three',
'Four'
]
self.some_listbox = Tkinter.Listbox(self.main_frame)
self.some_listbox.pack(fill='both', expand=True)
self.main_frame.pack(fill='both', expand=True)
# insert our items into the list box
for i, item in enumerate(self.some_list):
self.some_listbox.insert(i, item)
# add a button to select the next item
self.some_button = Tkinter.Button(
self.main_frame, text="Next", command=self.next_selection)
self.some_button.pack(side='top')
# not really necessary, just make things look nice and centered
self.main_frame.place(in_=self.master, anchor='c', relx=.5, rely=.5)
def next_selection(self):
selection_indices = self.some_listbox.curselection()
# default next selection is the beginning
next_selection = 0
# make sure at least one item is selected
if len(selection_indices) > 0:
# Get the last selection, remember they are strings for some reason
# so convert to int
last_selection = int(selection_indices[-1])
# clear current selections
self.some_listbox.selection_clear(selection_indices)
# Make sure we're not at the last item
if last_selection < self.some_listbox.size() - 1:
next_selection = last_selection + 1
self.some_listbox.activate(next_selection)
self.some_listbox.selection_set(next_selection)
root = Tkinter.Tk()
app = Application(root)
app.mainloop()