I have created following window with tkinter and ttk, however I simply can't force the ttk.Entry fields to follow textvariable for its default value, they just keep appearing as blank. Strangely sometimes when I actually cause an exception to occur elsewhere in the window they suddenly work.
class PopUpEdit:
def __init__(self, idx):
self.idx = idx
self.data = get_single(self.idx)
self.have = tk.StringVar(root)
self.site = tk.StringVar(root)
self.title = tk.StringVar(root)
self.tags = tk.StringVar(root)
self._setup_vars()
self._setup_window()
def _setup_window(self):
window = tk.Toplevel(root)
window.geometry('400x600')
pprint.pprint(self.data)
ttk.Label(window, text='Site').grid(row=2, column=1, pady=10, padx=10)
ttk.Entry(window, textvariable=self.site, width=40).grid(row=2, column=2, sticky='e', pady=10, padx=10)
ttk.Label(window, text='Title').grid(row=3, column=1, pady=10, padx=10)
ttk.Entry(window, textvariable=self.title, width=40).grid(row=3, column=2, sticky='e', pady=10, padx=10)
ttk.Label(window, text=self.data['id']).grid(row=4, column=1, pady=10, padx=10)
def _setup_vars(self):
self.title.set(self.data['title'])
self.site.set(self.data['site'])
self.tags.set(self.data['tags'])
Related
Im working on a tkinter GUI that creates labels from a dictionary.
on of the labels is a "Fails" counter (theres another function that updates this value in the dictionary) id like if so when the "fails" is updated in the dictionary, it updates the fails value in the label.
heres a snippet if createing the labels from the dictionary. i cant figure out how to make it so the fails_label text is changed when the dictionary is updated
Thank you
row = 2
widgets = {}
for key in obj2create:
strEngNumber = obj2create[key][0]
strLayer = obj2create[key][1]
strFile = obj2create[key][2]
intFails = obj2create[key][3]
strJobKey = key
job_label = tk.Label(self.frame, text=key, anchor="w",
justify="center", wraplength=701,background=bg)
job_label.grid(row=row, column=0, pady=10, padx=10, ipady=3)
eng_label = tk.Label(self.frame, text=strEngNumber, anchor="w",
justify="center", wraplength=701,background=bg)
eng_label.grid(row=row, column=1, pady=10, padx=10, sticky="w")
layer_label = tk.Label(self.frame, text=strLayer, anchor="w",
justify="center", wraplength=701,background=bg)
layer_label.grid(row=row, column=2, pady=10, padx=10, sticky="w")
file_label = tk.Label(self.frame, text=strFile, anchor="w",
justify="center", wraplength=701,background=bg)
file_label.grid(row=row, column=3, pady=10, padx=10, sticky="w")
fails_label = tk.Label(self.frame, text=intFails, anchor="w",
justify="center", wraplength=701,background=bg)
fails_label.grid(row=row, column=4, pady=10, padx=10, sticky="w")
You can use trace_add() method like in the example below:
from tkinter import *
def update(var, index, mode):
label.configure(text=intFails.get())
def functionOnClick():
intFails.set(intFails.get() + 1)
w = Tk()
w.geometry('400x400')
intFails = IntVar(w, 0)
intFails.trace_add('write', update)
label = Label(w, textvariable=intFails, anchor="w", justify="center", font=('Arial', 22))
label.place(x=0, y=0)
btn = Button(w, text='Click', command=functionOnClick, font=('Arial', 22))
btn.place(x=0, y=80, width = 100, height = 80)
w.mainloop()
This method helps you to automatically detect, when variable was changed. Though it works only with special IntVar() and StringVar(), but I think it's only possible way to do this at least with this type of vars.
On the other hand, you can try to create a class with dictionary as your field and works with it by set property. This link may be useful for you.
I have packaged a group a widgets into a single widget as follows:
class RunOptions(tk.Frame):
def __init__(self, master=None):
super().__init__(master, bg='green')
self.label = tk.Label(self, text='Options:')
self.folder_button_label = tk.Label(self, text='Select a Folder', bg='white')
self.folder_button = tk.Button(self, text='Select Image Folder')
self.template_button = tk.Button(self, text='Select Template')
self.template_frame = ImageCanvas(self, height=64, width=64)
self.label.grid(row=0, sticky='W')
self.folder_button.grid(row=1, column=1, sticky='W')
self.folder_button_label.grid(row=1, column=0, sticky='W')
self.template_button.grid(row=2, column=1, sticky='W')
self.template_frame.grid(row=2, column=0, sticky='W')
and
class DetectionCanvas(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.xml_var = tk.IntVar()
self.detectframe = ImageCanvas(self, label='Detection:', height=175, width=175)
self.x_out = tk.Label(self, bg='white', text='X:', anchor='w')
self.y_out = tk.Label(self, bg='white', text='Y:', anchor='w')
self.w_out = tk.Label(self, bg='white', text='W:', anchor='w')
self.h_out = tk.Label(self, bg='white', text='H:', anchor='w')
self.xml_check = tk.Checkbutton(self, text=' Save XML File',variable=self.xml_var)
self.detectframe.grid(row=0, column=0, rowspan=4)
self.x_out.grid(row=0, column=1)
self.y_out.grid(row=1, column=1)
self.w_out.grid(row=2, column=1)
self.h_out.grid(row=3, column=1)
self.xml_check.grid(row=4, column=0, sticky='w')
def display_out(self, *args):
pass
both of these widgets are all arranged in a large empty canvas (purple) using grid, but that doesn't matter here because the issue is in the individual widgets themselves:
I want the buttons in the options to anchor to the left, filling in the gap between the label. For the detection widget I want the labels to anchor left towards the canvas. I've tried anchoring and using sticky but nothing in the second column seems to move.
I'm trying to slice a string and now my label wont show..
First I got a DoubleVar with a default float value. Then I'm trying to convert the updated value to a string and then slice it and set the value to the label, whitch result come from an entry and OptionsMenu.
The thing I'm tryng to achieve is to always get a value in the resultlabel1 with 3 decimals, that updates when the entry and OptionsMenu changes.
The code I'm speaking about:
self.resultlabel1 = DoubleVar()
self.resultlabel1.set(float(0.000))
self.label1 = Label(root, textvariable=str(self.resultlabel1)[:5])
self.label1.grid(row=2, column=3, columnspan=1, sticky='WE')
My total code is here:
from tkinter import *
from decimal import *
class App(Frame):
def __init__(self, root=None):
Frame.__init__(self, root)
self.materialPrice = {'Brick': 70, 'Rockwool': 50, 'Concrete': 20}
materialvariable1 = StringVar(self, root)
materialvariable1.set("Choose material")
materialvariable2 = StringVar(self, root)
materialvariable2.set("Choose materiale")
self.w1 = OptionMenu(root, materialvariable1, *self.materialPrice, command=self.displayPrice)
self.w1.grid(row=2, column=0, columnspan=1, sticky='WE')
self.w2 = OptionMenu(root, materialvariable2, *self.materialPrice, command=self.displayPrice2)
self.w2.grid(row=3, column=0, columnspan=1, sticky='WE')
# --------------------------------------------------------------------------------------------------------------------
self.var = DoubleVar()
self.var.set(Decimal("0.100"))
self.var2 = DoubleVar()
self.var2.set(Decimal("0.200"))
self.entry1 = Entry(root, textvariable=self.var)
self.entry1.grid(row=2, column=1)
self.entry2 = Entry(root, textvariable=self.var2)
self.entry2.grid(row=3, column=1)
# --------------------------------------------------------------------------------------------------------------------
self.priceVarLabel1 = DoubleVar()
self.priceVarLabel1.set(float(0.00))
self.priceVarLabel2 = DoubleVar()
self.priceVarLabel2.set(float(0.00))
self.priceVarValue1 = Label(root, textvariable=self.priceVarLabel1, relief='sunken')
self.priceVarValue1.grid(row=2, column=2, columnspan=1, sticky='WE')
self.priceVarValue2 = Label(root, textvariable=self.priceVarLabel2, relief='sunken')
self.priceVarValue2.grid(row=3, column=2, columnspan=1, sticky='WE')
self.resultlabel1 = DoubleVar()
self.resultlabel1.set(float(0.000))
self.resultlabel2 = DoubleVar()
self.resultlabel2.set(float(0.00))
# This is what I got so far!
self.label1 = Label(root, textvariable=str(self.resultlabel1)[:5])
self.label1.grid(row=2, column=3, columnspan=1, sticky='WE')
self.label2 = Label(root, textvariable=self.resultlabel2)
self.label2.grid(row=3, column=3, columnspan=1, sticky='WE')
# --------------------------------------------------------------------------------------------------------------------
self.resultSumNew = DoubleVar()
#self.resultSumNew.set(float(0.00))
self.resultSumNew.set(Decimal("0.000"))
self.labelSum = Label(root, textvariable=self.resultSumNew)
self.labelSum.grid(row=4, column=1, columnspan=1, sticky='WE')
def set_label(name, index, mode):
self.resultSumNew.set(self.var.get() + self.var2.get())
self.var.trace('w', set_label)
self.var2.trace('w', set_label)
# --------------------------------------------------------------------------------------------------------------------
def displayPrice(self, value):
self.resultlabel1.set(self.var.get() / self.materialPrice[value])
self.priceVarLabel1.set(self.materialPrice[value])
def displayPrice2(self, value):
self.resultlabel2.set(self.var2.get() / self.materialPrice[value])
self.priceVarLabel2.set(self.materialPrice[value])
root = Tk()
app = App(root)
root.title("help")
root.mainloop()
I was able to do it this way. Used StringVar for Label text and then sliced it accordingly
self.resultlabel1 = DoubleVar()
self.resultlabel1.set(float(0.000))
self.resultlabel2 = DoubleVar()
self.resultlabel2.set(float(0.00))
self.resultlabel1_str = StringVar()
self.resultlabel1_str.set(str(self.resultlabel1.get()))
self.label1 = Label(root, textvariable=self.resultlabel1_str)
self.label1.grid(row=2, column=3, columnspan=1, sticky='WE')
self.label2 = Label(root, textvariable=self.resultlabel2)
self.label2.grid(row=3, column=3, columnspan=1, sticky='WE')
And in your functions,
def displayPrice(self, value):
self.resultlabel1.set(self.var.get() / self.materialPrice[value])
self.priceVarLabel1.set(self.materialPrice[value])
self.resultlabel1_str.set(str(self.resultlabel1.get())[:5])
def displayPrice2(self, value):
self.resultlabel2.set(self.var2.get() / self.materialPrice[value])
self.priceVarLabel2.set(self.materialPrice[value])
Hope this helps.
I'm in need off assistance with some ZeroDivision.
In my example I got an optionMenu, that returns a value to a label, whitch is divided with an entry, then the result is shown in a new label in column 3.
I allways want to type an entry, that starts with an zero, like 0.250 etc. then this float is divided with the labels value from the optionMenu and then the result should be shown in a new label with digits.
It works fine with int, but thats not how it should work :) and now I'm a bit lost.
My following code looks like this and I would really appreciate a bit off help :) Thx in advance.
from tkinter import *
class App(Frame):
def __init__(self, root=None):
Frame.__init__(self, root)
self.materialPrice = {'Brick': 70, 'Rockwool': 50, 'Concrete': 20}
materialvariable1 = StringVar(self, root)
materialvariable1.set("Choose material")
materialvariable2 = StringVar(self, root)
materialvariable2.set("Choose materiale")
self.w1 = OptionMenu(root, materialvariable1, *self.materialPrice, command=self.displayPrice)
self.w1.grid(row=2, column=0, columnspan=1, sticky='WE')
self.w2 = OptionMenu(root, materialvariable2, *self.materialPrice, command=self.displayPrice2)
self.w2.grid(row=3, column=0, columnspan=1, sticky='WE')
self.var = IntVar()
self.var.set(float(0.00))
self.var2 = IntVar()
self.var2.set(float(0.00))
self.entry1 = Entry(root, textvariable=self.var)
self.entry1.grid(row=2, column=1)
self.entry2 = Entry(root, textvariable=self.var2)
self.entry2.grid(row=3, column=1)
self.priceVarLabel1 = IntVar()
self.priceVarLabel1.set(float(0.00))
self.priceVarLabel2 = IntVar()
self.priceVarLabel2.set(float(0.00))
self.priceVarValue1 = Label(root, textvariable=self.priceVarLabel1, relief='sunken')
self.priceVarValue1.grid(row=2, column=2, columnspan=1, sticky='WE')
self.priceVarValue2 = Label(root, textvariable=self.priceVarLabel2, relief='sunken')
self.priceVarValue2.grid(row=3, column=2, columnspan=1, sticky='WE')
self.resultlabel1 = IntVar()
self.resultlabel1.set(float(0.00))
self.resultlabel2 = IntVar()
self.resultlabel2.set(float(0.00))
self.label1 = Label(root, textvariable=self.resultlabel1)
self.label1.grid(row=2, column=3, columnspan=1, sticky='WE')
self.label2 = Label(root, textvariable=self.resultlabel2)
self.label2.grid(row=3, column=3, columnspan=1, sticky='WE')
def displayPrice(self, value):
self.resultlabel1.set(self.var.get() / self.materialPrice[value])
self.priceVarLabel1.set(self.materialPrice[value])
def displayPrice2(self, value):
self.resultlabel2.set(self.var2.get() / self.materialPrice[value])
self.priceVarLabel2.set(self.materialPrice[value])
root = Tk()
app = App(root)
root.title("help")
root.mainloop()
It works when I change it to a DoubleVar, like my example.
But is there any way, that I can manage the digit length on the result?
self.priceVarLabel1 = DoubleVar()
self.priceVarLabel1.set(float(0.00))
Having trouble setting the file path that is selected by the user and setting to variable. I am able to retrieve the path and set it to display in the entry box but I would like to capture that path and import it into another script. Maybe my logic is flawed here? What am I doing wrong?
import Tkinter
import tkFileDialog
from Tkinter import *
from tkFileDialog import *
class GUI:
def __init__(self, master):
self.master = master
master.title("XML Compare Tool")
master.geometry('700x300')
path1 = StringVar()
path2 = StringVar()
self.bb1 = Button(master, text="Browse", command=lambda: path1.set(askopenfilename()))
self.bb1.grid(row=0, column=0, padx=5, pady=5)
self.bb2 = Button(master, text="Browse", command=lambda: path2.set(askopenfilename()))
self.bb2.grid(row=1, column=0, padx=5, pady=5)
self.confirm = Button(master, text="Confirm", command='')
self.confirm.grid(row=3, column=1, padx=5, pady=5, sticky='')
self.entry1 = Entry(master, width=75, textvariable=path1)
self.entry1.grid(row=0, column=1, columnspan=2, sticky=W)
print path1.get()
self.entry2 = Entry(master, width=75, textvariable=path2)
self.entry2.grid(row=1, column=1, sticky=W)
self.t_label = Label(master, text="Script Output")
self.t_label.grid(row=4, column=1, columnspan=1, sticky='')
self.t_frame = Frame(master, bg="white", height=150, width=600)
self.t_frame.grid(row=5, column=1, columnspan=1, sticky='')
self.t_text = Text(self.t_frame)
root = Tk()
my_gui = GUI(root)
root.mainloop()
You do not need to use a textvariable, you can just use variable = entry1.get(). A Tkinter textvariable is not like a traditional python variable, it is just used for setting the text in an entry.