Can't write full text in an Entry - tkinter - python

I'm working on a GUI software with Tkinter which basically print a general plane of the product after pushing the "Crear" button, as you can see at the following images:
GUI Interface
After pushing "Crear" Button
As you may have appreciated, once you give the full information at the entries and push the "Crear" button, a dynamic table (made with labels and entries in a for cycle) appear with the dimensions of the modules seen at the "Esquema" frame. The problem I have is that, when I edit the information at the dynamic table, I have an immediate change on the graph (which is possible thanks to the trace method) without letting me finish the number I'm already writing; I mean: I can't write the full number at the entries on the dynamic table before it make the changes on the graph. So, my question is: which function or command can I apply to make the program stop and reactivate after I finish writing the full number at the entries on the table?
Any help will be highly appreciated,
PS: I have already tried the "time.stop" and "after" functions. The first one crashed the program, which is unacceptable, and the second one increased the waiting time before I could continue writing numbers at the table. The full code of the program is really extensive, but here I share a runnable code:
Code
from tkinter import *
from tkinter import filedialog as fd
from tkinter import messagebox as ms
from tkinter import ttk
from io import open
import tkinter as tk
from pathlib import Path
import PIL
from PIL import Image, ImageTk
import glob
import sys
import numpy as np
import os
import os, os.path
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import time
#Made by:
#Juan David Argüello Plata
#----------------------------------------------CLASSES AND FUNCTIONS-----------------------------------------------------
class Interface():
def __init__(self, inter, w=860,h=700, titulo = "Example", titulo_principal = "EXAMPLE"):
inter.title(titulo)
inter.resizable(False, False)
#Dimensions of the screen
ws = inter.winfo_screenwidth()
hs = inter.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
#Position of the interface
inter.geometry('%dx%d+%d+%d' % (w, h, x, y))
titulo = Label(inter, text = titulo_principal, font=(fuente,24, "bold italic"))
titulo.pack()
self.inter = inter
#---Frames, labels and general data---
self.Principal_frames()
self.subframes()
self.Data()
#---Actions to execute---
Action(self)
def Principal_frames(self):
self.Frame_Table = Frame(self.inter)
self.Frame_Table.config(width = "400", height = "600", bd = 2, relief = "groove")
self.Frame_Table.place(x=10, y=50)
titulo = Label(self.Frame_Table, text = "Data", font=(fuente,20, "bold italic"))
titulo.place(x=180, y=5)
self.Frame_graph = Frame(self.inter)
self.Frame_graph.config(width = "400", height = "600", bd = 2, relief = "groove")
self.Frame_graph.place(x=450, y=50)
titulo = Label(self.Frame_graph, text = "Graph", font=(fuente,20, "bold italic"))
titulo.place(x=150, y=5)
def subframes(self):
self.subframe_Data = Frame(self.Frame_Table)
self.subframe_Data.config(width = "300", height = "200", bd = 2, relief = "groove")
self.subframe_Data.place(x=80, y=50)
self.subframe_graph = Frame(self.Frame_graph)
self.subframe_graph.config(width = "395", height = "400", bd = 2, relief = "flat")
self.subframe_graph.place(x=0, y=50)
def Data(self):
Length = Label(self.subframe_Data, text = "Length", font = Font)
Length.grid(row=0, column = 0, sticky=W, padx=3)
self.Length=Entry(self.subframe_Data, width=8)
self.Length.grid(row=0,column=1, sticky=W, padx=3)
self.Sub_Length=Entry(self.subframe_Data, width=8)
self.Sub_Length.grid(row=0,column=2, sticky=W, padx=3)
Width = Label(self.subframe_Data, text = "Width", font = Font)
Width.grid(row=1, column = 0, sticky=W, padx=3)
self.Width=Entry(self.subframe_Data, width=8)
self.Width.grid(row=1,column=1, sticky=W, padx=3)
self.Sub_Width=Entry(self.subframe_Data, width=8)
self.Sub_Width.grid(row=1,column=2, sticky=W, padx=3)
class Action(Interface):
def __init__(self, inter):
self.Interface = inter
self.modification = 0
Create = Button(self.Interface.subframe_Data, text="Create", font = Font, command = self.Table)
Create.grid(row=1,column=3)
def Table(self):
self.Table = Frame(self.Interface.Frame_Table)
self.Table.config(width = "150", height = "400", bd=2, relief="groove")
self.Table.place(x=80, y=150)
#Dimensions of the labels and entries of the table
Length = 176
Width = 200
#Reading of Data
self.Data = np.zeros(4)
self.Data[0] = float(self.Interface.Length.get())
self.Data[1] = float(self.Interface.Sub_Length.get())
self.Data[2] = float(self.Interface.Width.get())
self.Data[3] = float(self.Interface.Sub_Width.get())
#---Dynamic table ---
if self.Data[1] > self.Data[3]:
self.Max = self.Data[1]
else:
self.Max = self.Data[3]
#-Variables-
label = "label"
Entry_length = "length"
Entry_width = "width"
Numbers_label = [""]*(int(self.Max)+1)
self.width_data = [""]*(int(self.Max)+1)
self.length_data=[""]*(int(self.Max)+1)
self.First_Time = 0 #Counter that depends of the size of the table (help the program to recognize if it's the first time the "Create" button is pressed)
self.Modules = np.zeros((int(self.Max),2)) #Matrix which contains the table info
#--Scorllbar--
self.canvas_table = Canvas(self.Table)
self.canvas_table.pack(side="left", fill="both", expand = True)
self.canvas_table.config(width=str(Width), height=str(Length))
self.Frame_table = Frame(self.canvas_table)
self.Frame_table.config(width=str(Width), height=str(Length), relief="flat")
self.canvas_table.create_window(0,0,window= self.Frame_table, anchor = 'nw')
self.yscroll = Scrollbar(self.Table, orient = "vertical", command = self.canvas_table.yview)
self.yscroll.pack(side='right', fill='y')
self.canvas_table['yscrollcommand'] = self.yscroll.set
self.Frame_table.bind("<Configure>", self.AuxscrollFunction)
self.yscroll.grid_forget()
Number = Label(self.Frame_table, text="", width=4, font = Font, bd = 2, relief="groove")
Number.grid(row=0,column=0,sticky=W)
L = Label(self.Frame_table, text="L", width=8, font = Font, bd = 2, relief="groove")
L.grid(row=0,column=1,sticky=W)
Wid = Label(self.Frame_table, text="W", width=8, font = Font, bd = 2, relief="groove")
Wid.grid(row=0,column=2,sticky=W)
#Subdivisions (defect values)
Wth = self.Data[2]/self.Data[3]
l = self.Data[0]/self.Data[1]
self.var_length = []
self.var_width = []
for i in range(int(self.Max)+1):
if i != 0:
Numbers_label[i] = label + str(i)
Numbers_label[i] = Label(self.Frame_table, text=str(i), width=4, font = Font, bd = 2, relief="groove")
Numbers_label[i].grid(row=i,column=0,sticky=W)
if i <= self.Data[1]:
text = str(l)
else:
text = "0.0"
var_length = StringVar()
self.var_length.append(var_length)
self.length_data[i] = Entry_length + str(i)
self.length_data[i] = Entry(self.Frame_table, width=9, font = Font, bd = 2, relief="groove", textvariable = self.var_length[i-1])
self.var1 = self.length_data[i]
self.var_length[i-1].trace("w", lambda name, index, mode, envio=self: Action.callback(envio))
self.length_data[i].grid(row=i,column=1,sticky=W)
self.length_data[i].insert(0, text)
if i <= self.Data[3]:
text = str(Wth)
else:
text = "0.0"
var_width = StringVar()
self.var_width.append(var_width)
self.width_data[i] = Entry_width + str(i)
self.width_data[i] = Entry(self.Frame_table, width=9, font = Font, bd = 2, relief="groove", textvariable = self.var_width[i-1])
self.var1 = self.width_data[i]
self.var_width[i-1].trace("w", lambda name, index, mode, envio=self: Action.callback(envio))
self.width_data[i].grid(row=i,column=2,sticky=W)
self.width_data[i].insert(0, text)
self.yscroll.pack(side='right', fill = 'y')
def AuxscrollFunction(self,event):
self.canvas_table.configure(scrollregion=self.canvas_table.bbox("all"))
def callback(self, *args):
self.First_Time = self.First_Time+1
if self.First_Time >= 2*int(self.Max) and self.modification == 0:
try:
for i in range(int(self.Max)+1):
if i != 0:
self.Modules[i-1][0] = float(self.length_data[i].get())
self.Modules[i-1][1] = float(self.width_data[i].get())
self.Data[0] = 0
self.Data[2] = 0
for i in range(int(self.Max)):
self.Data[0] = self.Data[0]+self.Modules[i][0]
self.Data[2] = self.Data[2]+self.Modules[i][1]
self.Interface.Length.delete(0, 'end')
self.Interface.Width.delete(0, 'end')
self.Interface.Length.insert(0, str(self.Data[0]))
self.Interface.Width.insert(0, str(self.Data[2]))
#self.var1.focus()
self.Graph()
except ValueError:
pass
def Graph(self):
#---Area---
f=Figure(figsize=(3,3), dpi=100)
a=f.add_subplot(111)
type_line = 'r--' #Línea de borde de área
a.plot([0,self.Data[2]], [0,0], type_line)
a.plot([0,self.Data[2]], [self.Data[0],self.Data[0]], type_line)
a.plot([0,0], [0,self.Data[0]], type_line)
a.plot([self.Data[2],self.Data[2]], [0,self.Data[0]], type_line)
canvas = FigureCanvasTkAgg(f, self.Interface.subframe_graph)
canvas.draw()
canvas.get_tk_widget().place(x=0,y=0)
#--------------------------------------------------------INTERFACE-----------------------------------------------
#---Beginning of the interface---
root = Tk()
#Font
fuente = "TkFixedFont"
Font = (fuente, 10)
Interface(root)
root.mainloop()

Related

could not convert string to float: '' error in python(Tkinter)

I made a program that converts 1 currency to another(in this case only won to dollars). However, when I try to click on US radio button, it says "could not convert string to float: '' ". So, what's the problem here? I tried to run it without an additional window, and it worked perfectly fine, but when I open a converter window in a new window, it does not work. What is the problem and how do I make it so the converter would work fine when you open it in a new window?
import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showerror
from tkinter import *
root = tk.Tk()
root.geometry('5000x5000')
def openconverter():
root = tk.Tk()
root.title('Change Converter')
root.geometry('400x210')
def won_to_dollar(f):
US = 0.00079
return f*US
frame = ttk.Frame(root)
options = {'padx': 5, 'pady': 5}
won = tk.StringVar()
won_entry = ttk.Entry(frame, textvariable=won)
won_entry.grid(column=1, row=0, **options)
def convert_button_clicked(won_to_dollar):
try:
f = float(won.get())
c = won_to_dollar(f)
result = f'{f} won = {c:.2f}'
result_label.config(text=result)
except ValueError as error:
showerror(title='Error', message=error)
result_label = ttk.Label(frame)
result_label.grid(row=1, columnspan=3, **options)
frame.grid(padx=10, pady=10)
r = IntVar()
Radiobutton(root, text="US", variable = r, value = 1, command = lambda : convert_button_clicked(won_to_dollar)).place(x = 220, y = 20)
myLabel = Label(root, text = r.get())
myLabel.grid
root.mainloop()
Converted = Button(root, text="converter",font = ("Helvetica", 15), width=50, height=50, compound="c", activeforeground = "green", command = lambda: openconverter())
Converted.place(x=10, y=185)
root.mainloop()
Try this and click convert and enter value and select US.
from tkinter import ttk
from tkinter.messagebox import showerror
from tkinter import *
root = Tk()
root.title('Change Converter')
root.geometry('400x810')
def openconverter():
def won_to_dollar(f):
US = 0.00079
return f*US
frame = Frame(root)
options = {'padx': 5, 'pady': 5}
won = StringVar()
won_entry = Entry(frame, textvariable=won)
won_entry.grid(column=1, row=0, **options)
def convert_button_clicked(won_to_dollar):
try:
f = won.get()
c = won_to_dollar(float(f))
result = f'{f} won = {c}'
result_label.config(text=result)
except ValueError as error:
showerror(title='Error', message=error)
result_label = Label(frame)
result_label.grid(row=1, columnspan=3, **options)
frame.grid(padx=10, pady=10)
r = IntVar()
Radiobutton(root, text="US", variable = r,
value = 1,
command = lambda : convert_button_clicked(won_to_dollar)).place(x = 220, y = 20)
myLabel = Label(root, text = r.get())
myLabel.grid
Converted = Button(root, text="converter",
font = ("Helvetica", 15), width=50, height=50, compound="c",
activeforeground = "green", command = lambda: openconverter())
Converted.place(x=10, y=5)
root.mainloop()

How do I proceed with the rest of the function to keep updating my message box in tkinter?

I am trying to do a message box to warns the user in my UI that they will be moved to the homepage after 10 seconds, codes are as following:
from tkinter import *
import warnings
import random
import time
import sqlite3
from tkinter import simpledialog
from tkinter import messagebox
from tkcalendar import *
from tkinter import ttk
import math
from PIL import Image, ImageTk
import winsound
##-------------Frames setup--------------------------
class VendingApp(Tk):
def __init__(self):
Tk.__init__(self)
self._frame = None
self.switch_frame(Home)
def switch_frame(self, frame_class):
#Destroys current frame and replaces it with a new one.
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.pack()
####-----------------------Home page---------------------------
class Home(Frame):
def __init__(self, master):
Frame.__init__(self, master)
##-----------------------fuctions-----------------------------------
def clicked(a):
if (a.x <=1920) and (a.y<=1080):
master.switch_frame(Store)
print ("1")
else:
None
None
##----------------setup------------------------------------------
self._images = list()
img_banner = Image.open("pic/banner.jpg")
img_banner = img_banner.resize((400,100), Image.ANTIALIAS)
banner = ImageTk.PhotoImage(img_banner)
self._images.append(banner)
##---------------------Top frame Home------------------------------------
topFrame = Frame(self,width = 1920, height = 1080)
topFrame.pack()
canvasM = Canvas(topFrame,height=1080, width=1920)
canvasM['highlightthickness'] = 0
canvasM.pack()
body = canvasM.create_rectangle(0, 0,1920,1080, fill = 'gray95')
mylabel = canvasM.create_text((960, 390),font=("Purisa", 40), text="Touch anywhere to continue")
canvasM.tag_bind(body,"<Button>",clicked)
canvasM.tag_bind(mylabel,"<Button>",clicked)
#-------------------------Store page--------------------------------------------------------------
class Store(Frame):
def __init__(self, master):
Frame.__init__(self, master)
def timeset():
global time
time = 15
def active(event):
global time
time = 15
print (time)
def timeout():
global time
if time >= 10:
time -= 1
master.after(1000, timeout)
elif time <= 10 and time > 0:
askuser()
time -= 1
master.after(1000, timeout)
elif time <= 0:
master.switch_frame(Home)
print(time)
def askuser():
ask = messagebox.showinfo('Are you there?','Returning to home page in ' + (str(time)) + ' seconds. \n please touch the screen to continue using the app')
self._images = list()
img_banner = Image.open("pic/banner.jpg")
img_banner = img_banner.resize((400, 100), Image.ANTIALIAS)
banner = ImageTk.PhotoImage(img_banner)
self._images.append(banner)
##---------------------pictures and filters Store------------------------------------
PicFrame = Frame(self, width=400, height=100)
PicFrame.grid(row = 0, column = 0)
PicFrame.grid_propagate(False)
canvas_for_banner = Canvas(PicFrame, height=100, width=400 ) # banner image
canvas_for_banner.pack(anchor = N)
canvas_for_banner['highlightthickness'] = 0
canvas_for_banner.grid_propagate(False)
canvas_for_banner.create_image(0, 0, anchor=NW, image=banner)
##---------------------------------Midd store-------------------
FilterFrame =Frame(self, width=400, height=930, relief = RAISED, bd =1)
FilterFrame.grid(row = 1, column = 0)
FilterFrame.pack_propagate(0)
Ava_title = Label(FilterFrame, text = "Availability", font = ('Helvetica', 20, 'bold'))
Ava_title.pack(pady = (100,0))
self.stock_yes = IntVar()
self.stock_no = IntVar()
check_ava = Checkbutton(FilterFrame, text = 'Avaliable', variable = self.stock_yes, font = 20, command = None)
check_ava.pack( anchor = 'w', padx = 30, pady =10)
check_unava = Checkbutton(FilterFrame, text = 'Unavaliable', font = 20, variable = self.stock_no, command = None)
check_unava.pack(anchor = 'w', padx = 30, pady = 10)
gend_title = Label(FilterFrame, text = "Gender", font = ('Helvetica', 20, 'bold'))
gend_title.pack(pady = (30,0))
self.boi = IntVar()
self.girl = IntVar()
check_boi = Checkbutton(FilterFrame, text = 'Male', font = 20, variable = self.boi)
check_boi.pack( anchor = 'w', padx = 30, pady = 10)
cehck_girl = Checkbutton(FilterFrame, text = 'Female', font = 20, variable = self.girl)
cehck_girl.pack(anchor = 'w', padx = 30, pady =10)
Class_title = Label(FilterFrame, text = "Uniform class", font = ('Helvetica', 20, 'bold'))
Class_title.pack(pady = (30,0))
self.formal = IntVar()
self.sport = IntVar()
check_formal = Checkbutton(FilterFrame, text = 'Formal', font = 20, variable = self.formal)
check_formal.pack( anchor = 'w', padx = 30, pady =10)
check_sport = Checkbutton(FilterFrame, text = 'Sport', font = 20, variable = self.sport)
check_sport.pack(anchor = 'w', padx = 30, pady =10)
type_title = Label(FilterFrame, text = "Type", font = ('Helvetica', 20, 'bold'))
type_title.pack(pady = (30,0))
self.shirts = IntVar()
self.pants = IntVar()
self.misc = IntVar()
check_shirts = Checkbutton(FilterFrame, text = 'Shirts', font = 20, variable = self.shirts)
check_shirts.pack( anchor = 'w', padx = 30, pady =10)
check_pants = Checkbutton(FilterFrame, text = 'Pants', font = 20, variable = self.pants)
check_pants.pack(anchor = 'w', padx = 30, pady =10)
check_misc = Checkbutton(FilterFrame, text = 'Misc', font = 20, variable = self.misc)
check_misc.pack(anchor = 'w', padx = 30, pady =10)
##------------------------\\\\\\\\\\\\\\\\\\\\\\---------------------------------------------
MidFrame = Frame(self,width = 1520, height = 1030, relief = SUNKEN, bd = 2)
MidFrame.grid(row = 0, column = 1, rowspan = 2)
MidFrame.grid_propagate(False)
store_canvas = Canvas(MidFrame, width = 1520, height = 1030)
store_canvas.pack()
store_canvas.pack_propagate(0)
frames = []
frame_order = []
num = 1
for x in range(4):
frames.append([])
for y in range(4):
frames[x].append(0)
for x in range(4):
for y in range(4):
frames[x][y] = Frame(store_canvas, width=1520 / 4, height=1030 / 4, bd = 2, relief = SOLID)
frames[x][y].grid(row=y, column=x)
frames[x][y].pack_propagate(False)
frame_order.append(frames[x][y])
for frame in frame_order:
Label(frame, text=num, anchor='nw').pack( side = 'left')
num += 1
##------------------------\\\\\\\\\\\\\\\\\\\\\\---------------------------------------------
BottomFrame = Frame(self,width = 1920, height = 50, bd = 2, relief = RAISED)
BottomFrame.grid(row = 2, column =0, columnspan = 2)
BottomFrame.pack_propagate(False)
help_btn = Button(BottomFrame, width = 5, height = 3, text = '?', image = None)
help_btn.pack(side = 'right')
master.bind("<Button>",active)
timeset()
timeout()
#----------------------------------------------------------------------------------------
if __name__ == "__main__":
root = VendingApp()
#Renames the TITLE of the window
root.title("Vending machine")
root.geometry("1920x1080")
root.attributes('-fullscreen', True)
root.resizable(False, False)
root.mainloop()
The problem is that the whole program 'freezes' every time the msg box pop up and unless the user confirms 'ok' then the function will pick up where it left off. Is there any way to keep the function going, hence the number in the msg box will update according to the time remaining? Am I approaching this problem the wrong way? Is there another module for this all along and I am just using the wrong module for the task? Please go easy on me, I am still learning. All responses all much appreciated.
messagebox will pause the further execution until it receives an input. To prevent this you can try the following
Use threading
from tkinter import *
from tkinter import messagebox
from threading import Thread
def msgbox():
def _display():
messagebox.showinfo('Info','Self distruction after 2 seconds')
Thread(target=_display).start()
root.after(2000,root.destroy)
root=Tk()
button=Button(root,text='Run',command=msgbox)
button.pack()
root.mainloop()
Create your own info box using Toplevel (the below example will create a replica (sort of) of standard windows info box)
from tkinter import *
import tkinter.ttk as ttk
class InfoBox(Toplevel):
def __init__(self,title,message,parent=None):
Toplevel.__init__(self,parent)
self.bell()
self.transient(self.master)
self.title(title)
self.config(bg='white')
top_frame=Frame(self,bd=0,bg=self['bg'])
top_frame.pack(side='top',fill='x',pady=20)
bottom_frame=Frame(self,bd=0)
bottom_frame.pack(side='bottom',fill='x')
self.info_icon=Canvas(top_frame,width=36,height=36
,bg=self['bg'],bd=0,highlightthickness=0)
self.info_icon.create_oval(0,0,30,30,fill='#0077be',outline='#0077be')
self.info_icon.create_text(15,16,text='i',font=('',18),fill='white')
self.info_icon.pack(side='left',padx=(20,0),anchor='center')
self.label=Label(top_frame,text=message,bg=self['bg'])
self.label.pack(padx=(1,20),pady=5,anchor='center')
self.ok_button=ttk.Button(bottom_frame,text='OK',
state='active',command=self.destroy)
self.ok_button.pack(anchor='e',padx=15,pady=10)
self.update()
center_x=self.winfo_screenwidth()//2-self.winfo_width()//2
center_y=self.winfo_screenheight()//2-self.winfo_height()//2
self.geometry(f'+{center_x}+{center_y}')
def msgbox():
InfoBox('Info','Self distruction after 2 seconds')
root.after(2000,root.destroy)
root=Tk()
button=Button(root,text='Run',command=msgbox)
button.pack()
root.mainloop()
UPDATE
Stacking is automatically prevented
from tkinter import *
import tkinter.ttk as ttk
class InfoBox(Toplevel):
def __init__(self):
self.exists=False
def call(self,title,message,parent=None):
if self.exists:
self._destroy()
Toplevel.__init__(self,parent)
self.bell()
self.transient(self.master)
self.title(title)
self.config(bg='white')
top_frame=Frame(self,bd=0,bg=self['bg'])
top_frame.pack(side='top',fill='x',pady=20)
bottom_frame=Frame(self,bd=0)
bottom_frame.pack(side='bottom',fill='x')
self.info_icon=Canvas(top_frame,width=36,height=36
,bg=self['bg'],bd=0,highlightthickness=0)
self.info_icon.create_oval(0,0,30,30,fill='#0077be',outline='#0077be')
self.info_icon.create_text(15,16,text='i',font=('',18),fill='white')
self.info_icon.pack(side='left',padx=(20,0),anchor='center')
self.label=Label(top_frame,text=message,bg=self['bg'])
self.label.pack(padx=(1,20),pady=5,anchor='center')
self.ok_button=ttk.Button(bottom_frame,text='OK',
state='active',command=self._destroy)
self.ok_button.pack(anchor='e',padx=15,pady=10)
self.update()
center_x=self.winfo_screenwidth()//2-self.winfo_width()//2
center_y=self.winfo_screenheight()//2-self.winfo_height()//2
self.geometry(f'+{center_x}+{center_y}')
self.protocol('WM_DELETE_WINDOW',self._destroy)
self.exists=True
def _destroy(self):
self.destroy()
self.exists=False
root=Tk()
infobox=InfoBox()
button=Button(root,text='Hello',command=lambda:infobox.call('Info','Hello'))
button.pack()
button1=Button(root,text='World',command=lambda:infobox.call('Info','World'))
button1.pack()
root.mainloop()

RE: TKinter Table Row Deletion (PYTHON)

(If anyone has seen my previous question, I found a way to save the row indexes and use them in the delete function :3)
Is there a way to stop/delete a running function/table on a button click? I am making a simple customer registration program which saves data from text fields (cID, custName, custEmail, and custBday) and deletes a selected row. My problem is that whenever I delete a row, the last row somehow leaves/lags behind creating this duplicate whenever a row is deleted. Any suggestions or is there something I've done wrong or I've missed?
My Code:
from tkinter import *
from tkinter import messagebox
import tkinter as tk
at = False
dotcom = False
list = [['ID', 'NAME', 'EMAIL', 'BIRTHDATE']]
recentIndex = []
ID = 1
storedIndex = 0
def callback(event):
custid.config(state=NORMAL)
custid.delete('1.0', END)
custid.insert(1.0, list[event.widget._values][0])
custid.config(state=DISABLED)
cName.set(list[event.widget._values][1])
cEmail.set(list[event.widget._values][2])
birthdate.set(list[event.widget._values][3])
indexPosition = event.widget._values
recentIndex.append(indexPosition)
print(recentIndex)
def createTable():
for i in range(len(list)):
for j in range(len(list[0])):
mgrid = tk.Entry(window, width = 10, bg= 'yellow')
mgrid.insert(tk.END, list[i][j])
mgrid._values= i
mgrid.grid (row = i + 5,column = j + 5)
mgrid.bind("<Button-1>", callback)
def delete():
try:
list.pop(recentIndex[-1])
if recentIndex[-1] > 0 or NONE:
msgbox("Data Delete", "Record")
createTable()
else:
msgbox("No Data Selected", "record")
return
except:
msgbox("No Data Selected", "record")
def save ():
custid.config(state= NORMAL)
initialValue = int(custid.get('1.0', END))
custid.delete('1.0', END)
list.append([ID, custName.get(), custEmail.get(), custBday.get()])
custid.insert(1.0, initialValue + 1)
custid.config(state=DISABLED)
createTable()
msgbox("Saved", "Record")
ID = ID + 1
def msgbox (msg, titlebar):
messagebox.showinfo(title = titlebar, message=msg)
def products():
window = Tk()
window.title("Products Form")
window.geometry("550x400")
window.configure(bg="orange")
window = Tk()
window.title("Sample Window")
window.geometry("550x400")
window.configure(bg="orange")
menubar = Menu(window)
filemenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="Products", command=products)
filemenu.add_command(label="Orders")
filemenu.add_separator()
filemenu.add_command(label="Close", command = window.quit)
window.config(menu=menubar)
labelTitle = Label(window, text="Customer Registration System", width=30, height=1, bg="yellow", anchor= "center")
labelTitle.config(font=("Courier", 10))
labelTitle.grid(column=2, row=1)
labelID = Label(window, text="Customer ID", width = 20, height = 1, bg = "yellow")
labelID.grid(column=1, row=2)
cID = StringVar()
custid = Text(window, width=15, height=1)
custid.grid(column=2, row=2)
custid.insert(1.0, "1")
custid.config(state = DISABLED)
labelNameCheck = Label(window, text="Last Name, First Name", width = 20, height = 1, bg = "yellow")
labelNameCheck.grid(column=3, row=3)
labelName = Label(window, text="Customer Name", width = 20, height = 1, bg = "yellow")
labelName.grid(column=1, row=3)
cName = StringVar()
custName = Entry(window, textvariable = cName)
custName.grid(column=2, row=3)
labelEmail = Label(window, text="Customer Email", width = 20, height = 1, bg = "yellow")
labelEmail.grid(column=1, row=4)
cEmail = StringVar()
custEmail = Entry(window, textvariable = cEmail)
custEmail.grid(column=2, row=4)
custEmail.bind("<KeyRelease>", keyup)
labelEmail = Label(window, text="[a-z]#[a-z].com", width = 20, height = 1, bg = "yellow")
labelEmail.grid(column=3, row=4)
labelBday = Label(window, text="Customer Birthdate", width = 20, height = 1, bg = "yellow")
labelBday.grid(column=1, row=5)
birthdate= StringVar()
custBday = Entry(window, textvariable = birthdate)
custBday.grid(column=2, row=5)
custBday.bind("<KeyRelease>", keyupBdate)
birthdateCheck = Label(window, text="mm/dd/yyyy", width = 20, height = 1, bg = "yellow")
birthdateCheck.grid(column=3, row=5)
savebtn = Button(text = "Save", command = save)
savebtn.grid(column=1)
deletebtn = Button(text = "Delete", command = delete)
deletebtn.grid(column=1)
window.mainloop()
You need to delete current displayed records before showing updated records inside createTable(). Also better create a frame for showing the records, so that it is more easier to clear the displayed records:
def createTable():
# clear current displayed records
for w in tableFrame.winfo_children():
w.destroy()
# populate records
for i in range(len(list)):
for j in range(len(list[0])):
mgrid = tk.Entry(tableFrame, width = 10, bg= 'yellow') # use tableFrame as parent
mgrid.insert(tk.END, list[i][j])
mgrid._values= i
mgrid.grid (row = i,column = j)
mgrid.bind("<Button-1>", callback)
...
# frame for showing records
tableFrame = Frame(window)
tableFrame.grid(row=5, column=5)
...

Cannot make a label wider

I have this reproducible code, and I cannot understand why when I set the width value to 100 in the self.display_tcm_18 variable, it still does not increase its width. This self.display_tcm_18 lies within the self.xf Frame, which I set to a width value of 300 (wide enough to host a Label widget of 100). I don't know what I am missing in the Logic of building this GUI with tkinter. Does anyone could give me some hint?
import Tkinter
from Tkinter import *
import tkFileDialog
from tkFileDialog import askopenfilename
from tkFileDialog import askdirectory
class Window(Frame):
def __init__(self, master = None):
self.master = master
path = "logo.gif"
self.image = Tkinter.PhotoImage(file=path)
self.f = Frame(master, width=300, height =70)
self.sf = Frame(master, width=300, height=70)
self.xf = Frame(self.f,width = 300, relief=GROOVE, borderwidth = 2)
self.file_name_18 = ''
self.var = IntVar()
def browse_button():
filename = askopenfilename(filetypes = (("GEOTIFF Files", "*.tif"),))
self.file_name = filename
self.display.config(text = filename)
print(self.file_name)
self.Logo = Label(self.master, image = self.image).pack(side=TOP, padx=5)
self.open_tcm_button = Button(self.xf, text = "Open..", command = browse_button).pack(side=LEFT, padx = 5, pady = 10)
self.display_tcm_18 = Label(self.xf, width = 100, bg = "white", textvariable = self.file_name_18, relief = SUNKEN, anchor = W)
self.display_tcm_18.pack(side=LEFT)
self.tcm18_label = Label(self.f, text = "Tree Cover Mask 2018 ").place(relx=0.06, rely=0.125,anchor=W)
self.xf.place(relx=0.01, rely=0.125, anchor=NW)
self.f.pack(side=TOP)
root = Tk()
root.geometry("600x400")
app = Window(root)
root.mainloop()

Create another window in tkinter class

I have made "sticky notes" in python but how do I make the same open in another window when I press the new File (+ on the title bar) button? I thought of creating an object within the class but I don't think that's possible. Should I import and run similar file? Please suggest a method to do so. Suggestions to improve the code are welcomed.
Here's the code
from tkinter import *
import tkinter.scrolledtext as tkst
from tkinter import messagebox
from tkinter import font
class StickyNotes:
xclick = 0
yclick = 0
def __init__(self,master):
def get_pos(event):
self.xclick = event.x
self.yclick = event.y
def move_window(event):
master.geometry('+{0}+{1}'.format(event.x_root-self.xclick, event.y_root-self.yclick))
def another_window(event):
pass
def quit_window(event):
self.closebutton.config(relief = 'flat', bd = 0)
if(messagebox.askyesno('Delete Note?','Are you sure you want to delete this note?')):
master.destroy()
return
self.closebutton.config(relief = 'flat', bd = 0, bg = '#F8F7B6')
# master (root) window
master.overrideredirect(True)
master.geometry('250x250')
master.config(bg = '#838383')
master.resizable(True,True)
# titlebar
self.titlebar = Frame(root, bg = '#F8F796', relief = 'flat', bd = 2)
self.titlebar.bind('<Button-1>', get_pos)
self.titlebar.bind('<B1-Motion>', move_window)
self.titlebar.pack(fill = X, expand = 1, side = TOP)
self.closebutton = Label(self.titlebar, text = 'X', bg = '#F8F7B6', relief = 'flat')
self.closebutton.bind('<Button-1>', quit_window)
self.closebutton.pack(side = RIGHT)
self.newbutton = Label(self.titlebar, text = '+', bg = '#F8F7B6', relief = 'flat')
self.newbutton.pack(side = LEFT)
self.newbutton.bind('<Button-1>', another_window)
# main text area
self.mainarea = tkst.ScrolledText(master, bg = '#FDFDCA', font=('Comic Sans MS', 14, 'italic'), relief = 'flat', padx = 5, pady = 10)
self.mainarea.pack(fill = BOTH, expand = 1)
# frames to introduce shadows
self.shadow = Frame(root).pack(side=BOTTOM)
self.shadow = Frame(root).pack(side=RIGHT)
root = Tk()
root.attributes('-topmost', 'true')
sticky = StickyNotes(root)
root.mainloop()
You are using classes all wrong. One of the biggest advantages to using classes is the ability to steal code from Tkinter (or whatever GUI or framework you are trying to use). The Tkinter window class is called Toplevel, so you want to subclass that and use the class itself (named "self") for all your operations. I rewrote it for you:
from tkinter import *
import tkinter.scrolledtext as tkst
from tkinter import messagebox
from tkinter import font
class StickyNotes(Toplevel):
def __init__(self, master, **kwargs):
super().__init__(master, **kwargs)
self.xclick = 0
self.yclick = 0
# master (root) window
self.overrideredirect(True)
self.geometry('250x250+500+500')
self.config(bg = '#838383')
self.attributes('-topmost', 'true')
self.resizable(True,True)
# titlebar
self.titlebar = Frame(self, bg = '#F8F796', relief = 'flat', bd = 2)
self.titlebar.bind('<Button-1>', self.get_pos)
self.titlebar.bind('<B1-Motion>', self.move_window)
self.titlebar.pack(fill = X, expand = 1, side = TOP)
self.closebutton = Label(self.titlebar, text = 'X', bg = '#F8F7B6', relief = 'flat')
self.closebutton.bind('<Button-1>', self.quit_window)
self.closebutton.pack(side = RIGHT)
self.newbutton = Label(self.titlebar, text = '+', bg = '#F8F7B6', relief = 'flat')
self.newbutton.pack(side = LEFT)
self.newbutton.bind('<Button-1>', self.another_window)
# main text area
self.mainarea = tkst.ScrolledText(self, bg = '#FDFDCA', font=('Comic Sans MS', 14, 'italic'), relief = 'flat', padx = 5, pady = 10)
self.mainarea.pack(fill = BOTH, expand = 1)
# frames to introduce shadows
self.shadow = Frame(self).pack(side=BOTTOM)
self.shadow = Frame(self).pack(side=RIGHT)
def get_pos(self, event):
self.xclick = event.x
self.yclick = event.y
def move_window(self, event):
self.geometry('+{0}+{1}'.format(event.x_root-self.xclick, event.y_root-self.yclick))
def another_window(self, event):
sticky = StickyNotes(root)
def quit_window(self, event):
self.closebutton.config(relief = 'flat', bd = 0)
if(messagebox.askyesno('Delete Note?','Are you sure you want to delete this note?')):
self.destroy()
return
self.closebutton.config(relief = 'flat', bd = 0, bg = '#F8F7B6')
root = Tk()
root.withdraw()
sticky = StickyNotes(root) # make the first note.
root.mainloop()

Categories

Resources