insert() method seems to fail in a subframe - python-3.x

I am writing a 'change' dialog for records in a database.
The 'enter data' dialog (terminErfassen) for the same data records works fine.
In order to reuse as much of the existing code I have made a class for Labels and the values.
The Entry and Text Widgets are repeated in each of the programs.
The dialog 'terminAendern' (change due date) starts with a small window asking for the record number. Pressing the 'lookup' (Daten einlesen) button opens the second window which has the same look as the 'enter data' dialog.
Problem: Although the code is identically written, it works for the Entry-Fields in the main frame, and it fails for the Entry fields in the subframes.
However I am not sure the Frames are the culprits - it seems just the single item which is not identical in the structure.
Here is the code. Rows 0 to 5 get filled with data from the database, the Radiobuttons also work, just the Entries in the subframe have this problem. Find below also an image of the screen.
class TerminAendern(te2.DatenFenster):
"Termine können geändert werden. Erweiterung von terminErfassen"
def __init__(self, el):
"Übernimmt das Fenster aus dem Erfassungsdialog"
super().__init__()
self.ROOT.title("Termin ändern")
# Datensatz-Nummer
self.num_wrt = el["nummer"]
# die Werte aus der Datenbank in das Fenster setzen
#--------- row 0 -----------
#self.art_wrt = tk.StringVar() # Operation zB backup, apt-update, extrahieren
self.art_wrt.set(el["art"])
self.ART_EING = tk.Entry(self.FRMEINGAB, textvariable=self.art_wrt, bg='white')
self.ART_EING.grid(column=1, row=0)
self.ART_EING.insert(0, el["art"])
#--------- row 1 -----------
#self.gertwrt = tk.StringVar() # Rechnername oder Gerät (BoschNyon)
self.gertwrt.set(el["geraet"])
self.GERTEING = tk.Entry(self.FRMEINGAB, textvariable=self.gertwrt, bg='white')
self.GERTEING.insert(90, el["geraet"])
self.GERTEING.grid(column=1, row=1)
#--------- row 2 -----------
#self.brchwrt = tk.StringVar() # Partition/Gegenstand/Aktion/'': TB2, Karten, apt-update
self.brchwrt.set(el["bereich"])
self.BRCHEING = tk.Entry(self.FRMEINGAB, textvariable=self.brchwrt, bg='white')
self.BRCHEING.insert(0, el["bereich"])
self.BRCHEING.grid(column=1, row=2)
#--------- row 3 -----------
#self.bescwrt = tk.StringVar() # Kurztext
self.bescwrt.set(el["kurztext"])
self.BESCEING = tk.Label(self.FRMEINGAB, textvariable=self.bescwrt, bg='lightblue',
text=el["kurztext"],anchor=tk.W, relief=tk.RAISED)
self.BESCEING.grid(column=1, row=3)
#--------- row 4 -----------
#self.haufwrt = tk.IntVar() # Häufigkeit
self.haufwrt.set(el["haeufigkeit"])
self.HAUFEING = tk.Entry(self.FRMEINGAB, textvariable=self.haufwrt, bg='white')
self.HAUFEING.insert(0, el["haeufigkeit"])
self.HAUFEING.grid(column=1, row=4)
#--------- row 5 -----------
#self.ist_wrt = tk.StringVar() # Datum: Letzte Durchführung
dbdatum = el["wann"]
dbm = dbdatum.find("-", 6)
dbd = dbdatum[dbm+1:] + "." + str(dbdatum[5:dbm]) + "." + str(dbdatum[:4])
self.IST_EING = tk.Entry(self.FRMEINGAB, textvariable=self.ist_wrt, bg='white')
self.IST_EING.insert(0, dbd)
self.IST_EING.grid(column=1, row=5)
#--------- row 6 Frame 'Prüfung' -----------
for val, txt in self.pruefwerte: # (int,str)
if el["pruefen"] == txt:
self.prufwrt.set(val)
break
self.PRUFEING = {} # leeres Dict
for val, txt in self.pruefwerte: # (int,str)
self.PRUFEING[val] = tk.Radiobutton(self.FRMPRUEFG, text=txt, padx=5, pady=2,
variable=self.prufwrt, value=val)
self.PRUFEING[val].grid(column=0, row=val+1, sticky=tk.W)
if val == self.prufwrt.get():
self.PRUFEING[val].select()
#---- Prüfdatei ----
if "testen" in el:
self.testwrt.set(el["testen"])
else:
self.testwrt.set("")
print("testwrt = " + self.testwrt.get())
self.TESTEING = tk.Entry(self.FRMPRUEFG, textvariable=self.testwrt, bg='white')
#self.TESTEING.delete(0, tk.END)
self.TESTEING.insert(0, self.testwrt)
self.TESTEING.grid(column=4, row=2)
#--------- row 7 Frame 'Machen' -----------
if el["machen"] == "manuell":
self.machwrt.set(0)
self.skrpwrt.set("")
else:
self.machwrt.set(1)
self.skrpwrt.set(el["machen"])
self.MACHEING = {} # leeres Dict
for val, txt in self.machwerte:
self.MACHEING[val] = tk.Radiobutton(self.FRMMACHEN, text=txt, padx=5, pady=3,
variable=self.machwrt, value=val)
self.MACHEING[val].grid(column=1, row=val+1, sticky=tk.W)
if val == self.machwrt.get():
self.MACHEING[val].select()
#---- Arbeitsskript ----
self.SKRPEING = tk.Entry(self.FRMMACHEN, textvariable=self.skrpwrt, bg='white')
self.SKRPEING.insert(0, self.skrpwrt)
self.SKRPEING.grid(column=4, row=2)
#--------- row 8 -----------
self.ANLTeing = tk.Text(self.FRMEINGAB, height=3, width=80, bg='white')
self.ANLTeing.insert('1.0', el["anleitung"])
self.ANLTeing.grid(column=1, row=8, columnspan=3)
#------------ GRID = Alle aktivieren -----------
self.FRMPRUEFG.grid(column=0, row=6, columnspan=5, sticky=tk.W)
self.FRMMACHEN.grid(column=0, row=7, columnspan=5, sticky=tk.W)
self.FRMEINGAB.grid(row=0)
#------------
self.PROGENDEBUTTON = tk.Button(self.FRMSCHALT, text='Quit', bg="red",
command=self.ROOT.quit)\
.grid(row=0, column=4, sticky=tk.E, padx=20, pady=4)
self.FRMSCHALT.grid(row=1)
class DatenAuswahl:
"Fenster zur Auswahl des Datensatzes"
def __init__(self):
self.fenster = tk.Tk()
self.fenster.title('Datensatz auswählen')
self.MYFRAME = tk.Frame(self.fenster, borderwidth=5, relief=tk.RIDGE, pady=4)
self.satznr = tk.IntVar()
self.SATZNR_TXT = tk.Label(self.MYFRAME, text="Nummer des Termins ", padx=5, pady=9)\
.grid(column=0, row=1, sticky=tk.W)
self.SATZEIN = tk.Entry(self.MYFRAME, textvariable=self.satznr, bg='white')\
.grid(column=1,row=1)
self.DATENBUTTON = tk.Button(self.MYFRAME, text="Daten einlesen", bg="lightblue",
command=self.DatenLesen) #self.satznr ??
self.DATENBUTTON.grid(column=0, row=3, padx=20, pady=20)
self.MYFRAME.grid(row=0)
def DatenLesen(self):
"""Versucht, den Termin-Satz mit Nummer 'satznr' aus der Datenbank zu lesen,
danach wird das Fenster zur Datenkorrektur geöffnet."""
el = createTerminListe.terminAuslesen(int(self.satznr.get()))
# Ausgabe der Werte auf demn Bildschirm
for k in el.keys():
print(k + " = " + str(el[k]))
ausgabe = TerminAendern(el)
myprog = DatenAuswahl()
tk.mainloop()
The definition of the frames in the base class is simple:
class DatenFenster:
'Klasse zur Bearbeitung von Terminen'
def __init__ (self):
locale.setlocale(locale.LC_ALL, 'de_DE.utf8')
self.ROOT = tk.Tk()
self.ROOT.title("Termin erfassen")
self.FRMEINGAB = tk.Frame(self.ROOT, borderwidth=5, relief=tk.RIDGE, pady=4)
self.FRMPRUEFG = tk.Frame(self.FRMEINGAB, borderwidth=2, relief=tk.RIDGE)
self.FRMMACHEN = tk.Frame(self.FRMEINGAB, borderwidth=2, relief=tk.RIDGE)
self.FRMSCHALT = tk.Frame(self.ROOT, borderwidth=4, relief=tk.RAISED, pady=4, padx=6,
bg="orange")
--etc.---
'terminAendern' window
The Entry at 'Prüfdatei (Pfad)' is filled with a default instead of the supplied value from the database.
I have no idea where to look further (apart from the tk source, which I am not sure I can master).
I'd be happy if someone could tell me what I am missing.

I found the source of my problem myself.
First, a StringVar() created in one Tk() is not visible in another Tk():
see here.
Of course, I detected this problem in my code.
I have now 2 ways of resolution:
(1) to make my 'change'-dialog and my 'enter' dialog two separate programs, i.e. not reusing code. I did not intend this, but it may lead me to a running solution quicker.
(2) to use Toplevel(). This would allow me to keep the original program dependencies and to avoid duplicating code, but I did not find a lot of explanations on multi-window programming so far. Anyway, my problem is explained even if not solved.

Related

how to delete a specific item in the list after a button is clicked in tkinter python

Below is a small code where if you click add button a pop-up will appear where you write desired number. The number in the bottom represents the sum of all numbers you entered.
What I am trying to achieve is to update the sum_lbl and index_no as I delete any of the labels.
Code:
from tkinter import *
root = Tk()
root.geometry('400x400')
add_room_area_var= StringVar(None)
area_lst = []
index_no = 0
def destroy(widget):
widget.destroy()
def add_():
add_room_area = Toplevel(root)
add_room_area.title('Add Room area')
add_room_area.wm_minsize(200, 50)
add_room_area.resizable(False, False)
add_room_area.transient(root)
add_r_area_frame = LabelFrame(add_room_area, text=' Room area ', labelanchor=N)
add_r_area_frame.config(padx=3, pady=3)
add_r_area_frame.pack(fill=X, padx=10, pady=10)
add_r_area_entry = Entry(add_r_area_frame, textvariable=add_room_area_var)
add_r_area_entry.pack(fill=X)
add_r_area_entry.focus_set()
while True:
def ok_():
global index_no
name = add_room_area_var.get()
index_no += 1
entry_frame = Frame(root)
index_lbl = Label(entry_frame, text=index_no)
add_room_lbl = Label(entry_frame, text=name, width=12, bg='gray30', fg='white', pady=5)
close_button = Button(entry_frame, text='X', command=lambda:destroy(entry_frame))
entry_frame.pack(anchor=N, padx=1)
index_lbl.pack(side=LEFT, padx=3)
add_room_lbl.pack(fill=X, side=LEFT)
close_button.pack(side=RIGHT)
area_lst.append(int(name))
add_room_area.destroy()
area_sum = sum(area_lst)
sum_lbl.config(text=area_sum)
break
ok_button = Button(add_room_area, text='Ok', command=ok_)
ok_button.pack()
btn = Button(root, text='Add', command=add_)
btn.pack()
sum_lbl = Label(root, font=25)
sum_lbl.pack(side=BOTTOM, pady=15)
root.mainloop()
Output:
After deleting the 3rd and 4th label the output is:
I would suggest to change area_lst to dictionary using the frame as the key and the two labels as the value for each row.
Then update destroy() to use area_lst to update the total and indexes:
from tkinter import *
root = Tk()
root.geometry('400x400')
add_room_area_var= StringVar(None)
area_lst = {} # dictionary to hold labels of each row using frame as the key
def destroy(frame):
frame.destroy()
del area_lst[frame]
update_total()
# update index of remaining rows
for idx, (lbl, _) in enumerate(area_lst.values(), 1):
lbl['text'] = idx
# function to update the total label
def update_total():
area_sum = sum(int(room['text']) for _, room in area_lst.values())
sum_lbl.config(text=area_sum)
def add_():
add_room_area = Toplevel(root)
add_room_area.title('Add Room area')
add_room_area.wm_minsize(200, 50)
add_room_area.resizable(False, False)
add_room_area.transient(root)
add_r_area_frame = LabelFrame(add_room_area, text=' Room area ', labelanchor=N)
add_r_area_frame.config(padx=3, pady=3)
add_r_area_frame.pack(fill=X, padx=10, pady=10)
add_r_area_entry = Entry(add_r_area_frame, textvariable=add_room_area_var)
add_r_area_entry.pack(fill=X)
add_r_area_entry.focus_set()
def ok_():
name = add_room_area_var.get()
entry_frame = Frame(root)
index_lbl = Label(entry_frame, text=len(area_lst)+1)
add_room_lbl = Label(entry_frame, text=name, width=12, bg='gray30', fg='white', pady=5)
close_button = Button(entry_frame, text='X', command=lambda:destroy(entry_frame))
entry_frame.pack(anchor=N, padx=1)
index_lbl.pack(side=LEFT, padx=3)
add_room_lbl.pack(fill=X, side=LEFT)
close_button.pack(side=RIGHT)
# store current row to area_lst
area_lst[entry_frame] = (index_lbl, add_room_lbl)
add_room_area.destroy()
update_total()
ok_button = Button(add_room_area, text='Ok', command=ok_)
ok_button.pack()
btn = Button(root, text='Add', command=add_)
btn.pack()
sum_lbl = Label(root, font=25)
sum_lbl.pack(side=BOTTOM, pady=15)
root.mainloop()
You can allow buttons to call multiple commands, so for your 'close_button' button, I added two more commands: remove the name from 'area_lst' and update the 'sum_lbl' text with the new sum for 'area_lst'
Like this:
from tkinter import *
root = Tk()
root.geometry('400x400')
add_room_area_var= StringVar(None)
area_lst = []
index_no = 0
def destroy(widget):
widget.destroy()
def add_():
add_room_area = Toplevel(root)
add_room_area.title('Add Room area')
add_room_area.wm_minsize(200, 50)
add_room_area.resizable(False, False)
add_room_area.transient(root)
add_r_area_frame = LabelFrame(add_room_area, text=' Room area ', labelanchor=N)
add_r_area_frame.config(padx=3, pady=3)
add_r_area_frame.pack(fill=X, padx=10, pady=10)
add_r_area_entry = Entry(add_r_area_frame, textvariable=add_room_area_var)
add_r_area_entry.pack(fill=X)
add_r_area_entry.focus_set()
while True:
def ok_():
global index_no
name = add_room_area_var.get()
index_no += 1
entry_frame = Frame(root)
index_lbl = Label(entry_frame, text=index_no)
add_room_lbl = Label(entry_frame, text=name, width=12, bg='gray30', fg='white', pady=5)
close_button = Button(entry_frame, text='X', command=lambda:[destroy(entry_frame), area_lst.remove(int(name)), sum_lbl.config(text=sum(area_lst))])
entry_frame.pack(anchor=N, padx=1)
index_lbl.pack(side=LEFT, padx=3)
add_room_lbl.pack(fill=X, side=LEFT)
close_button.pack(side=RIGHT)
area_lst.append(int(name))
add_room_area.destroy()
area_sum = sum(area_lst)
sum_lbl.config(text=area_sum)
break
ok_button = Button(add_room_area, text='Ok', command=ok_)
ok_button.pack()
btn = Button(root, text='Add', command=add_)
btn.pack()
sum_lbl = Label(root, font=25)
sum_lbl.pack(side=BOTTOM, pady=15)
root.mainloop()

Is there good way to save text input from tkinter Text widget

I was building, a receipt using Tkinter in Text widgets, it is well-formatted in GUI
but when I save that it becomes like this
There is so much disorder in the text file
How can I get a text formatted like one in GUI, in text file ???
here is my code.
from tkinter import *
from tkinter.filedialog import asksaveasfilename
from tkinter.messagebox import askyesno
# ------------
app = Tk()
# =================== frames ========================
frame1 = Frame(app)
frame1.pack(side=TOP)
# ----
title_label = Label(frame1, text="Facture", font=("courier", 40, 'bold'))
title_label.pack()
# ----
frame2 = Frame(app, bd=5)
frame2.pack(side=TOP)
# ----
frame3 = Frame(app)
frame3.pack(side=TOP)
# ============================================
# ======--- text field -----======
text_input = Text(frame2, width=47, height=25, bg="aliceblue", fg='black', font=("arial", 14, 'bold'))
text_input.pack()
# ============ in text field ===============
text_input.insert(END, f'--------------------------------- Facture ---------------------------------\n')
text_input.insert(END, f"\nQty " + f"Product" + f" PU" + f" PV/TVAC" + f'\n')
text_input.insert(END, f"\n1 " + f"FANTA CITRON" + f" 2500" + f" 2500")
text_input.insert(END, f"\n1 " + f"BUFFET PER HEAD" + f" 10000" + f" 10000")
text_input.insert(END, f"\n1 " + f"MUKEKE GRILLE OIGNONS" + f"16000" + f" 16000" + f'\n')
text_input.insert(END, f"\nTOTAL" + f" 28500")
# --------- functions ---------
def save():
filepath = asksaveasfilename(
defaultextension = "csv",
filetypes = [("Text Files", "*.csv"), ("All Files", "*.*")])
if not filepath:
return
with open(filepath, 'w') as output_file:
text = text_input.get('1.0', END)
output_file.write(text)
def printR():
pass
def delete():
text_input.delete('1.0', END)
def exit():
iExit = askyesno("Attention", "You are on your way to quit\nAre you sure you want quit")
if iExit > 0:
app.destroy()
# ----------------------------------
# ============---------------===============
# =====--------- Buttons -----------========
save_button = Button(frame3, text="Save", height=3, width=10, command=save)
save_button.grid(row=0, column=0, padx=2)
# ----------------
print_button = Button(frame3, text="Print", height=3, width=10, command=printR)
print_button.grid(row=0, column=1, padx=2)
# ----------------
delete_button = Button(frame3, text="Delete", height=3, width=10, command=delete)
delete_button.grid(row=0, column=2, padx=2)
# ----------------
quit_button = Button(frame3, text="Exit", height=3, width=10, command=exit)
quit_button.grid(row=0, column=3, padx=2)
# ============================================
app.mainloop()
.........................
.........................
.........................
.........................
I think that the problem is that the "Text" is formatted well only using the Tkfixedfont font.
I made some changes, replaced the format type, deleted the bold and size and used the format() function to align the text.
from tkinter import *
from tkinter.filedialog import asksaveasfilename
from tkinter.messagebox import askyesno
# ------------
app = Tk()
# =================== frames ========================
frame1 = Frame(app)
frame1.pack(side=TOP)
# ----
title_label = Label(frame1, text="Facture", font=("courier", 40, 'bold'))
title_label.pack()
# ----
frame2 = Frame(app, bd=5)
frame2.pack(side=TOP)
# ----
frame3 = Frame(app)
frame3.pack(side=TOP)
# ============================================
# ======--- text field -----======
text_input = Text(frame2,bg="aliceblue", fg='black', font=('TkFixedFont'))
text_input.pack(expand = True)
# ============ in text field ===============
header = "{0} {1} {2}\n".format("-"*35,"Facture", "-"*35)
text_input.insert(END, header)
fields = "{0:10}{1:40}{2:20}{3:8}\n".format("Qty", "Product", "PU", "PV/TVAC")
text_input.insert(END, fields)
rs = (("1", "FANTA CITRON", "2500", "2500"),
("1", "BUFFET PER HEAD", "10000", "10000"),
("1", "MUKEKE GRILLE OIGNONS", "16000", "16000"),)
for i in rs:
fields = "{0:10}{1:40}{2:20}{3:10}\n".format(i[0], i[1], i[2], i[3])
text_input.insert(END, fields)
footer = "{0:70}{1}".format("TOTAL","28500")
text_input.insert(END, footer)
# --------- functions ---------
def save():
filepath = asksaveasfilename(
defaultextension = "csv",
filetypes = [("Text Files", "*.csv"), ("All Files", "*.*")])
if not filepath:
return
with open(filepath, 'w') as output_file:
text = text_input.get('1.0', END)
output_file.write(text)
def printR():
pass
def delete():
text_input.delete('1.0', END)
def exit():
iExit = askyesno("Attention", "You are on your way to quit\nAre you sure you want quit")
if iExit > 0:
app.destroy()
# ----------------------------------
# ============---------------===============
# =====--------- Buttons -----------========
save_button = Button(frame3, text="Save", height=3, width=10, command=save)
save_button.grid(row=0, column=0, padx=2)
# ----------------
print_button = Button(frame3, text="Print", height=3, width=10, command=printR)
print_button.grid(row=0, column=1, padx=2)
# ----------------
delete_button = Button(frame3, text="Delete", height=3, width=10, command=delete)
delete_button.grid(row=0, column=2, padx=2)
# ----------------
quit_button = Button(frame3, text="Exit", height=3, width=10, command=exit)
quit_button.grid(row=0, column=3, padx=2)
# ============================================
app.mainloop()

Print the difference result between two counters in Python

I have two counters whose results are displayed in a small part of the GUI for reference, but the important data I need is the result of IN minus OUT. For example, if I have 113 IN and 86 OUT, I am going to display those two data but I need to display also the result, 27 (113-86=27).
Screenshot of the app
Given these two counters:
def counter_label_IN(label):
def count():
s.sendall(b'gcounters\x00')
L_IN = next(iter(s.recv(1024)))
print(L_IN)
label_IN.config(text=str(L_IN))
label_IN.after(500, count)
count()
def counter_label_OUT(label):
def count():
s.sendall(b'gcounters\x00')
L_OUT = next(iter(s.recv(1024)))
print(L_OUT)
label_OUT.config(text=str(L_OUT))
label_OUT.after(500, count)
count()
How can I have another timer keeping refreshing the difference between the two?
Also, if the difference is a negative number, I need to display only 0.
EDIT after #j_4321 kind reply.
Thank you so much for the reply. I am a little lost and I guess it is one of those time the reply is right in front of my eyes but it is so bright that I can't see it... The code written gives no error, but the counts displayed in all the labels are zeroes. This is a simplified code, but still you can see the 0:
EDIT 2 after #j_4321 kind reply.
As suggested, I added:
counter_label_IN()
counter_label_OUT()
To the code, which I am pasting here for your consideration. It now gives me this error:
PS C:\Users\lorenzo.amati> & C:/Users/lorenzo.amati/AppData/Local/Programs/Python/Python38-32/python.exe "c:/Users/lorenzo.amati/Desktop/Software PCN/PCN-local-getdata-prova.py"
Traceback (most recent call last):
File "c:/Users/lorenzo.amati/Desktop/Software PCN/PCN-local-getdata-prova.py", line 55, in <module>
counter_label_IN()
File "c:/Users/lorenzo.amati/Desktop/Software PCN/PCN-local-getdata-prova.py", line 38, in counter_label_IN
count()
File "c:/Users/lorenzo.amati/Desktop/Software PCN/PCN-local-getdata-prova.py", line 27, in count
s.sendall(b'gcounters\x00')
OSError: [WinError 10038] An operation was attempted on something that is not a socket
Here is the code:
import socket
import tkinter as tk
import tkinter.ttk as ttk
# Main settings
IP_address = ('172.16.0.103')
root = tk.Tk()
root.title("People Counter")
root.configure(bg="#006bb3")
font1 = "-family {Source sans pro} -size 36 -weight bold"
font2 = "-family {Source sans pro} -size 150 -weight bold"
# use IntVar as counters
counter_IN = tk.IntVar(root)
counter_OUT = tk.IntVar(root)
counter_DIFF = tk.IntVar(root)
# get the sensor data
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((IP_address,5400))
def counter_label_IN():
def count():
s.sendall(b'gcounters\x00')
L_IN = next(iter(s.recv(1024)))
print(L_IN)
counter_IN.set(L_IN) # update counter IntVar instead of label
# update DIFF counter:
diff = L_IN - counter_OUT.get()
if diff < 0:
diff = 0
counter_DIFF.set(diff)
label_IN.after(500, count)
count()
def counter_label_OUT():
def count():
s.sendall(b'gcounters\x00')
L_OUT = next(iter(s.recv(1024)))
print(L_OUT)
counter_OUT.set(L_OUT) # update counter IntVar instead of label
diff = counter_IN.get() - L_OUT
if diff < 0:
diff = 0
counter_DIFF.set(diff)
label_OUT.after(500, count)
count()
s.close()
counter_label_IN()
counter_label_OUT()
# In/Out Informations display on top
FrameTOP = tk.Frame(root, bg="#006bb3", borderwidth="0")
FrameTOP.grid(row=0, column=0, columnspan=4, sticky='nsew')
Label_RTC_IN = tk.Label(FrameTOP, anchor='w',bg="#006bb3", fg='white',justify='left', text='Realtime count of people IN:')
Label_RTC_OUT = tk.Label(FrameTOP, anchor='w',bg="#006bb3", fg='white',justify='left', text='Realtime count of people OUT:')
label_IN = tk.Label(FrameTOP, textvariable=counter_IN, anchor='w',bg="white",fg="black", justify='left', relief='sunken', borderwidth="2")
label_OUT = tk.Label(FrameTOP, textvariable=counter_OUT, anchor='w',bg='white', fg='black', justify='left', relief='sunken', borderwidth="2")
Label_RTC_IN.grid(row=0, column=0, padx=10, pady=10)
label_IN.grid(row=0, column=1, padx=10, pady=10)
Label_RTC_OUT.grid(row=0, column=2, padx=10, pady=10)
label_OUT.grid(row=0, column=3, padx=10, pady=10)
# Frame in which to put the differential data of people inside
FrameCENTRAL = tk.Frame(root, bg="#006bb3",borderwidth="0")
FrameCENTRAL.grid(row=1, column=0, pady=50, columnspan=4,) #sticky='nsew')
TitleCentral = tk.Label(FrameCENTRAL,anchor='w', bg="#006bb3", fg='white', font=font1, text='''People Inside''')
TitleCentral.grid(row=0, column=0, padx=10, pady=10)
label_DIFF = tk.Label(FrameCENTRAL, textvariable=counter_DIFF, font=font2, bg="#006bb3", fg='white', anchor='center')
label_DIFF.grid(row=1, column=0, padx=10, pady=10)
# IP Informations
FrameBOTTOM = tk.Frame(root, bg="#006bb3", borderwidth="0")
FrameBOTTOM.grid(row=2, column=0, columnspan=4, sticky='nsew')
Label_IP_ADDRESS = tk.Label(FrameBOTTOM,anchor='w',bg="#006bb3",fg='white',text='''People counter sensor locally connected to local IP address:''')
Label_IP = tk.Label(FrameBOTTOM,anchor='w',bg="#006bb3",fg='white',text=(IP_address))
Label_IP_ADDRESS.grid(row=0, column=0, padx=10, pady=10)
Label_IP.grid(row=0, column=1, padx=10, pady=10)
# Closing button
close = tk.Button(FrameBOTTOM, bg="#006bb3",fg='white',text='Stop and close', width=16, command=root.destroy)
close.grid(row=0, column=3, padx=10, sticky='e')
root.mainloop()
Screenshot of the app after the modification, showing all 0
You can use IntVar as the IN, OUT and DIFF = IN - OUT counters and use the textvariable option of the Label to automatically update the text when updating the counters. In the counter_label_...() functions, the IntVar value will be updated instead of updating the label's text.
import tkinter as tk
root = tk.Tk()
# use IntVar as counters
counter_IN = tk.IntVar(root)
counter_OUT = tk.IntVar(root)
counter_DIFF = tk.IntVar(root)
# use textvariable to keep the labels updated
label_IN = tk.Label(root, textvariable=counter_IN)
label_OUT = tk.Label(root, textvariable=counter_OUT)
label_DIFF = tk.Label(root, textvariable=counter_DIFF)
# database polling
def counter_label_IN():
def count():
s.sendall(b'gcounters\x00')
L_IN = next(iter(s.recv(1024)))
print(L_IN)
counter_IN.set(L_IN) # update counter IntVar instead of label
# update DIFF counter:
diff = L_IN - counter_OUT.get()
if diff < 0:
diff = 0
counter_DIFF.set(diff)
label_IN.after(500, count)
count()
def counter_label_OUT():
def count():
s.sendall(b'gcounters\x00')
L_OUT = next(iter(s.recv(1024)))
print(L_OUT)
counter_OUT.set(L_OUT) # update counter IntVar instead of label
diff = counter_IN.get() - L_OUT
if diff < 0:
diff = 0
counter_DIFF.set(diff)
label_OUT.after(500, count)
count()
# start monitoring the database
counter_label_IN()
counter_label_OUT()

Return value from text entry to some other class

I am trying to get return values from tkinter window where i am entering text values,I want those text values to be returned so that I can capture those and send as input to other class methods.
I am able to print those captured values but not able to return them. I am very new to python
from tkinter import *
class gui_cls:
def __init__(self,*args):
self.master=args[0]
self.delete = StringVar()
self.insert = StringVar()
self.var1 = IntVar()
self.var3 = IntVar()
def vergui(self):
Delete = self.delete.get()
insertversions = self.insert.get()
prog = self.var1.get()
print(Delete)
print(insertversions)
if prog:
print("levels")
else:
pass
label_0 = Label(self.master, text="Adaptive", width=20, font=("bold", 20))
label_0.place(x=40, y=53)
label_1 = Label(self.master, text="Delete Versions", width=20, font=("bold", 10))
label_1.place(x=30, y=130)
entry_1 = Entry(root, textvar=self.delete)
entry_1.place(x=200, y=130)
label_2 = Label(self.master, text="Insert Versions", width=20, font=("bold", 10))
label_2.place(x=30, y=180)
entry_2 = Entry(self.master, textvar=self.insert)
entry_2.place(x=200, y=180)
label_3 = Label(self.master, text="Reload", width=20, font=("bold", 10))
label_3.place(x=30, y=230)
var2 = IntVar()
Checkbutton(self.master, text="Levels", padx=5, variable=self.var1).place(x=190, y=230)
Checkbutton(self.master, text="Accounts", padx=20, variable=var2).place(x=250, y=230)
label_4 = Label(self.master, text="Note: Please seperate versions by comma(,)", fg='red', font=("bold", 13)).place(x=30, y=280)
Button(self.master, text='Finish', width=20, bg='brown', fg='white', command=self.vergui).place(x=200, y=350)
root = Tk()
root.geometry('400x400')
root.title("Adaptive")
gui_cls(root).vergui()
root.mainloop()
Current you created an instance of the class on the fly. You can first define a variable for the instance of the class, and then call the methods separately:
#gui_cls(root).vergui()
gui = gui_cls(root)
gui.vergui()
Then you can access the class attributes anytime.
print (gui.delete.get())
print (gui.var1.get())
...

Tkinter background color issue at scrollbar

I am working on a tkinter script which has a vertical and horizontal scrollbar.
A portion of the window below the vertical scrollbar is not picking up the background color I'm applying.
I have tried the following color options still the small portion is not picking up.
Image:
Sample window snapshot
Full Code:
from tkinter.tix import *
from tkinter import *
import collections
root = Tk()
root.configure(background='steel blue')
# Global variables
fname = ''
# Variables for setting the height and width of widget
# Variables to set Height
actualRootHeight = 300
rootHScale = 25
rootHOffset = 100
canvasHeight = 300
root2CanvasHMargin =65
# Variables to set Width
rootWScale = 10
rootWOffset = 200
canvasWidth = 300
root2CanvasWMargin = 20
inpWidth = 0
# Lists to save configs
inpParamList = collections.OrderedDict()
paramListRef = collections.OrderedDict()
updatedParamList = collections.OrderedDict()
entryList = []
labels = []
# All widget coding is done here
class guiList(Frame):
global root
# Constructor - Use as a control structure
def __init__(self,parent):
Frame.__init__(self,parent)
self.parent = parent
self.readParams()
self.setGeometry()
self.initUI()
self.controlUI()
def onFrameConfigure(self, event, Canvas1):
# Reset the scroll region to encompass the inner frame
Canvas1.configure(scrollregion=Canvas1.bbox("all"), background='steel blue')
# All widget edition is done here
def initUI(self):
global paramListRef
titleStr = sys.argv[1]
self.parent.title(titleStr)
self.grid(row=0, column=0)
inpConfigs = inpParamList.items()
# Add a canvas and call Frame as it's child widget
# Scrollbar can be added to Canvas
Canvas1 = Canvas(self, width=canvasWidth, height=canvasHeight, borderwidth=0, bg="light steel blue")
vsb = Scrollbar(self, orient="vertical", command=Canvas1.yview, bg="light steel blue", troughcolor="steel blue", highlightcolor="light steel blue", activebackground="light steel blue", highlightbackground="light steel blue")
Canvas1.configure(yscrollcommand=vsb.set)
vsb.grid(column=2, sticky='NS')
hsb = Scrollbar(self, orient="horizontal", command=Canvas1.xview, bg="light steel blue", troughcolor="steel blue")
Canvas1.configure(xscrollcommand=hsb.set)
hsb.grid(column=0, sticky='EW')
Canvas1.grid(row=0, column=0, sticky='NWES')
# Create new Frame for input configs
Frame1 = Frame(Canvas1, width=canvasWidth, height=canvasHeight, bg="light steel blue")
Canvas1.create_window((1,1),window=Frame1, anchor="nw", tags="Frame1")
Frame1.bind("<Configure>", lambda event, arg=Canvas1: self.onFrameConfigure(event, arg))
# Loop through the input configs
i = 0
# Add label and combobox in loop
for k,v in inpConfigs:
# Label widgets
lbl1 = Label(Frame1, text=k, bg="light steel blue", font=("Helvetica", 12, "bold"), fg="steel blue")
lbl1.grid(row = i, column = 0, padx=10, pady=5, sticky='W')
labels.append(lbl1)
# Combo-box widget for configurations
tkvar = StringVar(Frame1)
tkvar.set(v[0])
entry1 = OptionMenu(Frame1, tkvar, *v)
entry1.configure(width=20, anchor=W, bg="steel blue", fg="white", font=("Helvetica", 11, "bold"))
entry1.grid(row = i, column=1, padx=10, pady=5, sticky='E')
#entry1.grid_columnconfigure(2, weight=2)
paramListRef[k] = tkvar
i += 1
# Read the updated configs after the button click
def readUpdatedParams(self):
global updatedParamList
for k,v in paramListRef.items():
updatedParamList[k] = v.get()
root.destroy()
self.writeBack()
# Seperate Frame for buttons
# Upon clicking read updted params
def controlUI(self):
Frame2 = Frame(self, bg="steel blue")
Frame2.grid(row=2, column = 0, sticky="EW")
b = Button(Frame2, text="OK", command=self.readUpdatedParams, bg="light steel blue", fg="steel blue", font=("Helvetica", 11, "bold"))
#b.grid(row=1, column=1, pady=10)
b.pack(fill="none", expand=True, pady = 10)
# Read the file and create a key, value pair for configs
# Lines in file is split with space as delimiter
# First column is the config name and rest are all possible value
def readParams(self):
global inpParamList
global inpWidth
f = open(fname)
for line in f:
val = {}
val = line.split()
key = val.pop(0)
# Get the max width of key to adjust widget width
inpWidth = len(key) if (len(key) > inpWidth) else inpWidth
inpParamList[key] = val
# Geometry ( X-width x Y-width + X-position + Y-position)
# Based on the number of elements in the config list
# the height of the widget is set (Max is 75% of screen size)
def setGeometry(self):
global actualRootHeight
global canvasWidth
global canvasHeight
listLen = len(inpParamList)
rootWinwidth = int(inpWidth *rootWScale) + rootWOffset
rootWinheight = (listLen * rootHScale ) + rootHOffset
screenWidth = self.winfo_screenwidth()
screenHeight = int(self.winfo_screenheight() * 0.75)
if rootWinheight < screenHeight :
actualRootHeight = rootWinheight
else :
actualRootHeight = screenHeight
canvasWidth = rootWinwidth - root2CanvasWMargin
canvasHeight = actualRootHeight - root2CanvasHMargin
rootWinresolution = str(rootWinwidth)+'x'+str(actualRootHeight)+'+'+'0'+'+'+'0'
root.geometry(rootWinresolution)
# Sub routine to write back the config file.
def writeBack(self):
fr = open("bt_top.param.config",'w')
for k,v in updatedParamList.items():
print(k,v)
fr.write(k)
fr.write(" ")
fr.write(v)
fr.write("\n")
fr.close()
# Main Function
# Define Window geometry and other top level stuff here
# Do not go into widget coding here
def main():
global fname
# Get File name from command line argument
fname = sys.argv[2]
app = guiList(root)
root.mainloop()
# The __name__ variable decides what to run
# Below lines make this file run stand-alone
if __name__ == '__main__':
Any suggestions are welcome. Thanks
-Vinay
The piece of black is the background of self, your guiList class. Add a line self.config(bg="steel blue") to its __init__() function (or to initUI() I suppose) to fix it.

Resources