Related
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.
I am losing my peanuts here. I am trying to clear two label values but i get an error
AttributeError: 'Label' object has no attribute 'delete'
basically if i were to click the calculate subtotal button then click the divide total button. I get my intended values. Now if I were to click on the clear values button i get an error. Literally shaking my head as I type this. Anyone care to explain why this is the case?
try:
import Tkinter as tk
except:
import tkinter as tk
class GetInterfaceValues():
def __init__(self):
self.root = tk.Tk()
self.totalValue = tk.StringVar()
self.root.geometry('500x200')
self.calculateButton = tk.Button(self.root,
text='Calculate Subtotal',
command=self.getSubtotals)
self.divideTotalButton = tk.Button(self.root,
text='Divide total',
command=self.divide)
self.textInputBox = tk.Text(self.root, relief=tk.RIDGE, height=1, width = 6, borderwidth=2)
self.firstLabel = tk.Label(self.root, text="This is the subtotal:")
self.secondLabel = tk.Label(self.root, text="This is the Divide Total:")
self.clearTotalButton = tk.Button(self.root, text='clear the values',command = self.clear)
self.firstLabel.pack(side="bottom")
self.secondLabel.pack(side="bottom")
self.textInputBox.pack()
self.calculateButton.pack()
self.divideTotalButton.pack()
self.clearTotalButton.pack()
self.root.mainloop()
def getTextInput(self):
result = self.textInputBox.get("1.0", "end")
return result
def getSubtotals(self):
userValue = int(self.getTextInput())
self.firstLabel["text"] = self.firstLabel["text"] + str(userValue * 5)
def divide(self):
userValue = int(self.getTextInput())
self.secondLabel["text"] = self.secondLabel["text"] + str(userValue / 10)
def clear(self):
self.firstLabel["text"] = self.firstLabel.delete("1.0","end")
app = GetInterfaceValues()
try:
import Tkinter as tk
except:
import tkinter as tk
class GetInterfaceValues():
def __init__(self):
self.root = tk.Tk()
self.totalValue = tk.StringVar()
self.root.geometry('500x200')
self.calculateButton = tk.Button(self.root,
text='Calculate Subtotal',
command=self.getSubtotals)
self.divideTotalButton = tk.Button(self.root,
text='Divide total',
command=self.divide)
self.textInputBox = tk.Text(self.root, relief=tk.RIDGE, height=1, width = 6, borderwidth=2)
self.firstLabelDefault = "This is the subtotal:"
self.secondLabelDefault = "This is the Divide Total:"
self.firstLabel = tk.Label(self.root, text=self.firstLabelDefault)
self.secondLabel = tk.Label(self.root, text=self.secondLabelDefault)
self.clearTotalButton = tk.Button(self.root, text='clear the values',command = self.clear)
self.firstLabel.pack(side="bottom")
self.secondLabel.pack(side="bottom")
self.textInputBox.pack()
self.calculateButton.pack()
self.divideTotalButton.pack()
self.clearTotalButton.pack()
self.root.mainloop()
def getTextInput(self):
result = self.textInputBox.get("1.0", "end")
return result
def getSubtotals(self):
userValue = int(self.getTextInput())
self.firstLabel["text"] = self.firstLabel["text"] + str(userValue * 5)
def divide(self):
userValue = int(self.getTextInput())
self.secondLabel["text"] = self.secondLabel["text"] + str(userValue / 10)
def clear(self):
self.firstLabel["text"] = self.firstLabelDefault
self.secondLabel["text"] = self.secondLabelDefault
self.textInputBox.delete("1.0", "end")
app = GetInterfaceValues()
You may have confused the methods of tkinter.Text and tkinter.Label. The method you called was tkinter.label.delete, which is not defined (does not exist), however it does exist for the tkinter.Text. Therefore, the only way to 'reset' would be to change the text attribute of the tkinter.Labels back to a 'default' string. It would perhaps be more appropriate to use another widget instead.
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()
I am creating a form for session variables in python and (currently) store the inputs in separate text files. How could I use a single file to hold all session variables in lists (there will be more than 2 in the final form)? What would I need to change in my code to make this more efficient? Any help is greatly appreciated.
import tkinter
from tkinter import *
from tkinter import ttk
regionList = open('regions.txt','r')
optionList = open('options.txt','r')
class MainWindow(Frame):
def __init__(self,master = None):
Frame.__init__(self,master)
self.master = master
self.init_window()
self.grid()
self.create_widgets()
def create_widgets(self):
"""Create Window Layout"""
Boxfont = ('Lucida Grande', 12)
self.label1 = Label(self, font=Boxfont,
text="Regions").grid(row=2,column=0)
self.regcombo = ttk.Combobox(self, font = Boxfont, width = 20, textvariable = varRegions)
self.regcombo.bind("<Return>", self.regcombo_onEnter)
self.regcombo.bind('<<ComboboxSelected>>',self.regcombo_onEnter)
self.regcombo['values'] = regionList.readlines()
self.regcombo.grid(row=2, column=1,sticky = W)
self.label2 = Label(self, font=Boxfont, text="Options").grid(row=4,column=0)
self.optcombo = ttk.Combobox(self, font = Boxfont, width = 20, textvariable = varOptions)
self.optcombo.bind("<Return>", self.optcombo_onEnter)
self.optcombo.bind('<<ComboboxSelected>>',self.optcombo_onEnter)
self.optcombo['values'] = optionList.readlines()
self.optcombo.grid(row=4, column=1,sticky = W)
def init_window(self):
self.master.title("User Settings")
self.pack(fill=BOTH, expand=1)
def regcombo_onEnter(self,event):
varRegions.set(varRegions.get().lower())
mytext = varRegions.get()
vals = self.regcombo.cget('values')
self.regcombo.select_range(0,END)
print(mytext)
if not vals:
self.regcombo.configure(values = (mytext.strip,))
elif mytext not in vals:
with open('regions.txt','a') as f:
f.write('\n'+ mytext)
self.regcombo.configure(values = vals + (mytext,))
f.close
return 'break'
def optcombo_onEnter(self,event):
varOptions.set(varOptions.get().lower())
mytext = varOptions.get()
vals = self.optcombo.cget('values')
self.optcombo.select_range(0,END)
print(mytext)
if not vals:
self.optcombo.configure(values = (mytext.strip,))
elif mytext not in vals:
with open('options.txt','a') as f:
f.write('\n'+ mytext)
self.optcombo.configure(values = vals + (mytext,))
f.close
return 'break'
root = tkinter.Tk()
root.geometry("600x600")
varRegions = tkinter.StringVar(root, value='')
varOptions = tkinter.StringVar(root, value='')
app = MainWindow(root)
root.mainloop()
I am working on python gui in tkinter and trying for a unit converter. Initially when I took my cursor at lower radio buttons they are automatically selected, please anyone help me how can I get rid of this.
from Tkinter import *
import tkMessageBox
root=Tk()
root.wm_title("Measurement Converter")
def Distance():
def sel():
print var.get()
L1 = Label(root, text="Enter Value :",font=20)
L1.grid(row=3,column=0,padx=(0,10),columnspan=2)
E1=Entry(root,justify=CENTER,width=20).grid(row=3,column=1,padx=(0,0),ipady=10,ipadx=20)
L2 = Label(root, text="units in-")
L2.grid(row=4,column=1,padx=(0,0))
var = IntVar()
R1 = Radiobutton(root, text="Meter", variable=var, value=1,command=sel)
R1.grid(row=4,column=1,padx=(120,0))
R2 = Radiobutton(root, text="Km", variable=var, value=2,command=sel)
R2.grid(row=4,column=1,padx=(240,0))
R3 = Radiobutton(root, text="Feet", variable=var, value=3,command=sel)
R3.grid(row=4,column=1,columnspan=2,padx=(100,0),pady=4)
L3 = Label(root, text="convert into-")
L3.grid(row=5,column=1,padx=(0,0))
var3 = IntVar()
RB1 = Radiobutton(root, text="Meter", variable=var3, value=1,command=sel)
RB1.grid(row=5,column=1,padx=(120,0))
RB2 = Radiobutton(root, text="Km", variable=var3, value=2,command=sel)
RB2.grid(row=5,column=1,padx=(240,0))
RB3 = Radiobutton(root, text="Feet", variable=var3, value=3,command=sel)
RB3.grid(row=5,column=1,columnspan=2,padx=(100,0),pady=5)
label1=Label(root, text='Select any Button to convert it in other Unit',bg="green",fg="white",justify=CENTER,borderwidth=1,font=20,padx=20 )
label1.grid(pady=15,padx=(15,15),row=0,column=1)
buttontext1=StringVar()
button1=Button(root,textvariable=buttontext1,font=25,padx=5,pady=5,width=15,command=Distance,bg='#FF0000')
buttontext1.set("Distance")
button1.grid(row=1,column=0,padx=(100,00))
buttontext2=StringVar()
button2=Button(root,textvariable=buttontext2,font=25,padx=5,pady=5,width=15,command=Distance,bg='#66FF66')
buttontext2.set("Weight")
button2.grid(row=1,column=2,padx=(0,100))
buttontext3=StringVar()
button3=Button(root,textvariable=buttontext3,font=25,padx=5,pady=5,width=15,command=Distance,bg='#3399CC')
buttontext3.set("Temprature")
button3.grid(row=2,column=0,pady=50,padx=(100,0))
buttontext4=StringVar()
button4=Button(root,textvariable=buttontext4,font=25,padx=5,pady=5,width=15,command=Distance,bg='#CCFF00')
buttontext4.set("Volume")
button4.grid(row=2,column=2,padx=(0,100))
root.mainloop()
I had few time so I developed this quickly. It's just a starting point, and surely it can be enhanced. I prefered to develop as class so you could separate elaboration code from display code (you should just develop another class and instantiate it inside Gui's calc method). When you have to do the conversion you have to query self.radio"variable" to get user selected option. If you need further help, please ask. I'll try to answer as soon as possible.
from Tkinter import *
class Calculate:
def __init__(self):
self.stuff = None #store here cosstants to do conversions...
def convert1(self,startval):#,someother params to specify "from" and "to"):
return startval#this is an identity just as example
def convert2(self,startval):
pass
#...and so on...
class Gui:
def __init__(self):
self.root = Tk()
self.c = Calculate()
self.volumef = StringVar()
self.volumef.set("C")
self.volumet = StringVar()
self.volumet.set("C")
self.weightf = StringVar()
self.weightf.set("K")
self.weightt = StringVar()
self.weightt.set("K")
self.distancef = StringVar()
self.distancef.set("M")
self.distancet = StringVar()
self.distancet.set("M")
self.temperaturef = StringVar()
self.temperaturef.set("C")
self.temperaturet = StringVar()
self.temperaturet.set("C")
self.f3 = None
self.f4 = None
self.f5 = None
self.DISTANCEMODES = [("Meter", "M"),
("Km", "K"),
("Feet", "F")
]
self.VOLUMEMODES = [ ("cm^3","C"),
("m^3","M"),
("mm^3","MM")
]
self.TEMPERATUREMODE = [ ("Celsius","C"),
("Farenheit","H"),
("Kelvin","K")
]
self.WEIGHTMODE = [ ("Kg","K"),
("g","G"),
("mg","M")
]
self.root.title("Conversions")
self.f1 = Frame(self.root,relief=SUNKEN)
self.f1.pack()
self.createWidgets()
self.root.mainloop()
def createWidgets(self):
self.f1 = Frame(self.root)
self.bd = Button(self.f1, text="Distance",command=self.distance,width=10)
self.bd.pack(side=LEFT,padx=10,pady=10)
self.bw = Button(self.f1, text="Weight",command=self.weight,width=10)
self.bw.pack(side=LEFT,padx=10,pady=10)
self.f1.pack()
self.f2 = Frame(self.root)
self.bt = Button(self.f2, text="Temperature",command=self.temperature,width=10)
self.bt.pack(side=LEFT,padx=10,pady=10)
self.bv = Button(self.f2, text="Volume",command=self.volume,width=10)
self.bv.pack(side=LEFT,padx=10,pady=10)
self.f2.pack()
def convert(self,val):
var = self.edit1.get()#get value
if val==0:#choose what conversion applay
#x = self.c.convert1(var,self.volumef,self.volumet)
x = self.c.convert1(var)#do a conversion
print "volume calc"
elif val==1:
x = self.c.convert1(var)#do a conversion
print "weight calc"
elif val==2:
x = self.c.convert1(var)#do a conversion
print "distance calc"
elif val==3:
x = self.c.convert1(var)#do a conversion
print "temperature calc"
else:
print "it should never happen, but u can trow an excepion"
x=0 #to avoid a python s.f. as I don't trow/manage exceptions
self.edit2.config(state=NORMAL)#set as normal to be able to edit
self.edit2.delete(0,END)#delete previous content
self.edit2.insert(0,x)#add new content
self.edit2.config(state=DISABLED)#do not allow user input
def createRadio(self,fv,tv,cmdp,mode):#fromvariable,tovariable,commandparam,mode
if self.f3 and self.f4 and self.f5:
self.f3.pack_forget()
self.f4.pack_forget()
self.f5.pack_forget()
#FROM:
self.f3 = Frame(self.root)
lbl = Label(self.f3,text="From:",width=8)
lbl.pack(side=LEFT)
for m_text,m_mode in mode:
b = Radiobutton(self.f3,text=m_text,value=m_mode,variable=fv)
b.pack(side=LEFT)
self.edit1 = Entry(self.f3,width=10)
self.edit1.pack(side=LEFT)
self.f3.pack()
#TO:
self.f4 = Frame(self.root)
lbl = Label(self.f4,text="To:",width=8)
lbl.pack(side=LEFT)
for m_text,m_mode in mode:
b = Radiobutton(self.f4,text=m_text,value=m_mode,variable=tv)
b.pack(side=LEFT)
self.edit2 = Entry(self.f4,width=10)
self.edit2.config(state=DISABLED)
self.edit2.pack(side=LEFT)
self.f4.pack()
self.f5 = Frame(self.root)
self.btnCalc = Button(self.f5,text="Calc",command=lambda:self.convert(cmdp),width=10)
self.btnCalc.pack()
self.f5.pack()
def volume(self):
self.createRadio(self.volumef,self.volumet,0,self.VOLUMEMODES)
def weight(self):
self.createRadio(self.weightf,self.weightt,1,self.WEIGHTMODE)
def distance(self):
self.createRadio(self.distancef,self.distancet,2,self.DISTANCEMODES)
def temperature(self):
self.createRadio(self.temperaturef,self.temperaturet,3,self.TEMPERATUREMODE)
Gui()
[EDIT]: ok i fixed a bit my code, now it should have a bit more sense ;)