Tkinter button not showing up until mouse hovers over it - python

There is a function which I call to add one row each time it's called containing an Entry, Combobox and a Button. When I first call the function, the button is not visible until I move the mouse cursor to the supposed position of the button.
Before cursor hover After cursor hover
If I call the function multiple times at once, all other rows contain the button visibly except the first one. I'm using grid layout inside a frame.
namevar = StringVar()
cbvar = StringVar()
entry = Entry(self.createTableFrame, textvariable = namevar)
cb = ttk.Combobox(self.createTableFrame, textvariable = cbvar, values= self.sqlDatatypes,
state='readonly'
)
cb.bind("<<ComboboxSelected>>", self.datatypeSelect)
cb.bind("<Return>", self.datatypeSelect)
#this segment contains the error
btn = Button(self.createTableFrame, text='Remove')
btn.bind('<Button-1>', self.deleteRowNT)
entry.grid(row=self.rowcountNT, column = 0)
cb.grid(row=self.rowcountNT, column = 1)
btn.grid(row = self.rowcountNT, column = 2)
Here is the Full code for reference:
(the error is occuring in the function def nextEntryTable(self) in the class Tables(Scan) )
from tkinter import *
import tkinter as tk
from tkinter import ttk
import mysql.connector
class Scrollable(ttk.Frame):
# Make a frame scrollable with scrollbar on the right.
# After adding or removing widgets to the scrollable frame,
# call the update() method to refresh the scrollable area.
def __init__(self, frame, width=16):
scrollbar = tk.Scrollbar(frame, width=width)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y, expand=False)
self.canvas = tk.Canvas(frame, yscrollcommand=scrollbar.set)
self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.config(command=self.canvas.yview)
self.canvas.bind('<Configure>', self.__fill_canvas)
# base class initialization
tk.Frame.__init__(self, frame)
# assign this obj (the inner frame) to the windows item of the canvas
self.windows_item = self.canvas.create_window(0,0, window=self, anchor=tk.NW)
def __fill_canvas(self, event):
"Enlarge the windows item to the canvas width"
canvas_width = event.width
self.canvas.itemconfig(self.windows_item, width = canvas_width)
def update(self):
"Update the canvas and the scrollregion"
self.update_idletasks()
self.canvas.config(scrollregion=self.canvas.bbox(self.windows_item))
class Scan(Frame):
def __init__(self, master):
self.flag = 0 # to stop multiple instances opening
self.master = master
self.master.geometry('300x200+500+300')
self.master.title('Scan Page')
self.frame = Frame(self.master)
lablist = ['Host','User name','Password', 'Database']
self.lables, self.entries, self.svars = self.addlables(self.frame, lablist)
self.b1=Button(self.frame,text='SCAN',command=self.tableselect)
self.b1.grid(row= len(lablist))
self.master.bind('<Return>',self.tableselect)
self.message = Message(self.frame, text='Connection status',
bg ='Grey', width= 100)
self.message.grid(row = 5, column = 1)
self.frame.pack(fill='x',expand= True)
self.tables = None
def tableselect(self, event=None):
try:
self.tables.destroy()
except:
print('Nothing to destroy')
conn = self.databaseconnect()
# print( self.entries[0]["textvariable"] )
if conn != -1:
self.tables = Toplevel(self.master)
self.app = Tables(self.tables, conn)
def addlables(self, lableroot, lablelist):
lables = []
entries = []
svars = []
for labs, i in zip(lablelist, range(len(lablelist))):
l = Label(lableroot, text = labs)
l.grid(row=i)
e = Entry(lableroot)
e.grid(row=i, column = 1, columnspan = 5)
s = StringVar()
e['textvariable'] = s
lables.append(l)
entries.append(e)
svars.append(s)
svars[0].set('localhost')
svars[1].set('myproject')
svars[2].set('myproject')
return [lables, entries, svars]
def printvals(self, event):
for s in self.svars:
print(s.get())
def databaseconnect(self):
s = self.svars
try:
if s[3].get()=='':
conn = mysql.connector.connect(host=s[0].get(), user = s[1].get(),
passwd = s[2].get())
else:
conn = mysql.connector.connect(host=s[0].get(), user = s[1].get(),
passwd = s[2].get(),
database = s[3].get())
self.message.config(text='Connected', bg ='Lightgreen')
return conn
except Exception as e:
for x in e.args:
print(x)
self.message.config(text="Error Connecting", bg='Red')
# self.message.grid(row = 5)
return -1
class Tables(Scan):
def __init__(self, master, connector):
self.conn = connector
self.cursor = self.conn.cursor()
self.master = master
self.master.geometry('600x400+150+20')
self.master.title('Table Selection')
if self.conn.database == None:
print('Connected without a database')
self.dbRadiobuttonState = 'normal'
else:
print('Conneccted using ',self.conn.database,' database')
self.dbRadiobuttonState = 'disabled'
self.master.title('Database: ' + self.conn.database)
self.f1 = Frame(self.master, padx=5) ## Main frame
self.entry = Entry(self.f1)
self.data = StringVar() ##Variable to get value from the Entry bar
self.entry['textvariable'] = self.data
self.entry.pack(fill = X, pady = 10)
##Button creations segment
self.f2root = Frame(self.f1) ##Main left frame, fixed size
self.f2 = Frame(self.f2root) ##top bar for 'Open tables'
self.b1 = Button(self.f2, text = ' Open Table', command= self.openTableClick)
self.b1.pack(side = 'left')
self.b1.bind('<Return>', self.openTableClick)
self.b2 = Button(self.f2, text = ' Select Databse ', command = self.selectDatabaseClick)
self.b2.bind('<Return>', self.selectDatabaseClick)
self.b2.pack(side = 'left', expand=True)
self.f2.pack(side = 'top')
self.f22 = Frame(self.f2root) ##Bar frame below self.f2
self.b12 = Button(self.f22, text = 'Create Table ', command = self.createTableClick)
self.b12.pack(side = 'left')
self.b22 = Button(self.f22, text = 'Create Database')
self.b22.pack(side = 'left')
self.f22.pack(side = 'top')
self.f2root.pack(fill='y', side='left')
##Button creation ended
self.nb = ttk.Notebook(self.f1)
self.dbPage = ttk.Frame(self.nb)
self.setDBList()
self.tablesPage = ttk.Frame(self.nb)
self.tableList= [] #Contains a list of all the tables
self.tableFrameBuffer = [] #Contains a list of all the Frames
self.currentFrameSelected = -1
self.tableLayoutSet()
if self.dbRadiobuttonState == 'disabled':
self.createTableBuffer()
self.dbval.set( self.dbList.index( self.conn.database))
self.nb.add(self.dbPage, text = 'Databse')
self.nb.add(self.tablesPage, text = 'Tables')
self.nb.pack(expand=1, fill='both')
self.f1.pack(fill='both', expand= True)
def selectDatabaseClick(self, event=None):
print('Database: ',self.data.get())
try:
index = self.dbList.index(self.data.get())
print('Index: ', index)
self.dbval.set(index)
self.connectDB()
except:
print('Error in clicking DB Select button')
def openTableClick(self, event=None): ##Called whenever we click 'Open table'
print(self.data.get())
try:
index = self.tableList.index(self.data.get())
print('Table index: ',index)
self.tabVar.set(index+1)
self.tableSelect()
except:
print('Could not find entered table')
def createTableClick(self):
##Uses button self.b12
print('Create Table clicked')
if self.nb.winfo_ismapped():
print('Notebook state: ', self.nb.winfo_ismapped())
self.nb.pack_forget()
self.b12.config(text = 'Cancel')
self.b22.config(state='disabled')
self.createNewTableLayout()
self.newTableMF.pack(fill='both', expand=True, anchor = 'n')
else:
self.newTableMF.pack_forget()
print('Notebook state: ', self.nb.winfo_ismapped())
self.nb.pack(expand=1, fill='both')
self.b12.config(text='Create Table ')
self.b22.config(state='normal')
def setDBList(self):
self.dbList = []
self.cursor.execute("SHOW DATABASES")
self.dbval = IntVar()
self.dbval.set(-1)
i=0
for (x,) in self.cursor:
self.dbList.append(x)
rb = tk.Radiobutton(self.dbPage,
text=x,
padx = 20,
variable=self.dbval,
command=self.connectDB,
state = self.dbRadiobuttonState,
value=i)
rb.pack(anchor="nw")
i=i+1
def connectDB(self):
self.cursor.execute("USE " + self.dbList[self.dbval.get()])
print("Databse selected: " + self.conn.database)
self.master.title('Database: ' + self.conn.database)
self.createTableBuffer()
def createTableBuffer(self):
self.cursor.execute("show tables")
self.tabVar = IntVar()
##CLeanup code
for destroyableFrame in self.tableFrameBuffer:
destroyableFrame.destroy()
self.currentFrameSelected = -1
self.tableFrameBuffer = [] ##Contains the list of Frames
self.tableList = []
for (x,) in self.cursor:
if (self.cursor.rowcount -1) % 10 == 0:
# print(self.cursor.rowcount,'Frame buffer ',' added ')
tempFrame = Frame(self.tablesTopFrame)
self.tableFrameBuffer.append(tempFrame)
self.currentFrameSelected = len(self.tableFrameBuffer)-1
rb = Radiobutton(self.tableFrameBuffer[-1],
text = x,
padx=20,
pady=2,
variable = self.tabVar,
command = self.tableSelect,
value = self.cursor.rowcount)
rb.pack(anchor='w')
self.tableList.append(x) ## List of all the names of tables
if len(self.tableFrameBuffer) >0:
self.tableFrameBuffer[0].pack()
self.currentFrameSelected = 0
def tableLayoutSet(self):
self.tablesTopFrame = Frame(self.tablesPage)
self.tablesBottomFrame = Frame(self.tablesPage)
self.nextTableButton = Button(self.tablesBottomFrame, text = 'Next',
command = self.nextTableFrame, padx=10)
self.prevTableButton = Button(self.tablesBottomFrame, text = 'Previous',
command = self.prevTableFrame, padx=10)
self.prevTableButton.pack(side = 'left')
self.nextTableButton.pack( side = 'left')
self.tablesBottomFrame.pack(side = 'bottom', fill='x')
self.tablesTopFrame.pack(side = 'top', anchor = 'w')
def nextTableFrame(self):
if self.currentFrameSelected < len(self.tableFrameBuffer) -1:
self.tableFrameBuffer[self.currentFrameSelected].pack_forget()
self.tableFrameBuffer[self.currentFrameSelected + 1].pack()
self.currentFrameSelected += 1
def prevTableFrame(self):
if self.currentFrameSelected > 0:
self.tableFrameBuffer[self.currentFrameSelected].pack_forget()
self.tableFrameBuffer[self.currentFrameSelected - 1].pack()
self.currentFrameSelected -= 1
def tableSelect(self):
val = self.tabVar.get()
print(self.tableList[val - 1])
try:
self.newTableWindow.destroy()
except:
pass
self.newTableWindow = Toplevel(self.master)
self.app = TablesData(self.newTableWindow, self.cursor,
self.tableList[val - 1])
def createNewTableLayout(self):
self.sqlDatatypes = ['int', 'tinyint', 'smallint', 'mediumint', 'bigint',
'float', 'double', 'decimal',
'date','datetime','timestamp','time','year',
'char','varchar','text', 'tinytext','mediumtext','longtext','enum']
self.ntRowList = []
self.ntVarList = [] ##New Table var list
self.newTableMF = Frame(self.f1) ## New table main frame
##Top frame containing the sql command
self.topFrameNT = Frame(self.newTableMF)
lable = Label(self.topFrameNT, text='SQL Command')
self.newtableSQLcommand = StringVar()
entry = Entry(self.topFrameNT, textvariable = self.newtableSQLcommand)
lable.pack(side='left')
entry.pack(side='left', fill='x', expand=True)
self.topFrameNT.pack(side='top', fill='x')
##Bottom frame containing table names and dattatypes
self.createTableFrame = Frame(self.newTableMF, bg='red') ##Bottom frame
lable = Label(self.createTableFrame, text = 'Table name')
lable.grid(column=0, row=0, sticky='w')
self.newTableName = StringVar()
entryNewTable = Entry(self.createTableFrame, textvariable = self.newTableName)
entryNewTable.grid(row=0, column=1, sticky='w')
plusButton = Button(self.createTableFrame, text = '+', command = self.nextEntryTable)
plusButton.grid(row=0, column=2)
lable = Label(self.createTableFrame, text = 'Column Name')
lable.grid(column=0, row=1, sticky= 'w')
lable = Label(self.createTableFrame, text = 'Datatype')
lable.grid(column=1, row=1, sticky= 'w')
self.rowcountNT = 1
self.nextEntryTable()
self.createTableFrame.pack(side='bottom', fill='both', expand=True)
def nextEntryTable(self):
self.rowcountNT += 1
namevar = StringVar()
cbvar = StringVar()
entry = Entry(self.createTableFrame, textvariable = namevar)
cb = ttk.Combobox(self.createTableFrame, textvariable = cbvar, values= self.sqlDatatypes,
state='readonly'
)
cb.bind("<<ComboboxSelected>>", self.datatypeSelect)
cb.bind("<Return>", self.datatypeSelect)
btn = Button(self.createTableFrame, text='Remove')
btn.bind('<Button-1>', self.deleteRowNT)
entry.grid(row=self.rowcountNT, column = 0)
cb.grid(row=self.rowcountNT, column = 1)
btn.grid(row = self.rowcountNT, column = 2)
l = [btn.winfo_id(), entry, cb, btn]
self.ntRowList.append(l)
l = [namevar, cbvar]
self.ntVarList.append(l)
def datatypeSelect(self, event):
state = list (map(lambda var: [var[0].get(), var[1].get()], self.ntVarList))
print(state)
def deleteRowNT(self, event):
bid = event.widget.winfo_id()
for rows in self.ntRowList:
if rows[0] == bid:
index = self.ntRowList.index(rows)
break
print('Row number: ', index+1)
row = self.ntRowList[index]
row[3].destroy()
row[2].destroy()
row[1].destroy()
del(self.ntRowList[index])
print('Row deleted')
class TablesData(Tables):
def __init__(self, master, cursor, table):
self.master = master
self.cursor = cursor
self.tablename = table
self.master.geometry('500x500+50+30')
self.master.title(str(table))
self.buttonFrame = Frame(self.master)
self.buttonLayoutSet()
self.buttonFrame.pack(side='bottom', fill='x')
self.topFrame = Frame(self.master)
self.scrollableFrame = Scrollable(self.topFrame)
self.entriesframe = Frame(self.scrollableFrame)
self.entriesframe.grid()
self.displayTables()
self.topFrame.pack(fill='both', side='top', anchor='w', expand=True)
def buttonLayoutSet(self):
self.delete = Button(self.buttonFrame, text='Delete', command=self.deleteClick)
self.delete.pack(side='left')
self.edit = Button(self.buttonFrame, text='Edit', command=self.editClick)
self.edit.pack(side='left')
self.insert = Button(self.buttonFrame, text='Insert', command=self.insertClick)
self.insert.pack(side='left', padx=20)
self.delete.config(state='disabled')
self.edit.config(state='disabled')
def insertClick(self):
print('Insert')
def deleteClick(self):
print('Delete')
def editClick(self):
print('Edit')
def allSelect(self):
allVal = self.allCheck.get()
for var in self.entryVarList:
var.set(allVal)
if allVal == 1:
self.delete.config(state='normal')
else:
self.delete.config(state='disabled')
self.edit.config(state='disabled')
def displayTables(self):
self.cursor.execute('DESC '+ str(self.tablename))
self.allCheck = IntVar()
cb = Checkbutton(self.entriesframe,
onvalue=1, offvalue=0,
variable = self.allCheck,
command = self.allSelect)
cb.grid(row=0, column=0)
for heading in self.cursor:
L = Label(self.entriesframe, text=heading[0])
L.grid(row=0, column = self.cursor.rowcount)
self.cursor.execute('select * from ' + str(self.tablename))
self.entryVarList = []
for tableEntries in self.cursor:
entryVar = IntVar()
cb = Checkbutton(self.entriesframe,
onvalue=1, offvalue= 0,
variable = entryVar,
command= self.selectEntry)
cb.grid(row=self.cursor.rowcount, column=0)
self.entryVarList.append(entryVar)
for val, col in zip(tableEntries, range(1,len(tableEntries) + 1)):
L = Label(self.entriesframe, text = val)
L.grid(row=self.cursor.rowcount, column = col)
self.scrollableFrame.update()
def selectEntry(self):
state = list (map(lambda var: var.get(), self.entryVarList))
if sum(state) == 0:
self.delete.config(state='disabled')
self.edit.config(state='disabled')
elif sum(state) == 1:
self.delete.config(state='normal')
self.edit.config(state='normal')
else:
self.delete.config(state='normal')
self.edit.config(state='disabled')
if len(state) == sum(state):
self.allCheck.set(1)
else:
self.allCheck.set(0)
def main():
root = Tk()
app = Scan(root)
root.mainloop()
if __name__ == '__main__':
main()

Related

How do I fix this error? self.category_id.set(row[1]), IndexError: string index out of range

I'm adding data into sqlite table and when I try to update the table, I'm getting this error 'string index not in range'.
Again when I execute the update command, all the columns gets updated except the identity column but my intention is only to update a selected row.
what I not doing right from the code below>
Your assistance will be highly appreciated.
The error is happening in the function update_record(self).
This is my code:
import tkinter
from tkinter import *
from tkinter import ttk
import tkinter.messagebox
import sqlite3
root =Tk()
root.title('Accounting App')
root.config(bg='#3d6466')
root.geometry("520x400")
root.resizable(False, False)
style = ttk.Style()
style.theme_use('alt')
style.configure("TCombobox", fieldbackground="Grey", background="Grey")
class Backend():
def __init__(self):
self.conn = sqlite3.connect('accounting.db')
self.cur = self.conn.cursor()
#self.conn.execute("""DROP TABLE IF EXISTS account_type""")
self.conn.execute("""CREATE TABLE IF NOT EXISTS account_type(
id INTEGER PRIMARY KEY,
category_id INTEGER NOT NULL,
category_type TEXT NOT NULL
)"""),
self.conn.commit()
# elf.conn.close()
# =========Account Type======
class Account_type():
def insert_account_type(self, category_id, category_type):
self.conn = sqlite3.connect('accounting.db')
self.cur = self.conn.cursor()
self.cur.execute("""INSERT INTO account_type(category_id,category_type) VALUES(?,?);""",
(category_id, category_type,))
self.conn.commit()
self.conn.close()
def view_account_type(self):
self.conn = sqlite3.connect('accounting.db')
self.cur = self.conn.cursor()
self.cur.execute("SELECT * FROM account_type")
rows = self.cur.fetchall()
self.conn.close()
return rows
acc_type = Backend.Account_type()
tb = Backend()
class Front_end():
def __init__(self, master):
# Frames
global cur
global conn
conn = sqlite3.connect('accounting.db')
cur = conn.cursor()
# Frames
self.left_frame = LabelFrame(master,bg='#3d6466', relief=SUNKEN,width=200)
self.left_frame.pack(fill = 'both',expand = YES , padx = 5,side=LEFT,anchor=NW)
self.right_frame = LabelFrame(master, bg='#3d6466', relief=SUNKEN)
self.right_frame.pack(fill = 'both',expand = YES ,side=LEFT,anchor=NW)
self.top_right_frame = LabelFrame(self.right_frame, bg='#3d6466', relief=SUNKEN,text='Details',fg='maroon')
self.top_right_frame.pack(fill=BOTH,side=TOP, anchor=NW,expand=YES)
self.top_r_inner_frame = LabelFrame(self.right_frame, bg='#3d6466', relief=SUNKEN, text='...', fg='maroon',height=10)
self.top_r_inner_frame.pack(fill=BOTH, side=TOP, anchor=SW, expand=YES)
self.bottom_right_frame = LabelFrame(self.right_frame, bg='#3d6466', relief=SUNKEN, text='Field View', fg='maroon')
self.bottom_right_frame.pack(fill=BOTH,side=TOP, anchor=SW, expand=YES)
self.my_canvas = Canvas(self.top_right_frame,bg='#3d6466')
self.my_canvas.pack(side=LEFT,fill='both', expand=YES)
# vertical configuration of scrollbar
self.yscrollbar = ttk.Scrollbar(self.top_right_frame, orient=VERTICAL, command = self.my_canvas.yview)
self.yscrollbar.pack(side=RIGHT,fill='both')
self.my_canvas.config(yscrollcommand = self.yscrollbar.set)
self.top_right_frame = Frame(self.my_canvas, bg='#3d6466', relief=SUNKEN)
self.my_canvas.create_window((0,0),window=self.top_right_frame, anchor=NW)
self.my_canvas.bind('<Configure>',lambda e:self.my_canvas.configure(scrollregion = self.my_canvas.bbox('all')))
self.side_frame = LabelFrame(self.left_frame,bg='#3d6466',relief=SUNKEN,text='Menu Buttons',fg='maroon',)
self.side_frame.pack(side=TOP,anchor=NW,expand=YES )
# Side Buttons
self.btn1 = Button(self.side_frame, text='Main Account Types', bg='#3d6466', font=('cambria', 12), anchor=W,
fg='white', width=18,height=2,command=self.main_account)
self.btn1.grid(row=0, column=0, sticky=W)
def main_account(self):
# variables
self.category_id = StringVar()
self.category_type = StringVar()
self.category_search =StringVar()
# functions
def add_main_accounts(self):
if self.category_id.get() == "":
tkinter.messagebox.showinfo('All fields are required')
else:
Backend.Account_type.insert_account_type(self,
self.category_id.get(),self.category_type.get())
tkinter.messagebox.showinfo('Entry successful')
def display_account_types(self):
self.trv.delete(*self.trv.get_children())
for rows in Backend.Account_type.view_account_type(self):
self.trv.insert("", END, values=rows)
def get_account_type(e):
selected_row = self.trv.focus()
data = self.trv.item(selected_row)
row = data["values"]
"""Grab items and send them to entry fields"""
self.category_id.set(row[1])
self.category_type.set(row[2])
def clear(self):
self.category_id.set("")
self.category_type.set("")
**def update_record(self):
selected = self.trv.focus()
self.trv.item(selected, values=(
self.category_id.get(), self.category_type.get()))
conn = sqlite3.connect("accounting.db")
cur = conn.cursor()
if self.category_id.get() == "" or self.category_type.get() == "" :
tkinter.messagebox.showinfo('All fields are required!')
return
update_record = tkinter.messagebox.askyesno('Confirm please',
'Do you want to update records?')
if update_record > 0:
cur.execute(
"UPDATE account_type SET category_id=:cat_id, category_type=:type",
{'cat_id': self.category_id.get(), 'type': self.category_type.get()})
tkinter.messagebox.showinfo('Record update successful!')
conn.commit()**
# call the function for Clearing the fields
clear(self)
conn.close()
"""=================TreeView==============="""
# Scrollbars
ttk.Style().configure("Treeview", background = "#3d6466", foreground = "white", fieldbackground = "grey")
scroll_x = Scrollbar(self.bottom_right_frame, orient = HORIZONTAL)
scroll_x.pack(side = BOTTOM, fill = X)
scroll_y = Scrollbar(self.bottom_right_frame, orient = VERTICAL)
scroll_y.pack(side = RIGHT, fill = Y)
# Treeview columns & setting scrollbars
self.trv = ttk.Treeview(self.bottom_right_frame, height=5, columns=
('id','category_id', 'category_type'), xscrollcommand = scroll_x.set, yscrollcommand = scroll_y.set)
# Treeview style configuration
ttk.Style().configure("Treeview", background = "#3d6466", foreground = "white", fieldbackground = "#3d6466")
# Configure vertical and Horizontal scroll
scroll_x.config(command = self.trv.xview)
scroll_y.config(command = self.trv.yview)
# Treeview Headings/columns
self.trv.heading('id', text = 'NO')
self.trv.heading('category_id', text = 'Category ID')
self.trv.heading('category_type', text = 'Category Type')
self.trv['show'] = 'headings'
# Treeview columns width
self.trv.column('id', width = 50)
self.trv.column('category_id', width = 70)
self.trv.column('category_type', width = 90)
self.trv.pack(fill = BOTH, expand = YES,anchor = NW)
# Binding Treeview with data
self.trv.bind('<<TreeviewSelect>>',get_account_type) # trv.bind('<Double-1>',"")
# Account Types Labels
self.lbl1 = Label(self.top_right_frame,text = 'Category ID',anchor = W,width=12,font = ('cambria',13,),bg = '#3d6466')
self.lbl1.grid(row = 0,column = 0,pady = 5)
self.lbl1 = Label(self.top_right_frame, text='Category Type', anchor=W, width=12, font=('cambria', 13,), bg='#3d6466')
self.lbl1.grid(row=1, column=0, pady=5)
self.lbl2 = Label(self.top_right_frame, text='Search Account', anchor=W, width=12, font=('cambria', 13,),
bg='#3d6466')
self.lbl2.grid(row=6, column=0, pady=5)
# Account Type Entries
self.entry1 = Entry(self.top_right_frame,textvariable = self.category_id,font = ('cambria',13,),bg = 'Grey',width=14)
self.entry1.grid(row = 0,column=1,sticky = W,padx = 4,columnspan=2)
self.entry1 = Entry(self.top_right_frame, textvariable=self.category_type, font=('cambria', 13,), bg='Grey', width=14)
self.entry1.grid(row=1, column=1, sticky=W, padx=4, columnspan=2)
self.entry2 = Entry(self.top_right_frame, textvariable=self.category_search, font=('cambria', 13,), bg='Grey', width=14)
self.entry2.grid(row=6, column=1, sticky=W, padx=4, columnspan=2)
# Buttons
self.btn_1 = Button(self.top_right_frame,text='Add',font=('cambria',12,'bold'),bg='#3d6466',
activebackground='green', fg = 'white',width=12,height = 1,relief=RAISED,
command = lambda :[add_main_accounts(self),display_account_types(self),clear(self)])
self.btn_1.grid(row = 3,column = 0,pady=6, padx=6)
self.btn_2 = Button(self.top_right_frame, text = 'View',command=lambda :[display_account_types(self),clear(self)],
font=('cambria', 12, 'bold'), bg = '#3d6466', activebackground='green',
fg ='white', width=12, height = 1, relief=RAISED)
self.btn_2.grid(row = 3, column=1,padx=0)
self.btn_3 = Button(self.top_right_frame, text = 'Update', command= lambda :[update_record(self),
display_account_types(self)],font=('cambria', 12, 'bold'), bg = '#3d6466',
activebackground = 'green', fg='white', width = 12, height = 1, relief=RAISED)
self.btn_3.grid(row = 4, column = 0,pady=6,padx=10)
# calling the class
app = Front_end(root)
root.mainloop()
Your update function updates all the records exist. To avoid this you should use WHERE. Here its fixed version
def update_record(self):
selected = self.trv.focus()
oldValues = self.trv.item(selected)["values"]
self.trv.item(selected, values=(oldValues[0],
self.category_id.get(), self.category_type.get()))
conn = sqlite3.connect("accounting.db")
cur = conn.cursor()
if self.category_id.get() == "" or self.category_type.get() == "" :
tkinter.messagebox.showinfo('All fields are required!')
return
update_record = tkinter.messagebox.askyesno('Confirm please',
'Do you want to update employee records?')
if update_record > 0:
cur.execute(
"UPDATE account_type SET category_id=:cat_id, category_type=:type WHERE id=:id_value",
{'cat_id': self.category_id.get(), 'type': self.category_type.get(), "id_value": oldValues[0]})
tkinter.messagebox.showinfo('Record update successful!')
conn.commit()
# call the function for Clearing the fields
clear(self)
conn.close()
We used selected rows idx etc.
However your error string index out of range is not about this. The function above going to fix your record update problem. Your error is because it tries to show a record value but after refreshed table, nothing is selected. So it returns empty.
def get_account_type(e):
selected_row = self.trv.focus()
data = self.trv.item(selected_row)
row = data["values"]
if(row == ""):
return
"""Grab items and send them to entry fields"""
self.category_id.set(row[1])
self.category_type.set(row[2])
Now if row is just an empty string, function stops executing and you get no errors.

Python Tkinter Spinboxes return value using for loops

I'm trying to use X many spin boxes as there are items in a list - so have put them on screen using a for loop.
However, I don't seem able to get them to return their value when I click a button.
aStarter = ["Starter 1", "Starter 2", "Starter 3"]
def getOrders():
aStarterOrder = []
aMainOrder = []
aDessertOrder = []
for i in aStarterQuantity:
aStarterOrder.append(StarterQuantity.get())
print(aStarterOrder)
aStarterQuantity = []
StarterQuantity = IntVar()
for i in range(len(aStarter)):
lbl = Label(self, text = aStarter[i]).grid(column = 0, row = 2 + i)
StarterQuantity = Spinbox(self, from_=0, to=20, width=5, command=callback, font=Font(family='Helvetica', size=20, weight='bold')).grid(column = 1, row = 2 + i)
print(StarterQuantity.get())
I have tried appending the StarterQuantity to an array inside of the for loop:
aStarterQuantity = []
StarterQuantity = IntVar()
for i in range(len(aStarter)):
lbl = Label(self, text = aStarter[i]).grid(column = 0, row = 2 + i)
StarterQuantity = Spinbox(self, from_=0, to=20, width=5, command=callback, font=Font(family='Helvetica', size=20, weight='bold')).grid(column = 1, row = 2 + i)
aStarterQuantity.append(StarterQuantity.get())
This returns a None Type error - I can't seem to get the value out of the spin box.
Any ideas?
Here is the full code (it's very much an early WIP!)
from tkinter import *
from tkinter.font import Font
import sqlite3
DatabaseFile = 'RMS.db'
connDatabase = sqlite3.connect(DatabaseFile)
#Creating a cursor to run SQL Commands
DatabaseSelect = connDatabase.cursor()
#Selecting all Menu Data
DatabaseSelect.execute("SELECT * FROM MENU")
MenuData = DatabaseSelect.fetchall()
class Main(Tk): #This sets up the initial Frame in a Window called Main
def __init__(self): #This creates a controller to use the Frames
Tk.__init__(self) #This creates a Window within the controller
self._frame = None #This sets the frame to have a value of None - this makes sure the main Window doesn't get destroyed by the switch frame function
self.switch_frame(Home)
def switch_frame(self, frame_class): #This function is used to switch frames. Self is the master frame, frame_class is the name of the Class (page) being passed int
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy() #Destroy any frames except the master
self._frame = new_frame #Make a new frame
self._frame.grid(column=0, row=0) #Put the frame in the top left
class Home(Frame):
def __init__(self, master):
Frame.__init__(self, master)
Label(self, text="The White Horse").grid(column = 0, row = 0)
btnPage1 = Button(self, text="Orders", command=lambda: master.switch_frame(Orders)).grid(column = 1, row = 0)
#Making a blank page with a return home button
class Orders(Frame): #This sets up a class called Page1 - Each new page will need a new class.
def __init__(self, master): #This sets up a controller to put things into the Frame
Frame.__init__(self, master) #Make the frame using the controller
#Get list of Starters from Menu Data
aStarter = ["Starter 1", "Starter 2", "Starter 3"]
aMain = []
aDessert = []
for i in MenuData:
if i[3] == "Starters":
aStarter.append(i[1])
if i[3] == "Main":
aMain.append(i[1])
if i[3] == "Dessert":
aDessert.append(i[1])
def getOrders():
aStarterOrder = []
aMainOrder = []
aDessertOrder = []
for i in aStarterQuantity:
aStarterOrder.append(StarterQuantity.get())
print(aStarterOrder)
def callback():
print(StarterQuantity.get())
#Starter Section
boxes = []
aStarterQuantity = []
StarterQuantity = IntVar()
for i in range(len(aStarter)):
lbl = Label(self, text = aStarter[i]).grid(column = 0, row = 2 + i)
StarterQuantity = Spinbox(self, from_=0, to=20, width=5, command=callback, font=Font(family='Helvetica', size=20, weight='bold')).grid(column = 1, row = 2 + i)
aStarterQuantity.append(StarterQuantity.get())
#Mains Sections
for i in range(len(aMain)):
lbl = Label(self, text = aMain[i]).grid(column = 6, row = 2 + i)
MainQuantity = Spinbox(self, from_=0, to=20, width=5, font=Font(family='Helvetica', size=20, weight='bold')).grid(column = 7, row = 2 + i)
#Dessert Section
for i in range(len(aDessert)):
lbl = Label(self, text = aDessert[i]).grid(column = 12, row = 2 + i)
DessertQuantity = Spinbox(self, from_=0, to=20, width=5, font=Font(family='Helvetica', size=20, weight='bold')).grid(column = 13, row = 2 + i)
btnHome = Button(self, text="Home", command=lambda: master.switch_frame(Home)).grid(column = 0, row = 1) #Add a Button
btnSubmitEntries = Button(self, text = "Submit", command = getOrders).grid(column = 0, row= 20)
Main = Main()
Main.geometry("1200x800")
Main.mainloop()
The problem seems to be that the grid method doesn't return anything, so StarterQuantity gets assigned None i.e. the default return value for a function.
for i in range(len(aStarter)):
lbl = Label(self, text=aStarter[i])
lbl.grid(column=0, row=2 + i)
sq_font = Font(family='Helvetica',
size=20,
weight='bold')
StarterQuantity = Spinbox(self,
from_=0,
to=20,
width=5, command=callback,
font=sq_font)
StarterQuantity.grid(column=1, row=2 + i)
aStarterQuantity.append(StarterQuantity.get())
This works in my case. (Pulled out the Font argument for Spinbox to increase readability on mobile).
Unrelated note; I don't know what code style you prefer/have to maintain and it is up to you of course, but I thought it might be helpful to mention that the naming style convention in Python (PEP8) is to use CamelCase for class names, lower_case_w_underscores for variable names and functions/methods, and SCREAMING_SNAKE for constants.

How to make text widget static

After changing the font size of the widget text increases , how to make it static?
I'm giving you all the code so you can run the program. So do not swear
from tkinter import*
import tkinter as tk
from tkinter import Toplevel, Listbox, StringVar, BooleanVar, TclError
from tkinter import filedialog, scrolledtext,Menu,END,messagebox
from tkinter.ttk import Checkbutton, Frame, Label, Button, Scrollbar, Style, Entry
from tkinter.font import families, Font
from locale import getdefaultlocale
import PIL
from PIL import Image, ImageTk
__version__ = "2.0.2"
# --- translation
EN = {"Cancel": "Cancel", "Bold": "Bold", "Italic": "Italic",
"Underline": "Underline", "Overstrike": "Strikethrough"}
FR = {"Cancel": "Annuler", "Bold": "Gras", "Italic": "Italique",
"Underline": "Souligné", "Overstrike": "Barré"}
LANGUAGES = {"fr": FR, "en": EN}
if getdefaultlocale()[0][:2] == "fr":
TR = LANGUAGES["fr"]
else:
TR = LANGUAGES["en"]
class FontChooser(Toplevel):
""".Font chooser dialog."""
def __init__(self, master, font_dict={}, text="Abcd", title="Font Chooser",
**kwargs):
"""
Create a new FontChooser instance.
Arguments:
master: master window
font_dict: dictionnary, like the one returned by the .actual
method of a Font object:
{'family': 'DejaVu Sans',
'overstrike': False,
'size': 12,
'slant': 'italic' or 'roman',
'underline': False,
'weight': 'bold' or 'normal'}
text: text to be displayed in the preview label
title: window title
**kwargs: additional keyword arguments to be passed to
Toplevel.__init__
"""
Toplevel.__init__(self, master, **kwargs)
self.title(title)
self.resizable(False, False)
self.protocol("WM_DELETE_WINDOW", self.quit)
self._validate_family = self.register(self.validate_font_family)
self._validate_size = self.register(self.validate_font_size)
# --- variable storing the chosen font
self.res = ""
style = Style(self)
style.configure("prev.TLabel", background="white")
bg = style.lookup("TLabel", "background")
self.configure(bg=bg)
# --- family list
self.fonts = list(set(families()))
self.fonts.append("TkDefaultFont")
self.fonts.sort()
for i in range(len(self.fonts)):
self.fonts[i] = self.fonts[i].replace(" ", "\ ")
max_length = int(2.5 * max([len(font) for font in self.fonts])) // 3
self.sizes = ["%i" % i for i in (list(range(6, 17)) + list(range(18, 32, 2)))]
# --- font default
font_dict["weight"] = font_dict.get("weight", "normal")
font_dict["slant"] = font_dict.get("slant", "roman")
font_dict["underline"] = font_dict.get("underline", False)
font_dict["overstrike"] = font_dict.get("overstrike", False)
font_dict["family"] = font_dict.get("family",
self.fonts[0].replace('\ ', ' '))
font_dict["size"] = font_dict.get("size", 10)
# --- creation of the widgets
# ------ style parameters (bold, italic ...)
options_frame = Frame(self, relief='groove', borderwidth=2)
self.font_family = StringVar(self, " ".join(self.fonts))
self.font_size = StringVar(self, " ".join(self.sizes))
self.var_bold = BooleanVar(self, font_dict["weight"] == "bold")
b_bold = Checkbutton(options_frame, text=TR["Bold"],
command=self.toggle_bold,
variable=self.var_bold)
b_bold.grid(row=0, sticky="w", padx=4, pady=(4, 2))
self.var_italic = BooleanVar(self, font_dict["slant"] == "italic")
b_italic = Checkbutton(options_frame, text=TR["Italic"],
command=self.toggle_italic,
variable=self.var_italic)
b_italic.grid(row=1, sticky="w", padx=4, pady=2)
self.var_underline = BooleanVar(self, font_dict["underline"])
b_underline = Checkbutton(options_frame, text=TR["Underline"],
command=self.toggle_underline,
variable=self.var_underline)
b_underline.grid(row=2, sticky="w", padx=4, pady=2)
self.var_overstrike = BooleanVar(self, font_dict["overstrike"])
b_overstrike = Checkbutton(options_frame, text=TR["Overstrike"],
variable=self.var_overstrike,
command=self.toggle_overstrike)
b_overstrike.grid(row=3, sticky="w", padx=4, pady=(2, 4))
# ------ Size and family
self.var_size = StringVar(self)
self.entry_family = Entry(self, width=max_length, validate="key",
validatecommand=(self._validate_family, "%d", "%S",
"%i", "%s", "%V"))
self.entry_size = Entry(self, width=4, validate="key",
textvariable=self.var_size,
validatecommand=(self._validate_size, "%d", "%P", "%V"))
self.list_family = Listbox(self, selectmode="browse",
listvariable=self.font_family, highlightthickness=0, exportselection=False, width=max_length)
self.list_size = Listbox(self, selectmode="browse",
listvariable=self.font_size, highlightthickness=0, exportselection=False, width=4)
scroll_family = Scrollbar(self, orient='vertical', command=self.list_family.yview)
scroll_size = Scrollbar(self, orient='vertical', command=self.list_size.yview)
self.preview_font = Font(self, **font_dict)
if len(text) > 30:
text = text[:30]
self.preview = Label(self, relief="groove", style="prev.TLabel", text=text, font=self.preview_font, anchor="center")
self.list_family.configure(yscrollcommand=scroll_family.set)
self.list_size.configure(yscrollcommand=scroll_size.set)
self.entry_family.insert(0, font_dict["family"])
self.entry_family.selection_clear()
self.entry_family.icursor("end")
self.entry_size.insert(0, font_dict["size"])
try:
i = self.fonts.index(self.entry_family.get().replace(" ", "\ "))
except ValueError:
i = 0
self.list_family.selection_clear(0, "end")
self.list_family.selection_set(i)
self.list_family.see(i)
try:
i = self.sizes.index(self.entry_size.get())
self.list_size.selection_clear(0, "end")
self.list_size.selection_set(i)
self.list_size.see(i)
except ValueError:
pass
self.entry_family.grid(row=0, column=0, sticky="ew", pady=(10, 1), padx=(10, 0))
self.entry_size.grid(row=0, column=2, sticky="ew", pady=(10, 1), padx=(10, 0))
self.list_family.grid(row=1, column=0, sticky="nsew", pady=(1, 10), padx=(10, 0))
self.list_size.grid(row=1, column=2, sticky="nsew", pady=(1, 10), padx=(10, 0))
scroll_family.grid(row=1, column=1, sticky='ns', pady=(1, 10))
scroll_size.grid(row=1, column=3, sticky='ns', pady=(1, 10))
options_frame.grid(row=0, column=4, rowspan=2, padx=10, pady=10, ipadx=10)
self.preview.grid(row=2, column=0, columnspan=5, sticky="eswn", padx=10, pady=(0, 10), ipadx=4, ipady=4)
button_frame = Frame(self)
button_frame.grid(row=3, column=0, columnspan=5, pady=(0, 10), padx=10)
Button(button_frame, text="Ok", command=self.ok).grid(row=0, column=0, padx=4, sticky='ew')
Button(button_frame, text=TR["Cancel"], command=self.quit).grid(row=0, column=1, padx=4, sticky='ew')
self.list_family.bind('<<ListboxSelect>>', self.update_entry_family)
self.list_size.bind('<<ListboxSelect>>', self.update_entry_size, add=True)
self.list_family.bind("<KeyPress>", self.keypress)
self.entry_family.bind("<Return>", self.change_font_family)
self.entry_family.bind("<Tab>", self.tab)
self.entry_size.bind("<Return>", self.change_font_size)
self.entry_family.bind("<Down>", self.down_family)
self.entry_size.bind("<Down>", self.down_size)
self.entry_family.bind("<Up>", self.up_family)
self.entry_size.bind("<Up>", self.up_size)
self.bind_class("TEntry", "<Control-a>", self.select_all)
self.wait_visibility(self)
self.grab_set()
self.entry_family.focus_set()
self.lift()
def select_all(self, event):
event.widget.selection_range(0, "end")
def keypress(self, event):
key = event.char.lower()
l = [i for i in self.fonts if i[0].lower() == key]
if l:
i = self.fonts.index(l[0])
self.list_family.selection_clear(0, "end")
self.list_family.selection_set(i)
self.list_family.see(i)
self.update_entry_family()
def up_family(self, event):
try:
i = self.list_family.curselection()[0]
self.list_family.selection_clear(0, "end")
if i <= 0:
i = len(self.fonts)
self.list_family.see(i - 1)
self.list_family.select_set(i - 1)
except TclError:
self.list_family.selection_clear(0, "end")
i = len(self.fonts)
self.list_family.see(i - 1)
self.list_family.select_set(i - 1)
self.list_family.event_generate('<<ListboxSelect>>')
def up_size(self, event):
"""Navigate in the size listbox with up key."""
try:
s = self.var_size.get()
if s in self.sizes:
i = self.sizes.index(s)
elif s:
sizes = list(self.sizes)
sizes.append(s)
sizes.sort(key=lambda x: int(x))
i = sizes.index(s)
else:
i = 0
self.list_size.selection_clear(0, "end")
if i <= 0:
i = len(self.sizes)
self.list_size.see(i - 1)
self.list_size.select_set(i - 1)
except TclError:
i = len(self.sizes)
self.list_size.see(i - 1)
self.list_size.select_set(i - 1)
self.list_size.event_generate('<<ListboxSelect>>')
def down_family(self, event):
"""Navigate in the family listbox with down key."""
try:
i = self.list_family.curselection()[0]
self.list_family.selection_clear(0, "end")
if i >= len(self.fonts):
i = -1
self.list_family.see(i + 1)
self.list_family.select_set(i + 1)
except TclError:
self.list_family.selection_clear(0, "end")
self.list_family.see(0)
self.list_family.select_set(0)
self.list_family.event_generate('<<ListboxSelect>>')
def down_size(self, event):
"""Navigate in the size listbox with down key."""
try:
s = self.var_size.get()
if s in self.sizes:
i = self.sizes.index(s)
elif s:
sizes = list(self.sizes)
sizes.append(s)
sizes.sort(key=lambda x: int(x))
i = sizes.index(s) - 1
else:
s = len(self.sizes) - 1
self.list_size.selection_clear(0, "end")
if i < len(self.sizes) - 1:
self.list_size.selection_set(i + 1)
self.list_size.see(i + 1)
else:
self.list_size.see(0)
self.list_size.select_set(0)
except TclError:
self.list_size.selection_set(0)
self.list_size.event_generate('<<ListboxSelect>>')
def toggle_bold(self):
"""Update font preview weight."""
b = self.var_bold.get()
self.preview_font.configure(weight=["normal", "bold"][b])
def toggle_italic(self):
"""Update font preview slant."""
b = self.var_italic.get()
self.preview_font.configure(slant=["roman", "italic"][b])
def toggle_underline(self):
"""Update font preview underline."""
b = self.var_underline.get()
self.preview_font.configure(underline=b)
def toggle_overstrike(self):
"""Update font preview overstrike."""
b = self.var_overstrike.get()
self.preview_font.configure(overstrike=b)
def change_font_family(self, event=None):
"""Update font preview family."""
family = self.entry_family.get()
if family.replace(" ", "\ ") in self.fonts:
self.preview_font.configure(family=family)
def change_font_size(self, event=None):
"""Update font preview size."""
size = int(self.var_size.get())
self.preview_font.configure(size=size)
def validate_font_size(self, d, ch, V):
"""Validation of the size entry content."""
l = [i for i in self.sizes if i[:len(ch)] == ch]
i = None
if l:
i = self.sizes.index(l[0])
elif ch.isdigit():
sizes = list(self.sizes)
sizes.append(ch)
sizes.sort(key=lambda x: int(x))
i = min(sizes.index(ch), len(self.sizes))
if i is not None:
self.list_size.selection_clear(0, "end")
self.list_size.selection_set(i)
deb = self.list_size.nearest(0)
fin = self.list_size.nearest(self.list_size.winfo_height())
if V != "forced":
if i < deb or i > fin:
self.list_size.see(i)
return True
if d == '1':
return ch.isdigit()
else:
return True
def tab(self, event):
"""Move at the end of selected text on tab press."""
self.entry_family = event.widget
self.entry_family.selection_clear()
self.entry_family.icursor("end")
return "break"
def validate_font_family(self, action, modif, pos, prev_txt, V):
"""Completion of the text in the entry with existing font names."""
if self.entry_family.selection_present():
sel = self.entry_family.selection_get()
txt = prev_txt.replace(sel, '')
else:
txt = prev_txt
if action == "0":
txt = txt[:int(pos)] + txt[int(pos) + 1:]
return True
else:
txt = txt[:int(pos)] + modif + txt[int(pos):]
ch = txt.replace(" ", "\ ")
l = [i for i in self.fonts if i[:len(ch)] == ch]
if l:
i = self.fonts.index(l[0])
self.list_family.selection_clear(0, "end")
self.list_family.selection_set(i)
deb = self.list_family.nearest(0)
fin = self.list_family.nearest(self.list_family.winfo_height())
index = self.entry_family.index("insert")
self.entry_family.delete(0, "end")
self.entry_family.insert(0, l[0].replace("\ ", " "))
self.entry_family.selection_range(index + 1, "end")
self.entry_family.icursor(index + 1)
if V != "forced":
if i < deb or i > fin:
self.list_family.see(i)
return True
else:
return False
def update_entry_family(self, event=None):
"""Update family entry when an item is selected in the family listbox."""
# family = self.list_family.get("#%i,%i" % (event.x , event.y))
family = self.list_family.get(self.list_family.curselection()[0])
self.entry_family.delete(0, "end")
self.entry_family.insert(0, family)
self.entry_family.selection_clear()
self.entry_family.icursor("end")
self.change_font_family()
def update_entry_size(self, event):
"""Update size entry when an item is selected in the size listbox."""
# size = self.list_size.get("#%i,%i" % (event.x , event.y))
size = self.list_size.get(self.list_size.curselection()[0])
self.var_size.set(size)
self.change_font_size()
def ok(self):
"""Validate choice."""
self.res = self.preview_font.actual()
self.quit()
def get_res(self):
"""Return chosen font."""
return self.res
def quit(self):
self.destroy()
def askfont(master=None, text="Abcd", title="Font Chooser", **font_args):
chooser = FontChooser(master, font_args, text, title)
chooser.wait_window(chooser)
return chooser.get_res()
def edit_font():
font = askfont(root, title="Choose a font")
if font:
font['family'] = font['family'].replace(' ', '\ ')
font_str = "%(family)s %(size)i %(weight)s %(slant)s" % font
if font['underline']:
font_str += ' underline'
if font['overstrike']:
font_str += ' overstrike'
text.configure(font=font_str)
root=tk.Tk()
root.geometry("1423x800")
# added weights so the widget resizes correctly with window
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
image = ImageTk.PhotoImage(file="0.png")
lab=tk.Label(root, image = image)
lab.grid(row=0, column=0)
text=tk.Text(root,width = 60,height=15, font=Font(family="Helvetica", size=10))
text.grid(row=0, column=0)
king=tk.Menu(root)
root.config(menu=king)
view=tk.Menu(king, tearoff=0)
view2=tk.Menu(view, tearoff=0)
view2.add_command(label='Font',command=edit_font)
view.add_cascade(label='Text', menu=view2)
king.add_cascade(label='View', menu=view)
root.mainloop()
This is the code you will most likely need to fix my problem:
def askfont(master=None, text="Abcd", title="Font Chooser", **font_args):
chooser = FontChooser(master, font_args, text, title)
chooser.wait_window(chooser)
return chooser.get_res()
def edit_font():
font = askfont(root, title="Choose a font")
if font:
font['family'] = font['family'].replace(' ', '\ ')
font_str = "%(family)s %(size)i %(weight)s %(slant)s" % font
if font['underline']:
font_str += ' underline'
if font['overstrike']:
font_str += ' overstrike'
text.configure(font=font_str)
root=tk.Tk()
root.geometry("1423x800")
# added weights so the widget resizes correctly with window
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
image = ImageTk.PhotoImage(file="0.png")
lab=tk.Label(root, image = image)
lab.grid(row=0, column=0)
text=tk.Text(root,width = 60,height=15, font=Font(family="Helvetica", size=10))
text.grid(row=0, column=0)
king=tk.Menu(root)
root.config(menu=king)
view=tk.Menu(king, tearoff=0)
view2=tk.Menu(view, tearoff=0)
view2.add_command(label='Font',command=edit_font)
view.add_cascade(label='Text', menu=view2)
king.add_cascade(label='View', menu=view)
root.mainloop()
This will probably include setting the frame size and frame, as well as banning distribution, one of my friends said. Hope this helps you
If you give the Text widget a fixed height and width and wrap it in a Frame with the same width and height and use grid_propagate(False), when the text is made bigger the Text widget stays the same size.
import tkinter as tk
def fontUp():
text.config(font = ("30"))
root = tk.Tk()
root.geometry("800x800")
frm = tk.Frame(root, height = 500, width = 500)
frm.grid(row = 0, column = 0)
frm.grid_propagate(False)
text = tk.Text(frm, height = 500, width = 500)
text.grid(row = 0, column = 0)
btn = tk.Button(root, text="Font bigger", command = fontUp)
btn.grid(row = 2, column = 0)

How can i erase contents in a Label?

Sorry for the mess
so I am making a seating chart, and I cant seem to get it working properly... again. I am trying to make the label reset every time i press the run button, any ideas?
#commands: add name , Run
#imports
import random
from time import sleep
from tkinter import *
#Console and background Handlers
Tables = 6
Names = []
def AddNames():
NewNames = e.get("1.0", 'end -1c')
if NewNames in Names:
print("Name Already exists")
elif NewNames == "":
print("Empty")
else:
Names.append(NewNames)
print(Names)
e.delete(1.0, END)
def Random():
RandomNum = random.randrange(Tables)
if RandomNum == 0:
RandomNum = random.randrange(Tables)
return RandomNum
def run():
X = 0
for i in Names:
#print(Names[X])
print("Table: " + str(Random()))
X += 1
#text = Label(popup, text = "")
text = Label(popup, text= Names[X] + "\n" + "Table: " + str(Random()))
text.pack()
#GUI Handler
root = Tk()
root.geometry("1024x768")
e = Text(root, bd = 10, font=("Comic Sans MS", 50) ,width = 15, height = 2)
e.pack()
popup = Toplevel()
popup.title("Seating Chart")
AddNameButton = Button(root, text = ("Add Name"), width = 15, height = 5, command = AddNames)
AddNameButton.pack()
RunButton = Button(root, text = ("Run"), width = 15, height = 5, command = run)
RunButton.pack()
root.mainloop()
I am trying to reset text every time the user presses the run button
import tkinter
from tkinter import ttk
import random
class MyApp:
def __init__(self):
self.root = tkinter.Tk()
self.seatwindow = None
self.root.title('Add Names')
self.currentname = tkinter.StringVar()
self._maxtables = tkinter.StringVar()
self.addednames = []
self.commandframe = ttk.Labelframe(self.root, text='Commands')
self.nameentry = ttk.Entry(self.root, textvariable=self.currentname)
self.addbutton = ttk.Button(self.root, text='Add Name', command=self.addname)
self.maxtablabel = ttk.Label(self.root, text='Tables: ')
self.maxtabentry = ttk.Entry(self.root, textvariable=self._maxtables)
self.genbutton = ttk.Button(self.commandframe, text='Run', command=self.generate)
self.resetbutton = ttk.Button(self.commandframe, text='Reset', command=self.reset)
self._maxtables.set('6')
self.nameentry.grid(row=0, column=0)
self.addbutton.grid(row=0, column=1, sticky='nsew')
self.maxtabentry.grid(row=1, column=1, sticky='nsw')
self.maxtablabel.grid(row=1, column=0, sticky='nse')
self.genbutton.grid(row=0, column=0, sticky='nsew')
self.resetbutton.grid(row=0, column=1, sticky='nsew')
self.commandframe.grid(row=2, column=0, columnspan=2, sticky='nsew')
self.nameentry.bind('<Return>', self.addname)
self.root.bind('<Control-Return>', self.generate)
def addname(self, event=None):
name = self.currentname.get()
if not(name == '' or name in self.addednames):
self.addednames.append(name)
self.currentname.set('')
else:
self.currentname.set('Name already added!')
def generate(self, event=None):
if not self.seatwindow == None:
self.seatwindow.destroy()
self.currentname.set('')
self.seatwindow = tkinter.Toplevel()
random.shuffle(self.addednames)
tables = []
for i in range(self.maxtables):
tableframe = ttk.Labelframe(self.seatwindow, text='Table ' + str(i + 1) + ':')
tableframe.grid(column=i, row=0, sticky='nsew')
tables.append(tableframe)
for index, name in enumerate(self.addednames):
namelabel = ttk.Label(tables[index%self.maxtables], text=name)
namelabel.grid(column=0, row=index//self.maxtables + 1)
def reset(self):
self.currentname.set('')
self.maxtables = 6
self.addednames = []
def run(self):
self.root.mainloop()
#property
def maxtables(self):
return int(self._maxtables.get())
MyApp().run()

Python treeview and grid

The problem is that when some objects are being created in the double click subroutine the grid goes messed up. The tree view expands a bit to the right and labels and buttons which are suppose to go in column 1 look like they are in column 3(went off button above tree view which is in column 3). Also when I try making a button it puts it above the tree view no matter its row.
Code:
from tkinter import *
import os
import datetime
import sqlite3
from tkinter.ttk import Combobox,Treeview,Scrollbar
class Application(Frame):
""" Binary to Decimal """
def __init__(self, master):
""" Initialize the frame. """
super(Application, self).__init__(master)
self.grid()
self.create_GUI()
def Quit(self):
self.master.destroy()
def create_GUI(self):
self.title_lbl = Label(self, text = "Students")
self.title_lbl.grid(row = 0, column = 2)
self.fn_lbl = Label(self, text = "First Name:")
self.fn_lbl.grid(row = 1 , column = 1)
self.fn_txt = Entry(self)
self.fn_txt.grid(row = 1, column = 2)
self.ln_lbl =Label(self, text = "Last Name:")
self.ln_lbl.grid(row = 2, column = 1)
self.ln_txt = Entry(self)
self.ln_txt.grid(row = 2, column = 2)
self.q_btn = Button(self, text = "Back",padx=80,pady=10, command = lambda: self.Quit)
self.q_btn.grid(row = 3, column = 0)
self.s_btn = Button(self, text = "search",padx=80,pady=10, command = lambda: self.search())
self.s_btn.grid(row = 3,column = 3)
self.tree = Treeview(self.master,height = 6)
self.tree["columns"] = ("StudentID","First Name","Last Name")#,"House Number", "Street Name", "Town Or City Name","PostCode","MobilePhoneNumber")
self.tree.column("StudentID",width = 20)
self.tree.column("First Name",width = 40)
self.tree.column("Last Name", width = 40)
## self.tree.column("House Number", width = 60)
## self.tree.column("Street Name", width = 60)
## self.tree.column("Town Or City Name", width = 60)
## self.tree.column("PostCode", width = 60)
## self.tree.column("MobilePhoneNumber", width = 60)
self.tree.heading("StudentID",text="StudentID")
self.tree.heading("First Name",text="First Name")
self.tree.heading("Last Name",text="Last Name")
## self.tree.heading("House Number",text="House Number")
## self.tree.heading("Street Name",text="Street Name")
## self.tree.heading("Town Or City Name",text="Town Or City Name")
## self.tree.heading("PostCode",text="PostCode")
## self.tree.heading("MobilePhoneNumber",text="MobilePhoneNumber")
self.tree["show"] = "headings"
yscrollbar = Scrollbar(self.master, orient='vertical', command=self.tree.yview)
xscrollbar = Scrollbar(self.master, orient='horizontal', command=self.tree.xview)
self.tree.configure(yscroll=yscrollbar.set, xscroll=xscrollbar.set)
yscrollbar.grid(row=4, column=3, padx=2, pady=2, sticky=NS)
self.tree.grid(row=4,column=0,columnspan =5, padx=2,pady=2,sticky =NSEW)
self.tree.bind("<Double-1>",lambda event :self.OnDoubleClick(event))
def OnDoubleClick(self, event):
curItem = self.tree.focus()
contents =(self.tree.item(curItem))
StudentDetails = contents['values']
print(StudentDetails)
self.tStudentID=StringVar()
self.tFirstName = StringVar()
self.tLastName = StringVar()
self.tHouseNumber = StringVar()
self.tStreetName = StringVar()
self.tTownOrCityName = StringVar()
self.tPostCode = StringVar()
self.tEmail = StringVar()
self.tMobilePhoneNumber = StringVar()
self.tStudentID.set(StudentDetails[0])
self.tFirstName.set(StudentDetails[1])
self.tLastName.set(StudentDetails[2])
self.tHouseNumber.set(StudentDetails[3])
self.tStreetName.set(StudentDetails[4])
self.tTownOrCityName.set(StudentDetails[5])
self.tPostCode.set(StudentDetails[6])
self.tEmail.set(StudentDetails[7])
self.tMobilePhoneNumber.set(StudentDetails[8])
self.inst_lbl0 = Label(self.master, text = "Student ID").grid(row=5,column=0,sticky=W)
self.NStudentID = Label(self.master, textvariable=self.tStudentID).grid(row =5,column=1,stick=W)
self.inst_lbl1 = Label(self.master, text = "First Name").grid(row=6,column=0,sticky=W)
self.NFirstName = Entry(self.master, textvariable=self.tFirstName).grid(row =6,column=1,stick=W)
self.inst_lbl2 = Label(self.master, text = "Last Name").grid(row=7,column=0,sticky=W)
self.NLastName = Entry(self.master, textvariable=self.tLastName).grid(row =7,column=1,stick=W)
self.inst_lbl3 = Label(self.master, text = "House Number").grid(row=8,column=0,sticky=W)
self.HouseNumber = Entry(self.master,textvariable=self.tHouseNumber).grid(row=8,column=1,sticky=W)
self.inst_lbl4 = Label(self.master, text = "Street Name").grid(row=9,column=0,sticky=W)
self.StreetName =Entry(self.master,textvariable=self.tStreetName).grid(row=9,column=1,sticky=W)
self.inst_lbl5 = Label(self.master, text = "Town or City Name").grid(row=10,column=0,sticky=W)
self.TownOrCityName =Entry(self.master,textvariable=self.tTownOrCityName).grid(row=10,column=1,sticky=W)
self.inst_lbl6 = Label(self.master, text = "Postcode").grid(row=11,column=0,sticky=W)
self.PostCode = Entry(self.master,textvariable=self.tPostCode).grid(row=11,column=1,sticky=W)
self.inst_lbl7 = Label(self.master, text = "Email").grid(row=12,column=0,sticky=W)
self.Email =Entry(self.master,textvariable=self.tEmail).grid(row=12,column=1,sticky=W)
self.inst_lbl8 = Label(self.master, text = "Mobile phonenumber").grid(row=13,column=0,sticky=W)
self.MobilePhoneNumber =Entry(self.master,textvariable=self.tMobilePhoneNumber).grid(row=13,column=1,sticky=W)
self.btnSaveChanges = Button(self, text = "save changes",padx=80,pady=10,command = lambda:self.SaveChanges).grid(row=14,column=0,sticky=W)
#self.btnSaveChanges = Button(self, text = "delete record",padx=80,pady=10,command = lambda:self.DeleteRecord).grid(row=14,column=1,sticky=W)
def search(self):
FirstName = self.fn_txt.get()
LastName = self.ln_txt.get()
with sqlite3.connect("GuitarLessons.db") as db:
cursor = db.cursor()
cursor.row_factory = sqlite3.Row
sql = "select StudentID,FirstName,LastName,HouseNumber,StreetName,TownOrCityName,PostCode,Email,MobilePhoneNumber"\
" from tblStudents"\
" where FirstName like ?"\
" and LastName like ?"
cursor.execute(sql,("%"+FirstName+"%","%"+LastName+"%",))
StudentList = cursor.fetchall()
print(StudentList)
self.loadStudents(StudentList)
def loadStudents(self,StudentList):
for i in self.tree.get_children():
self.tree.delete(i)
for student in StudentList:
self.tree.insert("" , 0,values=(student[0],student[1],student[2],student[3],student[4],student[5],student[6],student[7],student[8]))
def SaveChanges(self):
with sqlite3.connect("GuitarLessons.db") as db:
cursor = db.cursor()
sql = "update tblStudents set FirstName =?,LastName=?,HouseNumber=?,StreetName=?,TownOrCityName=?,PostCode=?,Email=?,MobilePhoneNumber=? where StudentID=?"
cursor.execute(sql,("%"+NFirstName+"%","%"+NLastName+"%","%"+NHouseNumber+"%","%"+NStreetName+"%","%"+NTownOrCityName+"%","%"+NPostCode+"%","%"+NEmail+"%","%"+NMobilePhoneNumber+"%"))
db.commit()
def DeleteRecord(self):
print("")
root = Tk()
root.title("booking system")
root.geometry("800x800")
root.configure(bg="white")
app = Application(root)
root.mainloop()
The mistake you are making is that you're trying to put everything into one massive grid, but the code to populate that grid is scattered throughout your program. Your UI clearly has three distinct sections, you should organize your GUI that way.
Create a frame for the top, a frame for the treeview, and a frame for the bottom section. You can use pack to place these in the master window, one on top of the other. Then, place your other widgets in the appropriate frame. This way, changes you make in one section (adding or removing columns or rows, switching to pack, etc) won't affect the other areas.

Categories

Resources