Why is this Python 2.7 code generating excessive labels? - python-2.7

I'm working with Python 2.7 using idle.
I have a getVar Button, to get whatever text is in Entry
and put it in myEmpty Label, using a btnWork function. I only want one myEmpty Label.
However, in the following code if I put myEmpty Label in the function, I get labels everytime I click the button. This is not what I want.
from Tkinter import *
myGui=Tk()
myGui.geometry("200x100")
myGui.title("basicGUI")
myGui.configure(bg="gray")
entryVar = StringVar()
entryVar.set("")
entry = Entry(textvariable=entryVar, width=10)
entry.pack()
eV = StringVar()
def btnWork():
global eV
eV = StringVar()
myBtn=Button(text="getVar", command=btnWork)
myBtn.pack()
myEmpty = Label(textvariable=eV, width=10)
myEmpty.pack()
mainloop()
How can I prevent this?

When you click the button you need to get the information with .get() then update the label
from Tkinter import *
myGui=Tk()
myGui.geometry("200x100")
myGui.title("basicGUI")
myGui.configure(bg="gray")
eV=''
entry = Entry(width=10)
entry.pack()
def btnWork():
eV = entry.get()
myEmpty.config(text=eV)
myBtn=Button(text="getVar", command=btnWork)
myBtn.pack()
myEmpty = Label(text=eV, width=10)
myEmpty.pack()
myGui.mainloop()

Related

Treeview removing highlight when using an update loop

I have a Treeview table that calls records from an external MongoDB collection, which changes frequently, so I need to use an update loop to reflect the changes in my table. Whenever I highlight a row with the cursor, it displays the highlighted row with the selected background colour.
The problem is when the loop updates, the highlight disappears. I was wondering if someone could show me a method for keeping the highlight in place, regardless of the table updates?
If you run this code, you'll see what I mean:
from Tkinter import *
import Tkinter
import ttk as TTK
root = Tk()
style = TTK.Style()
tv = TTK.Treeview()
def highlight_row(event):
tree = event.widget
item = tree.identify_row(event.y)
tree.tk.call(tree, "tag", "remove", "highlight")
tree.tk.call(tree, "tag", "add", "highlight", item)
tv.grid(row=1, column=0)
tv.tag_configure('highlight', background='orange')
tv.bind("<Motion>", highlight_row)
style.configure("Treeview", font=(None, 12))
style.configure("Treeview", foreground= '#3F3F3F',
background= '#3F3F3F',
fieldbackground='#3F3F3F')
tv['columns'] = ('a','b','c')
tv.heading('a', text='a')
tv.column('a', anchor='center', width=100)
tv.heading('b', text='b')
tv.column('b', anchor='center', width=175)
tv.heading('c', text='c')
tv.column( 'c', anchor='center', width=90)
external_db = [{'x':1,'y':2, 'z':3},
{'x':4,'y':5, 'z':6},
{'x':7,'y':8, 'z':9}]
def update():
try:
for j in tv.get_children():
tv.delete(j)
for j, k in enumerate(external_db):
tv.insert('', 'end', text=str(j), values=(k['x'],k['y'],k['z']) ,tags = ('col'))
tv.tag_configure('col', foreground = 'white')
except Exception, e:
print e, 'Update Exception'
pass
root.after(1500,update)
update()
root.mainloop()
i.e. there is an orange background highlight that disappears every time root.after(1500,update) is called.
Any suggestions? Thanks.
#_____________________
Here is what root.configure(background="#3F3F3F") does for me:

How to write user input (taken from Tkinter's Entry) in newly created file

I wanted to get user input from user using Tkinter's Entry something like this
from Tkinter import *
top = Tk()
label = Label(top, text="Enter your bio")
entry = Entry(top, bd = 2)
def create_new():
new_file = open('file.txt', 'w+')
user_input = str(entry) # I ALSO TRIED WITHOUT str()
new_file.write(user_input) #still doesn't work
button = Button(top, text = "SAVE", fg ="red", command=create_new)
label.pack()
entry.pack()
button.pack()
top.mainloop()
When I add my info in the field and hit SAVE, it does create a new file.txt but it doesn't write my info into the file.txt
file.txt only has some numbers like these
.22775808
.22710272
.22382592
etc...
Any ideas on how can I fix this? Also what do these numbers mean and why are they here?
from tkinter import *
top = Tk()
label = Label(top, text="Enter your bio")
entry = Entry(top, bd = 2)
def create_new():
new_file = open('file.txt', 'w+')
user_input = (entry).get() # I ALSO TRIED WITHOUT str()
new_file.write(user_input) #still doesn't work
button = Button(top, text = "SAVE", fg ="red", command=create_new)
label.pack()
entry.pack()
button.pack()`enter code here`
top.mainloop()
You aren't writing the contents of the Entry, you're writing the Entry itself - which from Python's point of view is just the randomly-generated name of the actual widget which lives in the embedded Tcl/Tk interpreter. Use entry.get() for the actual contents.
You're also forgetting to close the file after you write to it, so anything you do manage to write may not show up immediately.

Tabbed GUI keeps hanging on entry box

I have a very primitive GUI built with Tkinter. This is my first attempt at a GUI so I am struggling to understand what is going on (and with syntax). Here is what I have:
from __future__ import division, print_function
import os, ttk, tkFileDialog, Tkconstants
import Tkinter as tk
import datetime as dt
Tkinter = tk
# define OS version
version = '0.0.2'
class TestGUI(tk.Tk):
def __init__(self,parent):
tk.Tk.__init__(self,parent)
self.parent = parent
self.initialize()
# try building list of instruments and sites
if os.path.isfile('config'):
with open(''config','r') as config:
config = dict( [(r.split('=')[0].strip(), r.split('=')[1].strip()) for r in config.read().split('\n') if r[0]<>'#'] )
self.datapath = config['datapath']
else:
self.datapath = '../'
def initialize(self):
self.grid()
# set up tabs
self.geometry( "%dx%d+%d+%d" % (1500, 900, 200, 50) )
nb = ttk.Notebook(self)
nb.pack(fill='both',expand='yes')
f1 = tk.Frame(bg='green')
f2 = tk.Frame(bg='blue')
f3 = tk.Frame(bg='red')
f1.grid()
f2.grid()
f3.grid()
nb.add(f1, text='General'.ljust(12,' '))
nb.add(f2, text='Plot'.ljust(12,' '))
nb.add(f3, text='Analysis'.ljust(12,' '))
button = tk.Button(f2,text='I AM A BUTTON!')
button.pack(side='left', anchor='nw', padx=3, pady=5)
# insert button and text box for specifying data location
path_button = tk.Button(f1,text='Browse',command=self.askdirectory).pack(side='left', anchor='nw', padx=10, pady=15)
self.path_entry = tk.StringVar()
self.entry = tk.Entry(f1,textvariable=self.path_entry)
self.entry.grid(column=12,row=8,columnspan=10)
self.entry.bind("<Return>", self.OnPressEnter)
self.path_entry.set(u"Sites directory path...")
def OnButtonClick(self):
print("You clicked the button !")
def OnPressEnter(self,event):
print("You pressed enter !")
def askdirectory(self):
"""Returns a selected directoryname."""
self.datapath = tkFileDialog.askdirectory()
self.path_entry.set(self.datapath)
if __name__ == "__main__":
app = TestGUI(None)
app.title(version)
app.mainloop()
My problem is centered around the addition of an entry box here:
self.path_entry = tk.StringVar()
self.entry = tk.Entry(f1,textvariable=self.path_entry)
self.entry.grid(column=12,row=8,columnspan=10)
self.entry.bind("<Return>", self.OnPressEnter)
self.path_entry.set(u"Sites directory path...")
If I run the code as-is, it just hangs (it also hangs if I use "f2"; I suspect it is getting caught in the infinite loop without actually doing anything). However, if I change the parent from "f1" to "f3" or it works (the entry box is now in frame 3 instead of frame 1, but it at least does not hang on me). There is another issue even when f3 is used: the entry box's width/position never change despite my changing of column/row/columnspan values.
Does anyone know why the code is hanging when I specify "f1" or "f2" and how to fix it?
Does anyone know why my entry box position/size is not changing?
You have put widgets in f1 and f2 using the pack geometry manager:
button = tk.Button(f2,text='I AM A BUTTON!')
button.pack(side='left', anchor='nw', padx=3, pady=5)
#and
path_button = tk.Button(f1,text='Browse',command=self.askdirectory).pack(side='left', anchor='nw', padx=10, pady=15)
Mixing geometry managers can lead to your program hanging, so using grid to put in the Entry does exactly that.
From effbot.org:
Warning: Never mix grid and pack in the same master window. Tkinter will happily spend the rest of your lifetime trying to negotiate a solution that both managers are happy with. Instead of waiting, kill the application, and take another look at your code. A common mistake is to use the wrong parent for some of the widgets.
The problem you describe of the Entry not changing position is because it is the only widget there, so the row(s) and column(s) in which the entry is are the only ones which do not have a width and height of 0. To make rows and columns without widgets take up space, use grid_rowconfigure(index, weight=x) where x is non-zero. An example is given in this answer.
Again from effbot.org:
weight=
A relative weight used to distribute additional space between rows. A row with the weight 2 will grow twice as fast as a row with weight 1. The default is 0, which means that the row will not grow at all.

Getting the text of label once button is clicked (Tkinter)

I am new to Python and Tkinter so I am trying to create a sample program to explore.
The program basically shows the names as a Label then 4 buttons will be put right next to the Label.
One of the buttons is "Delete" and what I want to do is, the button will get the name of the Label that is right next to that 'Delete" button.
The code is :
from Tkinter import *
class GUI():
def __init__(self):
self.namelist = ["Mark","Anna","Jason","Lenna",
"Leo","Zucharich","Robinson",
"AReallyLongNameThatMightExist"]
self.canvas = Canvas(width=1200,height=700)
self.canvas.pack(expand=YES,fill=BOTH)
def Friends(self):
frame = Frame(self.canvas)
frame.place(x=600,y=300)
#Frame for showing names of friends
row = 0
for x in self.namelist:
label = Label(frame,text="%s "%x)
chatButton = Button(frame,text="Chat")
delButton = Button(frame,text="Delete")
setcloseButton = Button(frame,text="Set Close")
setgroupButton = Button(frame,text="Set Group")
label.grid(row=row, column=0, sticky="W")
chatButton.grid(row=row, column=1)
delButton.grid(row=row, column=2)
setcloseButton.grid(row=row, column=3)
setgroupButton.grid(row=row, column=4)
row = row + 1
mainloop()
GUI = GUI()
GUI.Friends()
Example: If you run the code, then when you click "Delete" button next to "Mark", then the button will return "Mark".
Thanks!
Tk buttons have a command option to allow you to specify code to be run when the button is clicked. In this case you just want to pass the sibling widget name to your function. You can do this by capturing the widget name at creation time:
label = ...
delButton = Button(frame,text="Delete",
command=self.makeClosure(label))
...
def makeClosure(self, labelWidget):
return lambda: self.onClick(labelWidget)
def onClick(self, labelWidget):
print(labelWidget["text"])
In this example, when we create the delButton widget, the command is defined as a lambda that creates a closure including the label variable as it is defined at the time when this lambda is defined. Now when the delButton is clicked, this value will be passed to the onClick function which can use this to call methods on the widget at runtime.

How do I use Tkinter to create a ball everywhere my mouse clicks?

I am trying to create a program that creates a ball every time the mouse clicks, wherever it clicks. I am new to Tkinter and its syntax, but it seems like a pretty useful GUI.
Thanks
Here is the code. This code also tracks whenever a key is pressed, and it prints the syntax for that key.
from Tkinter import *
root = Tk()
def key(event):
pressedkey = repr(event.char)
print "pressed", pressedkey
def callback(event):
canvas.focus_set()
print "clicked at", event.x, event.y
ball = canvas.create_oval(event.x-15, event.y-15, event.x+15, event.y+15, outline='black', fill='gray40', tags=('ball'))
canvas = Canvas(root, width =1224,height=1024,bg='white')
canvas.bind("<Key>", key)
canvas.bind("<Button-1>", callback)
canvas.pack()
root.mainloop()
Here is the Tkinter documentation