Tkinter "_tkinter.TclError: image "pyimage1" doesn't exist" error - python

I'm trying to add an image to a frame in Tkinter but getting the error: _tkinter.TclError: image "pyimage1" doesn't exist.
I have a parent class that all of my windows inherit from:
class GUI(tk.Tk):
def __init__(self, name, dimensions):
super().__init__()
self.name = name
self.dimensions = dimensions
self.title(self.name)
self.geometry(self.dimensions)
The child class I want to add the image to is shown below(I have taken out some of the functions so that it isn't very long).
class Analyze(GUI):
def __init__(self, name, dimensions):
super().__init__(name, dimensions)
conn = sqlite3.connect('invoice_db.db')
cursor = conn.cursor()
self.frame1 = LabelFrame(self, text="Analyze Data")
self.frame1.grid(row=0, column=0, padx=10, pady=5)
self.frame2 = LabelFrame(self, text="Graph")
self.frame2.grid(row=1, column=0, padx=10, pady=5)
self.choices = ["", "", "", "", ""]
self.select_type = ttk.Combobox(self.frame1, value=("Credit", "Debit", "Net Profit"))
self.select_type.current(0)
self.select_type.bind("<<ComboboxSelected>>", self.click_type)
self.select_type.grid(row=0, column=0)
self.company_list = ["All Companies"]
cursor.execute("SELECT company_name FROM companies"),
self.companies = cursor.fetchall()
for x in self.companies: self.company_list.append(x[0])
self.select_company = ttk.Combobox(self.frame1, value=self.company_list)
self.select_company.current(0)
self.select_company.bind("<<ComboboxSelected>>", self.click_company)
self.select_company.grid(row=0, column=1)
self.start_date_calendar = DateEntry(self.frame1, date_pattern='y-mm-dd')
self.start_date_calendar.grid(row=0, column=2, padx=10, pady=10)
self.start_date_calendar.bind("<<DateEntrySelected>>", self.start_date)
self.end_date_calendar = DateEntry(self.frame1, date_pattern='y-mm-dd')
self.end_date_calendar.grid(row=0, column=3, padx=10, pady=10)
self.end_date_calendar.bind("<<DateEntrySelected>>", self.end_date)
self.currency_entry = Entry(self.frame1)
self.currency_entry.grid(row=0, column=4, padx=10, pady=10)
self.show_results_button = Button(self.frame1, text="Show Results", command=self.show_results)
self.show_results_button.grid(row=1, column=1, padx=10, pady=10)
self.go_back_button = Button(self, text="Go Back", command=self.go_back)
self.go_back_button.grid(row=0, column=0, padx=10, pady=10)
self.create_graph_button = Button(self.frame2, text="Create Graph", command=self.create_graph)
self.create_graph_button.pack()
conn.commit()
conn.close()
def create_graph(self):
image1 = Image.open("images/hop1.png")
img = ImageTk.PhotoImage(image1)
label1 = Label(self.frame2,image=img)
label1.image = img
label1.pack()
I call the Analyze class in another class like this:
class Welcome(GUI):
def __init__(self, name, dimensions):
super().__init__(name, dimensions)
# Create the starting label and buttons
self.title = Label(self, text="Invoice Organizer", font=("Helvetica", 36))
self.title.place(relx=.5, rely=.1, anchor="center")
self.company_button = Button(self, text="Companies", font=("Helvetica", 18), command=lambda: self.select_page("Company"))
self.company_button.place(relx=.3, rely=.5, anchor="center")
self.analyze_button = Button(self, text="Invoices", font=("Helvetica", 18), command=lambda: self.select_page("Invoice"))
self.analyze_button.place(relx=.5, rely=.5, anchor="center")
self.invoice_button = Button(self, text="Analyze", font=("Helvetica", 18), command=lambda: self.select_page("Analyze"))
self.invoice_button.place(relx=.7, rely=.5, anchor="center")
def select_page(self, button):
if button == "Company":
new = Company(button, "1000x800")
elif button == "Invoice":
new = Invoice(button, "1000x800")
else:
new = Analyze(button, "1000x800")

Related

Python - How to add information from dictionaries to listbox widget?

This is my first encounter with listboxes and I want to know how to insert the name of each team member into the corresponding listbox.
I have a dictionary called teams, and it's store data like that:
{'Team1': {'Aleks', Richard}, 'Team2': {'Louis'}, 'Team3': set(), 'Team4': set()}
I need to put set of names in particular listbox (ex. 'Team1' set should appear in the team1Members listbox).
I was trying to use .insert method to insert specific items from my dictionary, but I receive an error:
_tkinter.TclError: bad listbox index ".!frame.!listcheckpage": must be active, anchor, end, #x,y, or a number
My code:
from tkinter import *
from tkinter import messagebox
import tkinter.ttk as ttk
import time
class CollegeApp(Tk):
def __init__(self):
Tk.__init__(self)
container = ttk.Frame(self)
container.pack(side="top", fill="both", expand=True)
self.frames = {}
for F in (StartPage, TeamsPage, successfullAddTeam, selectionPage, listCheckPage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
self.lift()
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.startMenu()
def startMenu(self):
heading = Label(self, text="College Tournament Points\n Count Software",
font=('Arial', 25))
heading.grid(row=0, column=0, columnspan=2, padx=240, pady=40)
start_Btn = Button(self, text="START", font="Arial 16", width=8,
command=lambda: self.controller.show_frame(selectionPage))
start_Btn.grid(row=1, column=0, columnspan=2, padx=30, pady=5)
exit_Btn = Button(self, text="EXIT", font="Arial 16", width=8,
command=self.controller.destroy)
exit_Btn.grid(row=2, column=0, columnspan=2, padx=30, pady=5)
def starting_Program(self):
pass
class selectionPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.teamSelect()
def teamSelect(self):
heading = Label(self, text="Select one of two options",
font=('Arial', 25))
heading.grid(row=0, column=0, columnspan=2, padx=250, pady=40)
teams = Button(self, text="Teams", font="Arial 24", width=15,
command=lambda: self.controller.show_frame(TeamsPage))
teams.grid(row=1, column=0, padx=270, pady=5)
class TeamsPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.userEntry()
def userEntry(self):
headingTest = Label(self, text="Enter your UserName:", font="Arial 20")
headingTest.grid(row=0, column=0, pady=5, padx=5)
self.usernameEnter = Entry(self, width=40)
self.usernameEnter.grid(row=0, column=1, padx=5, pady=5)
self.TeamName = StringVar(self)
self.TeamName.set("Team1")
AdditionalText = Label(self, text="Please select a team:", font="Arial 18")
AdditionalText.grid(row=1, column=0, sticky=W, pady=15, padx=5)
self.team_names = list(teams.keys())[:-1]
self.teamSelection = OptionMenu(self, self.TeamName, *self.team_names)
self.teamSelection.grid(row=1, column=1, sticky=W)
backBtn = Button(self, text="BACK", font="Arial 16",
command=lambda: self.controller.show_frame(StartPage))
backBtn.config(height=4, width=12)
backBtn.grid(sticky=W, row=2, column=0, pady=5, padx=5)
confirmBtn = Button(self, text="Confirm User", font="Arial 16",
command=self.confirm)
confirmBtn.config(height=4, width=12)
confirmBtn.grid(row=2, column=2, sticky=E, padx=45, pady=300)
def confirm(self):
if self.add_to_team():
time.sleep(0.2)
self.controller.show_frame(successfullAddTeam)
def add_to_team(self):
user = self.usernameEnter.get()
if len(user) == 0:
messagebox.showwarning(title='No user', message='Please enter a username!')
return
if self.usernameEnter.get():
time.sleep(0.1)
self.controller.show_frame(successfullAddTeam)
team_name = self.TeamName.get()
team = teams[team_name]
if user in team:
messagebox.showwarning(title='In team', message=f'{user} is already a member of {team_name}!')
team.add(user)
print(teams)
class successfullAddTeam(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.userEntry()
def userEntry(self):
successText = Label(self, text="You have successfully joined to a team!", font="Arial 25")
successText.grid(row=0, column=0, columnspan=2, padx=180, pady=35)
newUser = Button(self, text="Add another user", font="Arial 16",
command=lambda: self.controller.show_frame(selectionPage))
newUser.config(height=3, width=12)
newUser.grid(row=1, column=0, columnspan=2, padx=200, pady=10)
checkList = Button(self, text="Check the lists", font="Arial 16",
command=lambda: self.controller.show_frame(listCheckPage))
checkList.config(height=3, width=12)
checkList.grid(row=2, column=0, columnspan=2, padx=200, pady=0)
#####################################Problem here###############################################
class listCheckPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.userEntry()
def userEntry(self):
team1Members = Listbox(self)
team1Members.insert(self, teams['Team1'])
team1Members.config(height=13, width=20)
team1Members.grid(row=0, column=0, padx=10, pady=5, sticky=W)
team2Members = Listbox(self)
team2Members.insert(self, teams['Team2'])
team2Members.config(height=13, width=20)
team2Members.grid(row=0, column=1, padx=7, pady=5, sticky=W)
team3Members = Listbox(self)
team3Members.insert(self, teams['Team3'])
team3Members.config(height=13, width=20)
team3Members.grid(row=0, column=3, padx=7, pady=5, sticky=W)
team4Members = Listbox(self)
team4Members.insert(self, teams['Team4'])
team4Members.config(height=13, width=20)
team4Members.grid(row=0, column=4, padx=7, pady=5, sticky=W)
addUserBtn = Button(self, text="Add User", font="Arial 16",
command=lambda: self.controller.show_frame(selectionPage))
addUserBtn.config(height=3, width=18)
addUserBtn.grid(row=1, column=4, sticky=S)
if __name__ == '__main__':
teams = {}
for team in range(1, 5):
teams[f'Team{team}'] = set()
app = CollegeApp()
app.geometry("800x500")
app.title('Points Counter')
app.mainloop()
It is obvious that I am doing something wrong, and I would like to know how this issue can be properly resolved.

Python - How to assign OpenMenu choice as a List?

I have created Frame with Entry widget to ask user to input his Username and select a team, that he want to join in and also I have created an OpenMenu Widget with 4 teams that user can join.
I want to know, how to assign list to OpenMenu variations as a list. For example: Selection "Team 1" = team1Members etc.
Also I want to know, how to assign data from Entry Widget to appropriate list. For example, if user have selected "Team 1", his username will append to team1Members list.
from tkinter import *
import tkinter.ttk as ttk
team1Members = []
team2Members = []
team3Members = []
team4Members = []
class CollegeApp(Tk):
def __init__(self):
Tk.__init__(self)
container = ttk.Frame(self)
container.pack(side="top", fill="both", expand=True)
self.frames = {}
for F in (StartPage, selectionPage, TeamsPage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.startMenu()
def startMenu(self):
heading = Label(self, text="College Tournament Points\n Count Software",
font=('Arial', 25))
heading.grid(row=0, column=0, columnspan=2, padx=240, pady=40)
start_Btn = Button(self, text="Start", font="Arial 16", width=8,
command=lambda: self.controller.show_frame(selectionPage))
start_Btn.grid(row=1, column=0, padx=30, pady=5)
exit_Btn = Button(self, text="EXIT", font="Arial 16", width=8,
command=self.controller.destroy)
exit_Btn.grid(row=1, column=1, padx=30, pady=5)
def starting_Program(self):
pass
class selectionPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.teamSelect()
def teamSelect(self):
heading = Label(self, text="Become a member of a Team",
font=('Arial', 25))
heading.grid(row=0, column=0, columnspan=2, padx=200, pady=40)
teams = Button(self, text="Teams", font="Arial 24", width=15,
command=lambda: self.controller.show_frame(TeamsPage))
teams.grid(row=1, column=0, padx=270, pady=5)
class TeamsPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.userEntry()
def userEntry(self):
headingTest = Label(self, text="Enter your Username:", font="Arial 20")
headingTest.grid(row=0, column=0, pady=0)
usernameEnter = Entry(self, width=40)
usernameEnter.grid(row=0, column=1, padx=2, pady=10)
UserName = StringVar(self)
UserName.set("Team1")
AdditionalText = Label(self, text="Please select a team:", font="Arial 18")
AdditionalText.grid(row=1, column=0, sticky=W, pady=15)
teamSelection = OptionMenu(self, UserName, "Team1", "Team2", "Team3", "Team 4") # How to link those variations to team list? For example: Team 1 = team1Members?
teamSelection.grid(row=1, column=1, sticky=W)
confirmBtn = Button(self, text="Submit", font="Arial 16",
command=()) # Command to Save username in teamXMembers list. Depends on the user selection
confirmBtn.config(height=4, width=12)
confirmBtn.grid(row=2, column=2, sticky=E, padx=65, pady=300)
if __name__ == '__main__':
app = CollegeApp()
app.geometry("800x500")
app.title('Points Counter')
app.mainloop()
Screenshot of this window:
There are few ways that could achieve this. The First would be to create a list of teams and unpack them using * in optionMenu then use if else condition to check which list to append to.
Here is a demo
class TeamsPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.teamList = ["Team1", "Team2", "Team3", "Team 4"]
self.userEntry()
def userEntry(self):
...
self.usernameEnter = Entry(self, width=40)
self.usernameEnter.grid(row=0, column=1, padx=2, pady=10)
self.userName = StringVar(self)
self.userName.set("Team1")
teamSelection = OptionMenu(self, self.userName, *self.teamList)
teamSelection.grid(row=1, column=1, sticky=W)
confirmBtn = Button(self, text="Submit", font="Arial 16",
command= self.updateTeamList) # Command to Save username in teamXMembers list. Depends on the user selection
...
def updateTeamList(self):
if self.userName.get() == self.teamList[0]:
team1Members.append(self.usernameEnter.get())
elif self.userName.get() == self.teamList[1]:
team2Members.append(self.usernameEnter.get())
...
but a better way would be to create a dictionary. something as shown
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.teamList = {"Team1": team1Members , "Team2": team2Members,
"Team3":team3Members, "Team 4": team4Members}
self.userEntry()
def userEntry(self):
...
self.usernameEnter = Entry(self, width=40)
self.usernameEnter.grid(row=0, column=1, padx=2, pady=10)
self.userName = StringVar(self)
self.userName.set("Team1")
AdditionalText = Label(self, text="Please select a team:", font="Arial 18")
AdditionalText.grid(row=1, column=0, sticky=W, pady=15)
teamSelection = OptionMenu(self, self.userName, *self.teamList.keys())
teamSelection.grid(row=1, column=1, sticky=W)
confirmBtn = Button(self, text="Submit", font="Arial 16",
command= self.updateTeamList) # Command to Save username in teamXMembers list. Depends on the user selection
...
def updateTeamList(self):
self.teamList[self.userName.get()].append(self.usernameEnter.get())

Is It possible to create multiple form fields in tkinter & python and then submit it to a out to an output textbox in a table column format

So my problem is that I want to create multiple entry fields like over 30, but every time I reformat it using .pack or .grid it keeps throwing off the formatting. is there a way to fit nearly 30 entry boxes on one window without using anything like SQLite? As we can see from this code, we have 4 fields, how would you go on with shrinking the boxes to put in more entry fields like over 30.
Secondly, I want to output all the typed data entry fields to the Listbox is there a way to add a table column to the list box to show a breakdown of each entry field.
The third is it possible to move the Listbox to another tab on the same window to show all entry fields that were typed in, if so how would you do so.
Here is my current code so far
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
from datetime import *
# Import Packages
import tkinter as tk
from tkinter import *
from tkinter import ttk
from tkinter.scrolledtext import *
import tkinter.filedialog
from tkcalendar import Calendar, DateEntry
from tkinter import messagebox
from tkintertable import TableCanvas, TableModel
from tkinter import ttk
# Database
#import sqlite3
import csv
window = Tk()
window.title("TESTTEST")
window.geometry("750x450")
window.config(background='black')
#style = ttk.Style(window)
#style.configure('lefttab.TNotebook', tabposition='wn',)
# TAB LAYOUT
#tab_control = ttk.Notebook(window,style='righttab.TNotebook')
#tab1 = ttk.Frame(tab_control)
#tab2 = ttk.Frame(tab_control)
#tab3 = ttk.Frame(tab_control)
#tab4 = ttk.Frame(tab_control)
#tab5 = ttk.Frame(tab_control)
#tab6 = ttk.Frame(tab_control)
# ADD TABS TO NOTEBOOK
#tab_control.add(tab1, text=f'{"Home":^20s}')
#tab_control.add(tab2, text=f'{"View":^20s}')
#tab_control.add(tab3, text=f'{"Search":^20s}')
#tab_control.add(tab4, text=f'{"Edit":^20s}')
#tab_control.add(tab5, text=f'{"Export":^20s}')
#tab_control.add(tab6, text=f'{"About ":^20s}')
#label1 = Label(tab1, text= 'Python RPA APP',padx=1, pady=1)
#label1.grid(column=0, row=0)
#label2 = Label(tab2, text= 'View',padx=5, pady=5)
#label2.grid(column=0, row=0)
#label3 = Label(tab3, text= 'Search',padx=5, pady=5)
#label3.grid(column=0, row=0)
#label4 = Label(tab4, text= 'Edit/Update',padx=5, pady=5)
#label4.grid(column=0, row=0)
#label5 = Label(tab5, text= 'Export',padx=5, pady=5)
#label5.grid(column=0, row=0)
#label6 = Label(tab6, text= 'About',padx=5, pady=5)
#label6.grid(column=0, row=0)
#tab_control.pack(expand=1, fill='both')
class Main(ttk.Frame):
def __init__(self, parent):
super().__init__()
self.parent = parent
self.punches_list = []
self.ent1 = tk.StringVar()
self.ent2 = tk.StringVar()
self.ent3 = tk.StringVar()
self.ent4 = tk.StringVar()
self.init_ui()
def init_ui(self):
f = ttk.Frame()
# ttk.Label(f, text = "Entry1").pack(side=TOP, anchor=NW)
## ttk.Label(f, text = "Entry1").pack(side=LEFT, padx=5, pady=5, anchor=NW)
## self.txTest = ttk.Entry(f,textvariable=self.ent).pack(fill=X, padx=5, expand=True, anchor=NW)
# ttk.Label(f, text = "Entry1").pack(side=TOP, anchor=NW)
# self.txTest1 = ttk.Entry(f, textvariable=self.ent2).pack(side=TOP, anchor=NW)
ttk.Label(f, text = "Entry1").pack(side=TOP, anchor=NW, fill=tk.BOTH, pady=5, padx=5, expand=0)
self.txTest1 = ttk.Entry(f, textvariable=self.ent1).pack(side=TOP, anchor=NW, fill=tk.BOTH, pady=5, padx=5, expand=0)
ttk.Label(f, text = "Entry2").pack(side=TOP, anchor=NW,fill=tk.BOTH, pady=5, padx=5, expand=0)
self.txTest2 = ttk.Entry(f, textvariable=self.ent2).pack(side=TOP, anchor=NW,fill=tk.BOTH, pady=5, padx=5, expand=0)
ttk.Label(f, text = "Entry3").pack(side=TOP, anchor=NW,fill=tk.BOTH, pady=5, padx=5, expand=0)
self.txTest3 = ttk.Entry(f, textvariable=self.ent3).pack(side=TOP, anchor=NW,fill=tk.BOTH, pady=5, padx=5, expand=0)
#tkinter.Label(window, text = "Username").grid(row = 0) #'username' is placed on position 00 (row - 0 and column - 0)
#tkinter.Entry(window).grid(row = 0, column = 1) # first input-field is placed on position 01 (row - 0 and column - 1)
ttk.Label(f, text = "Entry4").pack(side=TOP, anchor=NW,fill=tk.BOTH, pady=5, padx=5, expand=0)
self.txTest4 = ttk.Entry(f, textvariable=self.ent4).pack(side=TOP, anchor=NW,fill=tk.BOTH, pady=5, padx=5, expand=0)
self.lstItems = self.get_listbox(f, 140,140).pack(anchor=N)
w = ttk.Frame()
ttk.Button(w, text="Add",command=self.add_In).pack(side=TOP, anchor=NE)
ttk.Button(w, text="Clear", command=self.clear_Out).pack(side=TOP, anchor=NE)
ttk.Button(w, text="Close", command=self.on_close).pack(side=TOP, anchor=NE)
#f.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)
#w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)
f.pack(side=tk.LEFT, fill=tk.BOTH, pady=5, padx=5, expand=1)
w.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
def add_In(self,):
#s = "IN {0:>30} {1}".format(str(datetime.now()), self.ent.get())
s = self.ent1.get()
self.set_list(s)
s = self.ent2.get()
self.set_list(s)
s = self.ent3.get()
self.set_list(s)
s = self.ent4.get()
self.set_list(s)
self.ent1.set('')
self.ent2.set('')
self.ent3.set('')
self.ent4.set('')
def clear_Out(self):
#s = "OUT {0:>29} {1}".format(str(datetime.now()), self.ent1.get())
#field_name.set('')
self.ent1.set('')
self.ent2.set('')
self.ent3.set('')
self.ent4.set('')
#self.set_list(s)
def set_list(self,s):
self.punches_list.append(s)
self.lstItems.delete(0, tk.END)
for i in self.punches_list:
self.lstItems.insert(tk.END, i)
def on_set(self):
self.check.set(1)
def on_close(self):
#self.destroy()
self.parent.on_exit()
def get_listbox(self, container, height=750, width=600):
sb = tk.Scrollbar(container,orient=tk.VERTICAL)
w = tk.Listbox(container,
relief=tk.GROOVE,
selectmode=tk.BROWSE,
height=height,
width=width,
background = 'white',
font='TkFixedFont',
yscrollcommand=sb.set,)
sb.config(command=w.yview)
w.pack(side=tk.LEFT,fill=tk.BOTH, expand =1)
sb.pack(fill=tk.Y, expand=1)
return w
class App(tk.Tk):
"""Start here"""
def __init__(self):
super().__init__()
self.protocol("WM_DELETE_WINDOW", self.on_exit)
self.set_style()
self.set_title()
Main(self,)
def set_style(self):
self.style = ttk.Style()
#('winnative', 'clam', 'alt', 'default', 'classic', 'vista', 'xpnative')
self.style.theme_use("vista") #change to your liking :)
def set_title(self):
s = "{0}".format('Employee Time-Clock')
self.title(s)
self.destroy()
def on_exit(self):
window.destroy()
#self.destroy()
#sys.exit()
#"""Close all"""
#if messagebox.askokcancel( self.title(), "Do you want to quit?", parent=self):
# self.destroy()
if __name__ == '__main__':
app = App()
app.mainloop()
Your code is a giant mess, brah ;D. What I gather from your question is that you need some kind of table. What I gather from your code is the table should have cells comprised of Label and Entry. You also want an interface to create entries. Below is an example of all of that. I don't really see anything to explain. It's just a bunch of Frame, Label, Entry and Button. The only real action is in Table. All that action is, is mathematically figuring out where to put the next Item. This is all really basic stuff.
import tkinter as tk
from tkinter import ttk
#the entire bottom row of the app.
#has a dependency on self.master.table ~ not good OOP
class EntryManager(tk.Frame):
def __init__(self, master, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.grid_columnconfigure(5, weight=1)
font='Helvetica 10 bold'
tk.Label(self, text='Label', font=font, width=5).grid(row=0, column=0, padx=2)
lbl = tk.Entry(self, width=10, font=font)
lbl.grid(row=0, column=1, padx=2)
tk.Label(self, text='Entry', font=font, width=5).grid(row=0, column=2, padx=2)
ent = tk.Entry(self, width=25, font=font)
ent.grid(row=0, column=3, padx=2)
tk.Button(self, text='add', font=font, command=lambda: self.master.table.addItem(lbl.get(), ent.get())).grid(row=0, column=4, padx=2, sticky='w')
tk.Label(self, text='rows', font=font, width=4).grid(row=0, column=5, padx=2, sticky='e')
r = tk.Entry(self, width=4, font=font)
r.insert('end', self.master.table.rows)
r.grid(row=0, column=6, padx=2)
tk.Label(self, text='cols', font=font, width=4).grid(row=0, column=7, padx=2)
c = tk.Entry(self, width=4, font=font)
c.insert('end', self.master.table.cols)
c.grid(row=0, column=8, padx=2)
tk.Button(self, text='set', font=font, command=lambda: self.master.table.setDims(r.get(), c.get())).grid(row=0, column=9, padx=2, sticky='e')
#generic scrollable frame
class ScrollFrame(tk.Frame):
def __init__(self, master, row=0, column=0, scrollspeed=.02, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.grid(row=row, column=column, sticky='nswe')
self.scrollspeed = scrollspeed
self.canvas = tk.Canvas(self, highlightthickness=0)
self.canvas.grid(column=0, row=0, sticky='nswe')
self.v_scroll = tk.Scrollbar(self, orient='vertical', command=self.canvas.yview)
self.v_scroll.grid(row=0, column=1, sticky='ns')
self.canvas.configure(yscrollcommand=self.v_scroll.set)
self.canvas.bind_all('<MouseWheel>', self.on_mousewheel)
self.frame = tk.Frame(self.canvas, height=0)
self.frame.grid_columnconfigure(0, weight=1)
self.frame.bind('<Configure>', lambda e:self.canvas.configure(scrollregion=self.canvas.bbox("all")))
self.canvas.create_window((0,0), window=self.frame, anchor="nw")
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
def on_mousewheel(self, event):
self.canvas.yview_moveto(self.v_scroll.get()[0]+((-event.delta/abs(event.delta))*self.scrollspeed))
#a table cell
class Item(tk.Frame):
#property
def value(self):
return self.__value.get()
#value.setter
def value(self, text):
self.__value.set(text)
def __init__(self, master, text, value, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
tk.Label(self, text=text, width=10, font='none 8 bold').grid(row=0, column=0, pady=5, padx=5)
self.__value = tk.StringVar(value=value)
tk.Entry(self, textvariable=self.__value, width=25).grid(row=0, column=1, pady=5, padx=5)
#the table
class Table(ScrollFrame):
def __init__(self, master, rows=15, cols=3, **kwargs):
ScrollFrame.__init__(self, master, **kwargs)
self.entries = []
self.rows = rows
self.cols = cols
def addItem(self, text, value):
if len(self.entries) < self.rows*self.cols:
self.entries.append(Item(self.frame, text, value))
self.entries[-1].grid(row=(len(self.entries)-1)%self.rows, column=(len(self.entries)-1)//self.rows)
def getItem(self, row, column):
return self.entries[self.rows*column+row].value
def setDims(self, rows, cols):
if rows.isnumeric():
self.rows = int(rows)
if cols.isnumeric():
self.cols = int(cols)
for ent in self.entries:
ent.grid_forget()
for i, ent in enumerate(self.entries):
if i < self.rows*self.cols:
ent.grid(row=i%self.rows, column=i//self.rows)
class App(tk.Tk):
WIDTH, HEIGHT, TITLE = 770, 465, 'Application'
def __init__(self):
tk.Tk.__init__(self)
ttk.Style().theme_use("vista")
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.table = Table(self, rows=20, cols=3)
self.table.grid(row=0, column=0, sticky='nswe')
EntryManager(self).grid(row=1, column=0, sticky='nswe', ipady=5)
#junk for testing
for i in range(12):
self.table.addItem(f'entry_{i}', f'data {i}')
if __name__ == '__main__':
app = App()
app.config(background='black')
app.title(App.TITLE)
app.geometry(f'{App.WIDTH}x{App.HEIGHT}')
#app.resizable(width=False, height=False)
app.mainloop()
Might as well dump the table keys in the table and see what happens. The sizes and alignments of things could use some work.

Clearing text area in Python ToDo-app GUI

I've already did a cool little CLI To-Do app in python, and now I'm trying to build a basic GUI around it. The main buttons, field in place, and yesterday I've figured out how to redirect the return string from my Todo class to the text area.
My problem now is how to clear the text area? Currently if I press the 'View button' it's continously redirecting the text without deleting the previous output. I've tried to create a function with
self.text.delete('1.0','end') + the function with the string output, but it's not working. Can you suggest me something? Thanks in advance!
import tkinter as tk
from tkinter import messagebox as mbox
from todo_app import ToDo, arguments
import sys
class ToDoGui:
def __init__(self, root):
self.t = ToDo()
self.root = root
self.mainframe = tk.Frame(self.root, bg="white")
self.mainframe.pack(fill=tk.BOTH, expand=True)
self.build_grid()
self.build_banner()
self.build_text_area()
self.build_buttons()
sys.stderr = TextRedirector(self.text, "stderr")
self.entry()
def build_grid(self):
self.mainframe.columnconfigure(0, weight=1)
self.mainframe.rowconfigure(0, weight=0)
self.mainframe.rowconfigure(1, weight=1)
self.mainframe.rowconfigure(0, weight=0)
def build_banner(self):
banner = tk.Label(
self.mainframe,
bg="orange",
text="PyKeep",
fg="green",
font=('Helvetica', 24)
)
banner.grid(
row=0, column=0,
sticky='ew',
padx=10, pady=10
)
def build_buttons(self):
buttons_frame = tk.Frame(self.mainframe)
buttons_frame.grid(row=3, column=0, sticky='nsew',
padx=10, pady=10)
buttons_frame.columnconfigure(0, weight=1)
buttons_frame.columnconfigure(1, weight=1)
buttons_frame.columnconfigure(2, weight=1)
buttons_frame.columnconfigure(3, weight=1)
buttons_frame.columnconfigure(4, weight=1)
self.clear_button = tk.Button(
buttons_frame,
text='Clear',
command=self.text.delete('0.0', tk.END)
)
self.view_button= tk.Button(
buttons_frame,
text='View list',
command=self.t.list_view
)
self.add_button = tk.Button(
buttons_frame,
text='Add task',
command=None
)
self.remove_button = tk.Button(
buttons_frame,
text='Remove task',
command=None
)
self.complete_button = tk.Button(
buttons_frame,
text='Complete task',
command=None
)
self.clear_button.grid(row=0, column=0, sticky='ew')
self.view_button.grid(row=0, column=1, sticky='ew')
self.add_button.grid(row=0, column=2, sticky='ew')
self.remove_button.grid(row=0, column=3, sticky='ew')
self.complete_button.grid(row=0, column=4, sticky='ew')
def entry(self):
entry_field = tk.Entry(self.mainframe, bd=2)
entry_field.grid(row=1, column=0, sticky='nwse', padx=10, pady=10)
entry_field.insert(0, 'Enter task OR number of a task')
entry_field.focus()
def build_text_area(self):
text_frame = tk.Text(self.mainframe, wrap="word")
text_frame.grid(row=2, column=0, sticky='nsew',
padx=10, pady=10)
text_frame.columnconfigure(0, weight=1)
text_frame.config(state=tk.DISABLED)
text_frame.tag_configure("stderr", foreground="#b22222")
self.text = text_frame
return self.text
class TextRedirector(object):
def __init__(self, widget, tag="stderr"):
self.widget = widget
self.tag = tag
def write(self, str):
self.widget.configure(state="normal")
self.widget.insert("end", str, (self.tag,))
self.widget.configure(state="disabled")
if __name__ == '__main__':
root = tk.Tk()
ToDoGui(root)
root.mainloop()
The contents you are trying to delete is not Text's contents. It's your Entry widget.
def entry(self):
entry_field = tk.Entry(self.mainframe, bd=2)
entry_field.grid(row=1, column=0, sticky='nwse', padx=10, pady=10)
entry_field.insert(0, 'Enter task OR number of a task')
entry_field.focus()
self.entry_field= entry_field #make entry widget class' object
#since there is only one row in common Entry, you need to only specify starting index
self.clear_button = tk.Button(..., command=lambda: self.entry_field.delete(0, tk.END)

Python. mysql.connector. Lack of displaying data in listbox from database

I have got problem with not displaying data in listbox in tkinter. Console don't show me any errors. In my opinion it is a problem w with second connection with database. First connection is in ConfigurationPage, second in DeletePage. In HomePage I can add new lines to database and textbox shows adding results, but in deletePage is something wrong with listbox. I hope you know what is incorrect. To ease I put some screenshots of app's working
ConfigurationPage
HomePage
DeletePage
Code:
__author__ = 'Goldsmitd'
import mysql.connector
import tkinter as tk
from tkinter import ttk
class AdressBookApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.container = tk.Frame(self)
self.container.pack(side='top')
#creating menu
menubar = tk.Menu(self.container, bg='grey')
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Save settings")
filemenu.add_separator()
filemenu.add_command(label="Exit", command=quit)
menubar.add_cascade(label="File", menu=filemenu)
optmenu = tk.Menu(menubar, tearoff=0)
optmenu.add_command(label='Configuration',
command=lambda: self.show_frame(ConfigurationPage))
menubar.add_cascade(label='Options', menu=optmenu)
tk.Tk.config(self, menu=menubar)
#creating windows
self.frames ={}
for F in (HomePage, ConfigurationPage, DeletePage):
frame = F(self.container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky='nsew')
#displaying start page
self.show_frame(ConfigurationPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class ConfigurationPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.userL = ttk.Label(self, text='user name:')
self.passL = ttk.Label(self, text='password:')
self.hostL = ttk.Label(self, text='host:')
self.dataL = ttk.Label(self, text='databse:')
self.userL.grid(row=0, column=0, pady=5, padx=5)
self.passL.grid(row=1, column=0, pady=5, padx=5)
self.hostL.grid(row=2, column=0, pady=5, padx=5)
self.dataL.grid(row=3, column=0, pady=5, padx=5)
self.userE = ttk.Entry(self)
self.passE = ttk.Entry(self)
self.hostE = ttk.Entry(self)
self.dataE = ttk.Entry(self)
self.userE.grid(row=0, column=1, pady=5, padx=5)
self.passE.grid(row=1, column=1, pady=5, padx=5)
self.hostE.grid(row=2, column=1, pady=5, padx=5)
self.dataE.grid(row=3, column=1, pady=5, padx=5)
self.userE.insert(0, 'root')
self.passE.insert(0, '')
self.hostE.insert(0, 'localhost')
self.dataE.insert(0, 'people')
#default connection to database
self.connect_base('root','','localhost','people')
#CREATING BUTTONS
self.connB = ttk.Button(self, text='connect',
command=lambda: self.connect_base(self.userE.get(),
self.passE.get(),
self.hostE.get(),
self.dataE.get()))
self.cleaB = ttk.Button(self, text='clear',
command=self.clear_click)
self.closB = ttk.Button(self, text='close',
command=lambda: controller.show_frame(HomePage))
self.connB.grid(row=4, column=0, pady=5, padx=5)
self.cleaB.grid(row=4, column=1, pady=5, padx=5)
self.closB.grid(row=4, column=2, pady=5, padx=5)
def connect_base(self,inUser,inPass,inHost,inData):
self.cnx = mysql.connector.connect(user=inUser, password=inPass, host=inHost, database=inData)
self.cursor = self.cnx.cursor()
def clear_click(self):
self.userE.delete(0,'end')
self.passE.delete(0,'end')
self.hostE.delete(0,'end')
self.dataE.delete(0,'end')
class HomePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
#Eempty label
self.emptyL = ttk.Label(self)
self.emptyL.grid(column=0, row=0)
# creating widgets
self.gnameL = ttk.Label(self, text='given name:')
self.gnameE = ttk.Entry(self, width=30)
self.gnameL.grid(column=0, row=1, pady=5, padx=5)
self.gnameE.grid(column=1, row=1, pady=5, padx=5, columnspan=2)
self.snameL = ttk.Label(self, text='surname:')
self.snameE = ttk.Entry(self, width=30)
self.snameL.grid(column=0, row=2, pady=5, padx=5)
self.snameE.grid(column=1, row=2, pady=5, padx=5, columnspan=2)
self.adressL = ttk.Label(self, text='adress:')
self.adressE = ttk.Entry(self, width=30)
self.adressL.grid(column=0, row=3, pady=5, padx=5)
self.adressE.grid(column=1, row=3, pady=5, padx=5, columnspan=2)
self.mobileL = ttk.Label(self, text='mobile:')
self.mobileE = ttk.Entry(self, width=30)
self.mobileL.grid(column=0, row=4, pady=5, padx=5)
self.mobileE.grid(column=1, row=4, pady=5, padx=5, columnspan=2)
self.emailL = ttk.Label(self, text='email:')
self.emailE = ttk.Entry(self, width=30)
self.emailL.grid(column=0, row=5, pady=5, padx=5)
self.emailE.grid(column=1, row=5, pady=5, padx=5, columnspan=2)
#creating BUTTONS
self.addB = ttk.Button(self, text='add',
command=lambda: self.add_click(controller.frames[ConfigurationPage],
self.gnameE.get(),
self.snameE.get(),
self.adressE.get(),
self.mobileE.get(),
self.emailE.get()))
self.deleteB = ttk.Button(self, text='delete',
command=lambda: app.show_frame(DeletePage))
self.clearB = ttk.Button(self, text='clear',
command=self.clear_click)
self.addB.grid(column=0, row=6, padx=5, pady=5)
self.deleteB.grid(column=1, row=6, padx=5, pady=5)
self.clearB.grid(column=2,row=6, padx=5, pady=5, sticky='w')
#creating OUTPUT
self.o1T = tk.Text(self, width=50, height=10,padx=5,pady=5, relief='ridge')
self.o1T.grid(column=4, row=1,columnspan=3, rowspan = 5)
#creating commands
def add_click(self, vessel, name1, name2, name3, name4, name5):
vessel.cursor.execute('ALTER TABLE book MODIFY `id` INT(11) NOT NULL AUTO_INCREMENT')
vessel.cursor.execute("INSERT INTO book (gname, surname, adress, mobile, email) VALUES ('%s', '%s', '%s', '%s', '%s')"\
% (name1, name2, name3, name4, name5))
vessel.cnx.commit()
vessel.cursor.execute('SELECT id, gname, surname, adress, mobile, email FROM book')
for (id, gname, surname, adress, mobile, email) in vessel.cursor:
self.o1T.insert(tk.INSERT, '\n' + '%d, %s, %s, %s, %s, %s' %(id, gname, surname, adress, mobile, email))
self.o1T.tag_configure("center", justify='center')
self.o1T.tag_add("center", 1.0, "end")
vessel.cursor.close()
vessel.cnx.close()
def clear_click(self):
self.gnameE.delete(0,'end')
self.snameE.delete(0,'end')
self.adressE.delete(0,'end')
self.mobileE.delete(0,'end')
self.emailE.delete(0,'end')
class DeletePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
#LISTBOX
self.lix = tk.Listbox(self, width=100)
self.lix.grid(rowspan=6)
for (id, gname, surname, adress, mobile, email) in controller.frames[ConfigurationPage].cursor:
self.lix.insert('end', ('%d || %s || %s || %s || %s || %s') % (id, gname, surname, adress, mobile, email))
#CREATING BUTTONS
self.okB = ttk.Button(self,text='OK',
command=lambda controller=controller:self.ok_click(controller.frames[ConfigurationPage]))
self.closeB = ttk.Button(self, text='close',
command=lambda controller=controller: self.cl_click(controller))
self.okB.grid(row=1, column=1)
self.closeB.grid(row=2, column=1)
#deleting seleceted row
def ok_click(self,vessel):
self.value = self.lix.get(self.lix.curselection()) #getting strings from selected line in istbox
self.valist = self.value.split() # converting it to list of words
self.vind = self.valist[0] # getting index
vessel.cursor.execute('DELETE FROM book WHERE id=%s' % (self.vind))
vessel.cnx.commit()
self.lix.delete('anchor')
#closing deletePage
def cl_click(self,vessel):
vessel.frames[ConfigurationPage].cursor.close()
vessel.frames[ConfigurationPage].cnx.close()
vessel.show_frame(HomePage)
app = AdressBookApp()
app.mainloop()

Categories

Resources