Tkinter displaying button instead of Label - python

I am creating a little app that will take in details from the user about a bank transaction and then display it in a table.
I am currently using a CSV file to store the data and then when a new piece of data is put in, it will display that too.
I have a list of labels and then a button at the bottom of them to submit new entry. The problem I am getting is when the length of the table exceeds what it was to begin with there is a display error.
class accountant(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
master.title("Accountant")
self.pack()
self.numIncoming = 0
self.numOutgoing = 0
self.incoming = fs.fileStore("incoming", "csv")
print("log: incoming.csv opened sucessfully")
self.outgoing = fs.fileStore("outgoing", "csv")
print("log: outgoing.csv opened sucessfully")
self.setup()
def setup(self):
self.paint()
self.incomingData()
self.outgoingData()
self.newEntryButtons()
def paint(self):
tk.Label(self, width=45, text="incoming").grid(row=1, column=0, columnspan=45)
tk.Label(self, width=45, text="outgoing").grid(row=1, column=45, columnspan=45)
tk.Label(self, width=15, text="Date").grid(row=2, column=0, columnspan=15)
tk.Label(self, width=15, text="Transaction Name").grid(row=2, column=15, columnspan=15)
tk.Label(self, width=15, text="Amount").grid(row=2, column=30, columnspan=15)
tk.Label(self, width=15, text="Date").grid(row=2, column=45, columnspan=15)
tk.Label(self, width=15, text="Transaction Name").grid(row=2, column=60, columnspan=15)
tk.Label(self, width=15, text="Amount").grid(row=2, column=75, columnspan=15)
def incomingData(self):
self.incoming.closeFile()
self.incoming.openFile()
i = 3
for cell in self.incoming.reader:
#cell[0] = Date, cell[1]= Transaction Name, cell[2] =amount
tk.Label(self, width=15, text=cell[0]).grid(row=i, column=0, columnspan=15)
tk.Label(self, width=15, text=cell[1]).grid(row=i, column=15, columnspan=15)
tk.Label(self, width=15, text=cell[2]).grid(row=i, column=30, columnspan=15)
i += 1
self.numIncoming = i
print("incoming:", self.numIncoming-3)
print("outgoing:", self.numOutgoing-3)
def outgoingData(self):
self.outgoing.closeFile()
self.outgoing.openFile()
i = 3
for cell in self.outgoing.reader:
#cell[0] = Date, cell[1]= Transaction Name, cell[2] =amount
tk.Label(self, width=15, text=cell[0]).grid(row=i, column=45, columnspan=15)
tk.Label(self, width=15, text=cell[1]).grid(row=i, column=60, columnspan=15)
tk.Label(self, width=15, text=cell[2]).grid(row=i, column=75, columnspan=15)
i += 1
self.numOutgoing = i
print("incoming:", self.numIncoming-3)
print("outgoing:", self.numOutgoing-3, '\n\n')
def newEntryButtons(self):
if(self.numIncoming < self.numOutgoing):
tk.Button(self, text="new incoming", width=45, command=lambda: self.newEntry(self.incoming)).grid(row=self.numOutgoing, column=0, columnspan=45)
tk.Button(self, text="new outgoing", width=45, command=lambda: self.newEntry(self.outgoing)).grid(row=self.numOutgoing, column=45, columnspan=45)
else:
tk.Button(self, text="new incoming", width=45, command=lambda: self.newEntry(self.incoming)).grid(row=self.numIncoming, column=0, columnspan=45)
tk.Button(self, text="new outgoing", width=45, command=lambda: self.newEntry(self.outgoing)).grid(row=self.numIncoming, column=45, columnspan=45)
def newEntry(self, inFile):
win = tk.Toplevel()
self.newName = tk.StringVar()
self.newDate = tk.StringVar()
self.newAmount = tk.StringVar()
tk.Label(win, width=5, text="Name:").grid(row=0, column=0, columnspan=5)
tk.Entry(win, textvariable=self.newName).grid(row=0, column=5, columnspan=5)
tk.Label(win, width=5, text="date:").grid(row=1, column=0, columnspan=5)
tk.Entry(win, textvariable = self.newDate).grid(row=1, column=5, columnspan=5)
tk.Label(win, width=5, text="amount: £").grid(row=2, column=0, columnspan=5)
tk.Entry(win, textvariable=self.newAmount).grid(row=2, column=5, columnspan=5)
button = tk.Button(win, text="submit", width=5, command= lambda: self.submit(win, inFile))
button.grid(row=5, column=5, columnspan=5)
def submit(self, win, inFile):
with open(inFile.file, 'a') as f:
string= '\n'+self.newName.get() + ',' + self.newDate.get() + ',' + self.newAmount.get()
f.write(string)
if inFile.fileName == "incoming":
self.numIncoming += 1
# print("incoming:", self.numIncoming-3)
# print("outgoing:", self.numOutgoing-3)
else:
self.numOutgoing += 1
print("outgoing:", self.numOutgoing-3)
win.destroy()
self.setup()
filestore is just a class that basically opens the csv using
reader = csv.reader(open(file+'.'fileExt)) where file and fileExt are the parameters passed in.
Here is the image after a new entry. the bottom two buttons should stay as they are and the top two should be d e f in the left column and just whitespace in the right column

Replace self.pack() with self.grid(). To change a Label to Button you will, in addition, have to define a command function that executes when the Button is pressed, see the code below
bttn = tk.Button(self, text = "buttontitle", command = self.do_function )
bttn.grid(row = 14, column = 4, sticky = W)
def do_function():
print "HI"

Related

Save bottom only saves the last entry into excel sheet (tkinter)

Here, I have two classes. First one (MedicalDevices.py) has the functions that I wanna use on the second class (tkinter_devices.py).
I am new to python and the help is appreciate it
Issue I am facing:
I am trying to enter information of devices to excel sheet, but every time I entered more than one device's information, it only save the last entries that I entered while the tkinter running.
MedicalDevices.py
import datetime
import pandas as pd
# excel file path
f_path = "medical_devices_data.xlsx"
df = pd.read_excel(f_path, sheet_name="Sheet1")
class MedicalDevices:
# class attributes: to keep truck the number of the objects that been made.
num_of_devices = 0
# initialization/ construction
def __init__(self, name, sn, manufacture, model, supplier, department='In Store', warranty_expire="Expired"):
# object attributes (to make private attribute, add __ before the name
self.name = name
self.sn = sn
self.manufacture = manufacture
self.model = model
self.supplier = supplier
self.department = department
self.warranty_expire = warranty_expire
# increase number of devices made with every initialization
MedicalDevices.num_of_devices += 1
# dunder (double underscore)method
# override function to print string instead of printing the memory address of an object
def __str__(self):
return f"Name: {self.name}\nSerial#: {self.sn}\nManufacture: {self.manufacture}\n" \
f"Model: {self.model}\nSupplier: {self.supplier}\nDepartment: {self.department}\n" \
f"Warranty expire on: {self.warranty_expire}"
def add_new_device(newDevice):
SerA = df["Name"]
SerB = df["Serial"]
SerC = df["Manufacture"]
SerD = df["Model"]
SerE = df["Supplier"]
SerF = df["Department"]
SerG = df["Warranty"]
# this must be Series type to be able to concatenate with DataFrame
A = pd.Series(newDevice.name)
B = pd.Series(newDevice.sn)
C = pd.Series(newDevice.manufacture)
D = pd.Series(newDevice.model)
E = pd.Series(newDevice.supplier)
F = pd.Series(newDevice.department)
G = pd.Series(newDevice.warranty_expire)
SerA = SerA.append(A)
SerB = SerB.append(B)
SerC = SerC.append(C)
SerD = SerD.append(D)
SerE = SerE.append(E)
SerF = SerF.append(F)
SerG = SerG.append(G)
df2 = pd.DataFrame({"Name": SerA,
"Serial": SerB,
"Manufacture": SerC,
"Model": SerD,
"Department": SerE,
"Supplier": SerF,
"Warranty": SerG})
df2.to_excel(f_path, index=False)
print(f"A new device added with Serial#: {newDevice.sn}")
#
# def search_by_sn(self, sn):
# if sn in df.values:
# print("Got it. Here is the device(s) info: \n-------------------------------")
# print(df.loc[df.Serial == sn])
# else:
# print("Not found")
# newInput = input("Do you want to add a new device (yes/ no): ")
# if newInput == "yes":
# self.add_new_device(DC_1)
# else:
# print("Ok")
# To check Warranty
def check_warranty(self):
date = datetime.datetime.strptime(self.warranty_expire, '%Y/%m/%d').date()
if date >= datetime.date.today():
print(self.name + " is still in Warranty\n" + "Warranty expires on " + self.warranty_expire)
else:
print("Attention, Warranty expired on " + self.warranty_expire)
tkinter_devices.py
import tkinter as tk
from tkinter import ttk
import pandas as pd
from MedicalDevices import MedicalDevices
font1 = ("Verdana", 12)
font2 = ("Verdana", 10)
pageSize = "500x300"
f_path = "medical_devices_data.xlsx"
df = pd.read_excel(f_path, sheet_name="Sheet1")
class MedicalDeviceApp(tk.Tk):
# args=argument (any number of argument (unlimited))
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Medical Devices Data")
tk.Tk.wm_geometry(self, pageSize) # (width x height)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, AddDevice, PageTwo):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text="Start Page", font=font1)
label.grid(row=0, column=5, sticky="nsew")
bot1 = ttk.Button(self, text="Add a new device",
command=lambda: controller.show_frame(AddDevice))
bot1.grid(row=1, column=0, sticky="nsew", columnspan=1, ipadx=5)
bot2 = ttk.Button(self, text="Page Two",
command=lambda: controller.show_frame(PageTwo))
bot2.grid(row=2, column=0, sticky="nsew")
bot_exit = ttk.Button(self, text="Exit", command=lambda: controller.destroy())
bot_exit.grid(row=3, column=0, sticky="nsew")
class AddDevice(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
# Labels
label1 = ttk.Label(self, text="Enter a new device information", font=font1)
label1.grid(row=0, column=1)
label2 = ttk.Label(self, text="Required information with *")
label2.grid(row=1, column=1, pady=5)
label_name = ttk.Label(self, text="Device Name:", font=font2)
label_name.grid(row=2, column=0, sticky="w")
label_serial = ttk.Label(self, text="Serial Number:", font=font2)
label_serial.grid(row=3, column=0, sticky="w")
label_manf = ttk.Label(self, text="Manufacture:", font=font2)
label_manf.grid(row=4, column=0, sticky="w")
label_model = ttk.Label(self, text="Model:", font=font2)
label_model.grid(row=5, column=0, padx=2, sticky="w")
label_supplier = ttk.Label(self, text="Supplier:", font=font2)
label_supplier.grid(row=6, column=0, padx=2, sticky="w")
label_depart = ttk.Label(self, text="Department:", font=font2)
label_depart.grid(row=7, column=0, padx=2, sticky="w")
label_expire = ttk.Label(self, text="Expire Date:", font=font2)
label_expire.grid(row=8, column=0, padx=2, sticky="w")
# Entries
self.entry_name = ttk.Entry(self)
self.entry_name.grid(row=2, column=1, ipadx=20, pady=5)
self.entry_serial = ttk.Entry(self)
self.entry_serial.grid(row=3, column=1, ipadx=20, pady=5)
self.entry_manf = ttk.Entry(self)
self.entry_manf.grid(row=4, column=1, ipadx=20, pady=5)
self.entry_model = ttk.Entry(self)
self.entry_model.grid(row=5, column=1, ipadx=20, pady=5)
self.entry_supplier = ttk.Entry(self)
self.entry_supplier.grid(row=6, column=1, ipadx=20, pady=5)
self.entry_depart = ttk.Entry(self)
self.entry_depart.grid(row=7, column=1, ipadx=20, pady=5)
self.entry_expire = ttk.Entry(self)
self.entry_expire.grid(row=8, column=1, ipadx=20, pady=5)
# Bottoms
self.bot_save = ttk.Button(self, text="Save", command=self.save)
self.bot_save.grid(row=2, column=2, ipadx=20, pady=5, columnspan=1)
self.bot_clear = ttk.Button(self, text="Clear", command=self.delete)
self.bot_clear.grid(row=4, column=2, ipadx=20, pady=2, columnspan=1)
self.bot_back = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
self.bot_back.grid(row=6, column=2, ipadx=20)
self.bot_exit = ttk.Button(self, text="Exit", command=lambda: controller.destroy())
self.bot_exit.grid(row=8, column=2, ipadx=25)
def delete(self):
self.entry_name.delete(0, 'end')
self.entry_serial.delete(0, 'end')
self.entry_manf.delete(0, 'end')
self.entry_model.delete(0, 'end')
self.entry_supplier.delete(0, 'end')
self.entry_depart.delete(0, 'end')
self.entry_expire.delete(0, 'end')
def save(self):
if int(self.entry_serial.get()) in df.values:
print("found it ")
self.delete()
else:
device = MedicalDevices(self.entry_name.get(), self.entry_serial.get(), self.entry_manf.get(),
self.entry_model.get(), self.entry_supplier.get(), self.entry_depart.get(),
self.entry_expire.get())
MedicalDevices.add_new_device(device)
self.delete()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text="Page Tow", font=font1)
label.pack(pady=10, padx=10)
bot1 = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
bot1.pack()
app = MedicalDeviceApp()
app.mainloop()
Inside add_new_device(), you copy serise from the global df and append the new record, then create a new dataframe df2 with the new series and save to file. However you forget to update the global df so that it does not include the new device. Next time another new device is to be added, you copy series from the global df again which does not have the previously added device, append the current new device and save to file. The file will then be overwritten without the previously added device.
To fix that you need to update the global df instead of creating a new dataframe df2. Also suggest to move the global df into MedicalDevices as a class variable:
class MedicalDevices:
# excel file path
f_path = "medical_devices_data.xlsx"
df = pd.read_excel(f_path, sheet_name="Sheet1")
...
def add_new_device(newDevice):
# update class dataframe `df` instead of creating new one
MedicalDevices.df = MedicalDevices.df.append({
"Name": newDevice.name,
"Serial": newDevice.sn,
"Manufacture": newDevice.manufacture,
"Model": newDevice.model,
"Supplier": newDevice.supplier,
"Department": newDevice.department,
"Warranty": newDevice.warranty_expire
}, ignore_index=True)
# export to file
MedicalDevices.df.to_excel(MedicalDevices.f_path, index=False)
print(f"A new device added with Serial#: {newDevice.sn}")

How to call onto the class that is in the tkinter mainloop?

I've been trying to call the class that is in my mainloop, but whenever I properly call it makes it that the program doesn't even launch anymore. I've been attempting to call it in order to get a method, which would return the current frame. I am aware that my code uses controller and parent to communicate between classes, but I haven't managed to fully grasp an understanding of these. If I call the mainlooped class, with "test = Database_project()", then the program won't run anymore. Can someone explain this to me? I'm trying to get the scrollbar feature to work on specific frames, and I haven't managed to figure out just yet. I'm trying to call the mainlooped class in the "CreatePage" class. Thank you in advance!
from tkinter import *
import tkinter as tk
class Database_Project(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
stack_frame_container = tk.Frame(self)
stack_frame_container.grid_columnconfigure(0, weight=1)
stack_frame_container.grid_rowconfigure(0, weight=1)
stack_frame_container.pack(side="top", fill="both", expand=True)
self.frameslist = {}
for frame in (MainPage, CreatePage):
frame_occurrence = frame.__name__
active_frame = frame(parent=stack_frame_container, controller=self)
self.frameslist[frame_occurrence] = active_frame
active_frame.grid(row=0, column=0, sticky="snew")
#self.frameslist["CreatePage"].dbproject = self.frameslist["Datanase_Project"]
self.current_frame("MainPage")
print(self.frameslist)
def current_frame(self, frame_occurrence):
active_frame = self.frameslist[frame_occurrence]
active_frame.tkraise()
def get_current_frame(self, frame_occurrence):
active_frame = self.frameslist[frame_occurrence]
return active_frame
class MainPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label_create = tk.Label(self, text="Create and insert data").grid(row=0, column=0, padx=50, pady=(50,0))
create_button = tk.Button(self, text="CREATE", command=lambda: controller.current_frame("CreatePage")).grid(row=1, column=0)
label_read = tk.Label(self, text="Query over data").grid(row=0, column=1, padx=50, pady=(50,0))
read_button = tk.Button(self, text="READ").grid(row=1, column=1)
label_update = tk.Label(self, text="Modify existing data").grid(row=2, column=0, padx=50, pady=(50,0))
update_button = tk.Button(self, text="UPDATE").grid(row=3, column=0, pady=(0,50))
label_delete = tk.Label(self, text="Remove data").grid(row=2, column=1, padx=50, pady=(50,0))
delete_button = tk.Button(self, text="DELETE").grid(row=3, column=1, pady=(0,50))
class CreatePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.inputlist = []
self.newinputlist = []
Test = Database_Project()
#active_frame = Test.get_current_frame("CreatePage")
#scrollbar = tk.Scrollbar(active_frame, orient="vertical")
#scrollbar.grid(row=0, column=2, stick="ns", columnspan=10)
#text["yscrollcommand"] =
labels = [tk.Label(self, text="Enter unique field"), tk.Label(self, text="Enter corresponding the value/s")]
self.inputlist.append(labels[:])
for toplabels in range(1):
self.inputlist[toplabels][0].grid(row=toplabels, column=0, padx=10, pady=5)
self.inputlist[toplabels][1].grid(row=toplabels, column=1, padx=10, pady=5)
first_entries = [tk.Entry(self, borderwidth=5), tk.Text(self, borderwidth=5, height= 5, width=20)]
self.newinputlist.append(first_entries[:])
self.inputlist.append(first_entries[:])
for x in range(0, len(self.newinputlist) + 1):
self.newinputlist[0][x].grid(row=1, column=x, padx=10, pady=5)
button_input_1 = [tk.Button(self, text="ADD FIELD/VALUE", command=self.add_insert), tk.Button(self, text="BACK", command=lambda: controller.current_frame("MainPage"))]
self.inputlist.append(button_input_1[:])
button_input_2 = [tk.Button(self, text="IMPORT FILE"), tk.Button(self, text="SUBMIT DATA", command=self.submit_data)]
self.inputlist.append(button_input_2[:])
for button in range(len(self.inputlist) - 2, len(self.inputlist)):
self.inputlist[button][0].grid(row=button, column=0, padx=10, pady=5)
self.inputlist[button][1].grid(row=button, column=1, padx=10, pady=5)
def add_insert(self):
add_input = [tk.Entry(self, borderwidth=5), tk.Text(self, borderwidth=5, height= 5, width=20)]
self.inputlist.insert(-2, add_input)
self.newinputlist.append(add_input)
for widget in self.children.values():
widget.grid_forget()
for index, widgets in enumerate(self.inputlist):
print(widgets)
widget_one = widgets[0]
widget_two = widgets[1]
print(str(index), widget_one, widget_two)
widget_one.grid(row=index, column=0, padx=10, pady=5)
widget_two.grid(row=index, column=1, padx=10)
def submit_data(self):
for index, entries in enumerate(self.newinputlist):
my_label = Label(self, text=str(entries[0].get()) + str(entries[1].get("1.0", END)))
my_label.grid(row=len(self.inputlist) + index, column=0)
if __name__ == "__main__":
NoSQL_Project = Database_Project()
NoSQL_Project.title("NoSQL Database Project")
NoSQL_Project.maxsize(500, 500)
NoSQL_Project.mainloop()

How do I return the length of the currently focussed Entry in Tkinter? (Backspace focussed entry)

I'm trying to create a backspace button for a GUI, currently I have a Clear effect bound to one button but its irritating when a mistake is made having to retype the entire string.
I have tried several rearrangements of Entry.focus_get(self), trying to call from within len, i.e. len(Entry.focus_get(self)-1, END).
from tkinter import *
from datetime import datetime
import time
from time import sleep
import csv
import tkinter
class LabeledCheckbutton(Frame):
def __init__(self, root):
Frame.__init__(self, root)
self.checkbutton = Checkbutton(self)
self.label = Label(self)
self.label.grid(row=0, column=0, sticky=W)
self.checkbutton.grid(row=0, column=1, sticky=E)
class Clock(Frame):
def __init__(self, root):
Frame.__init__(self, root)
clock_frame = Label(self)
clock_frame['text'] = '19:12:09'
clock_frame.grid(row=0, column=0)
def tic():
clock_frame['text'] = datetime.now().strftime("%d %B %Y %I:%M:%S %p")
def tac():
tic()
clock_frame.after(1, tac)
tac()
class SampleApp(Tk):
def __init__(self):
Tk.__init__(self)
self._frame = None
self.switch_frame(AddMethod)
def switch_frame(self, frame_class):
"""Destroys current frame and replaces it with a new one."""
#camera.stop_preview()
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.grid(row=0, column=0)
class AddMethod(Frame):
def __init__(self, master):
Frame.__init__(self, master)
title = Label(self, text="Method Settings").grid(row=0, column=1)
clock = Clock(self).grid(row=0, column=2, columnspan=2)
a1 = Button(self, text='Back', height=5, width=20, command=lambda: master.switch_frame(ManMeth)).grid(row=1, rowspan=2, column=0, sticky='')
a2 = Button(self, text='Save and Return to Analysis', height=5, width=20, command=lambda: master.switch_frame(ManMeth)).grid(row=3, rowspan=2, column=0, sticky='')
a3 = Button(self, text='Save Method', height=5, width=20, command=self.writeToFile).grid(row=5, column=0, sticky='')
mthtit = Label(self, text="Method Title", font="Verdana 20").grid(row=2, column=1, sticky=W)
sttemp = Label(self, text="Start Temperature", font="Verdana 20").grid(row=3, column=1, sticky=W)
wttm = Label(self, text="Waiting Time", font="Verdana 20").grid(row=4, column=1, sticky=W)
sktm = Label(self, text="Soaking Time", font="Verdana 20").grid(row=5, column=1, sticky=W)
endtemp = Label(self, text="End Temperature", font="Verdana 20").grid(row=6, column=1, sticky=W)
htrt = Label(self, text="Heating Rate", font="Verdana 20").grid(row=7, column=1, sticky=W)
self.labeledcb = LabeledCheckbutton(self)
self.labeledcb.label.configure(text="Ramp to Starting Temperature", font="Verdana 20")
self.labeledcb.grid(row=1, column=1, sticky=W, padx=10, pady=10)
self.mthtite = Entry(self, relief=SUNKEN, bd=5)
self.mthtite.grid(row=2, column=2, padx=10, pady=10)
self.sttempe = Entry(self, relief=SUNKEN, bd=5)
self.sttempe.grid(row=3, column=2, padx=10, pady=10)
self.wttme = Entry(self, relief=SUNKEN, bd=5)
self.wttme.grid(row=4, column=2, padx=10, pady=10)
self.sktme = Entry(self, relief=SUNKEN, bd=5)
self.sktme.grid(row=5, column=2, padx=10, pady=10)
self.endtempe = Entry(self, relief=SUNKEN, bd=5)
self.endtempe.grid(row=6, column=2, padx=10, pady=10)
self.htrte = Entry(self, relief=SUNKEN, bd=5)
self.htrte.grid(row=7, column=2, padx=10, pady=10)
sttemp1 = Label(self, text="°C", font="Verdana 20").grid(row=3, column=3, sticky=W)
wttm1 = Label(self, text="Sec", font="Verdana 20").grid(row=4, column=3, sticky=W)
sktm1 = Label(self, text="MM:SS", font="Verdana 20").grid(row=5, column=3, sticky=W)
endtemp1 = Label(self, text="°C", font="Verdana 20").grid(row=6, column=3, sticky=W)
htrt1 = Label(self, text="°C/Min", font="Verdana 20").grid(row=7, column=3, sticky=W)
buttons = [
'~','`','!','#','#','$','%','^','&','*','(',')','-','_' ,'Clear',
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P','\\','7','8','9','Back',
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L','[',']','4','5','6','Tab',
'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.','?','/','1','2','3','Space',
]
#entry = Entry.focus_get(self)
#def length():
#ln = Entry.focus_get(self).get
#length = (len(ln)-1)
widget = self.focus_get()
if widget:
widget.delete(widget.index("end")-1)
####################
def select(value):
if value =="Clear":
Entry.focus_get(self).delete(0, END)
elif value == "Back":
Entry.focus_get(self).delete(widget)
elif value == "Space":
Entry.focus_get(self).insert(END, ' ')
elif value == " Tab ":
Entry.focus_get(self).insert(END, ' ')
else :
Entry.focus_get(self).insert(END, value)
######################
class Keyboard(Frame):
def __init__(self, root):
Frame.__init__(self, root)
def HosoPop():
varRow = 2
varColumn = 0
for button in buttons:
command = lambda x=button: select(x)
if button == "Clear" or button == "Back" or button == "Tab" or button == "Space":
Button(self,text= button,width=9, height=3, bg="grey", fg="black",
activebackground = "#ffffff", activeforeground="#3c4987", padx=2,
command=command).grid(row=varRow,column=varColumn)
else:
Button(self,text= button,width=8, height=3, bg="grey", fg="black",
activebackground = "#ffffff", activeforeground="#3c4987",
command=command).grid(row=varRow,column=varColumn)
varColumn +=1
if varColumn > 14 and varRow == 2:
varColumn = 0
varRow+=1
if varColumn > 14 and varRow == 3:
varColumn = 0
varRow+=1
if varColumn > 14 and varRow == 4:
varColumn = 0
varRow+=1
HosoPop()
#btmfrm = Frame(self, height=200, width=800, bd=1, relief=SUNKEN).grid(row=8, columnspan=3)
keys = Keyboard(self).grid(row=8, column=1, columnspan=2)
#keys = KeyboardEntry(self).grid(row=8, column=1, columnspan=2)
def writeToFile(self):
with open('Working_MethodFile.csv', 'a') as f:
w=csv.writer(f, quoting=csv.QUOTE_ALL)
w.writerow([self.mthtite.get(), self.sttempe.get(), self.wttme.get(), self.sktme.get(), self.endtempe.get(), self.htrte.get()])
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
I would like the button to remove the last character from the currently focussed text entry, similarly to how clear removes all text from the currently focussed entry.
You can use the focus_get method of the root window to determine which widget has the keyboard focus.
You can use the index method to get the index of the last character. To delete that character, subtract one from the index and pass that to the delete method:
widget = root.focus_get()
if widget:
widget.delete(widget.index("end")-1)
Here is a complete working example:
import tkinter as tk
def do_delete():
widget = root.focus_get()
if widget:
widget.delete(widget.index("end")-1)
root = tk.Tk()
for i in range(5):
entry = tk.Entry(root)
entry.pack(side="top", fill="x")
button = tk.Button(root, text="Delete last char", command=do_delete)
button.pack(side="bottom", expand=True)
root.mainloop()
I ended up just having to add your code into the "Back" Button command as below;
def select(value):
if value =="Clear":
Entry.focus_get(self).delete(0, END)
elif value == "Back":
widget = Entry.focus_get(self)
if widget:
widget.delete(widget.index("end")-1)
elif value == "Space":
Entry.focus_get(self).insert(END, ' ')
elif value == " Tab ":
Entry.focus_get(self).insert(END, ' ')
else :
Entry.focus_get(self).insert(END, value)
Thanks for your help on this!! I spent a few long nights trying to work on this before giving up and asking for help haha.

If error, return to the same window Python Tkinter 2.7

I would like to return to the same page if a field is not completed.
Here is what I have tried so far:
class Tenants(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self,master)
self.tenant_entries=[]
self.create_widgets(master)
def create_widgets(self,master):
label = tk.Label(self, text="Insert the name of the tenants")
start_button = tk.Button(self, text="Return to start page", command=lambda: master.switch_frame(StartPage))
new_tenant_button = tk.Button(self, text="Add tenant", command=self.add_tenant)
new_tenant_button.bind("<Return>", self.add_tenant)
new_tenant_button.grid(row=len(self.master.tenants), column=3, padx=4, pady=6, sticky="W")
next_button=tk.Button(self, text="Next", command=lambda:[master.switch_frame(Networks)] and self.tenants())
next_button.grid(row=1500, column=5,padx=4, pady=6, sticky="W")
label.pack(side="top", fill="x", pady=10)
start_button.pack()
new_tenant_button.pack()
next_button.pack()
for index, tenant in enumerate(self.master.tenants):
self.render_tenant_field(tenant, index)
def add_tenant(self):
self.master.tenants.append({'variable': tk.StringVar(self.master)})
self.master.switch_frame(Tenants)
def render_tenant_field(self, tenant, index):
entry_field = tk.Entry(self, textvariable=tenant['variable'])
entry_field.grid(row=index, column=0, columnspan=2, padx=4, pady=6, sticky="NEWS")
entry_field.pack()
self.tenant_entries.append(tenant['variable'])
def tenants(self):
with open("/home/dante/tenants.yml", "w") as f:
if self.tenant_entries:
f.write("--- #" + "\n")
f.write("clouds:" + "\n")
for ent in self.tenant_entries:
value=ent.get()
if value:
f.write(" "+value+":"+ "\n")
f.write(" username: admin"+"\n")
else:
tkMessageBox.showerror("tk", "No tenants defined!")
With this code, I am getting the error message, but after clicking OK, is going to the next page. I would like that after clicking OK to return to the same page(Tenants) to fill that field.
How I can accomplish this?
Found the way:
class Tenants(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self,master)
self.tenant_entries=[]
self.create_widgets(master)
def create_widgets(self,master):
label = tk.Label(self, text="Insert the name of the tenants")
start_button = tk.Button(self, text="Return to start page", command=lambda: master.switch_frame(StartPage))
new_tenant_button = tk.Button(self, text="Add tenant", command=self.add_tenant)
new_tenant_button.bind("<Return>", self.add_tenant)
new_tenant_button.grid(row=len(self.master.tenants), column=3, padx=4, pady=6, sticky="W")
next_button=tk.Button(self, text="Next", command=lambda:[master.switch_frame(Networks)] and self.tenants())
next_button.grid(row=1500, column=5,padx=4, pady=6, sticky="W")
label.pack(side="top", fill="x", pady=10)
start_button.pack()
new_tenant_button.pack()
next_button.pack()
for index, tenant in enumerate(self.master.tenants):
self.render_tenant_field(tenant, index)
def add_tenant(self):
self.master.tenants.append({'variable': tk.StringVar(self.master)})
self.master.switch_frame(Tenants)
def render_tenant_field(self, tenant, index):
entry_field = tk.Entry(self, textvariable=tenant['variable'])
entry_field.grid(row=index, column=0, columnspan=2, padx=4, pady=6, sticky="NEWS")
entry_field.pack()
self.tenant_entries.append(tenant['variable'])
def tenants(self):
with open("/home/dante/tenants.yml", "w") as f:
if self.tenant_entries:
f.write("--- #" + "\n")
f.write("clouds:" + "\n")
for ent in self.tenant_entries:
value=ent.get()
if value:
f.write(" "+value+":"+ "\n")
f.write(" username: admin"+"\n")
else:
tkMessageBox.showerror("tk", "No tenants defined!")
self.master.switch_frame(Tenants)

NameError with defining command on python

I don't understand why I keep getting the error: NameError: name 'submit_answer' is not defined.
class Add(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent, background="blue")
button = tk.Button(self, text="Main Menu", font=LARGE_FONT, background="white",
command=lambda: controller.show_frame(Main))
button.place(relx=0.83, rely=0.92)
button4 = tk.Button(self, text="Start Game", font=LARGE_FONT, background="white",
command=self.time_start)
button4.place(relx=0.42, rely=0.8, relheight=0.1, relwidth=0.2)
def time_start(self):
timelabel = tk.Label(self, text="Good luck!", font=LARGE_FONT, background="blue")
timelabel.place(relx=0.42, rely=0.8, relheight=0.1, relwidth=0.2)
x = int(random.uniform(1,10))
y = int(random.uniform(50,100))
z = int(random.uniform(10,50))
qlabel = tk.Label(self, text= (x,"+",y,"+",z,"=",), font=LARGE_FONT, bg="blue")
qlabel.pack()
## entrylabel = tk.Label(self, text="Answer:", font=LARGE_FONT, background="blue")
## entrylabel.pack()
e1 = tk.Entry(self)
e1.pack()
ebutton = tk.Button(self, text="Done", font=LARGE_FONT, background="white",
command=submit_answer)
ebutton.pack()
def submit_answer(self):
a = (x+y+z)
if int(e1.get()) == a:
answerlabel = tk.Label(self, text="Correct!", font=LARGE_FONT, background="blue")
answerlable.pack()
else:
answerlabel = tk.Label(self, text="Incorrect!", font=LARGE_FONT, background="blue")
answerlable.pack()
self.label = tk.Label(self, text="", width=10, font=LARGE_FONT)
self.label.place(relx=0.1, rely=0.1)
self.remaining = 0
self.countdown(5)
in order to call the method submit_answer that in the class you should use: self.submit_answer
so this line should change to:
ebutton = tk.Button(self, text="Done", font=LARGE_FONT, background="white",
command=self.submit_answer)

Categories