How can i erase contents in a Label? - python

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()

Related

tkinter - Printing current input + by mistake also previous inputs

I am making a GUI in Tkinter and the code prints some attributes of a class.
However, something makes it print the attributes from the current instance but also from the previous ones (sorry if the jargon is wrong, I'm really new to this).
So in the Todo-list GUI I have created, I will enter a task and specify some attributes, then print all the attributes.
The task name is then displayed in a listbox and all the attributes of the task should be printed to terminal at the same time - however, this is where it will print the current attributes which I have just entered but also the attributes from the previously added task.
This is the code and the print command is in the def show_task(): function.
from tkcalendar import * # Calendar module
import tkinter.messagebox # Import the messagebox module
task_list = []
task_types = ['Sparetime', 'School', 'Work']
class Task:
def __init__(self, n, type_, i, m, p, h): #(h, w=8, p, u, n, v):
self.name = n
self.type = type_
self.impact = i
self.manageability = m
self.proximity = p
self.hours = h
#self.connectivity = c
##self.work = w ##hours of work per day
##self.urgency = u
##self.note = n
##self.value = v
def show_tasks():
# for widget in task_frame.winfo_children():
# widget.destroy()
for task in task_list:
#listbox_tasks.insert(tkinter.END, *task_list) #(task_frame, text=f'{task.name} \n Type: {task.type} | Impact: {task.impact}| Manageability: {task.manageability} | Proximity: {task.proximity}').pack(fill='x')
print(
'Task:'+task.name +
'\n' +
'Type:' + task.type + '\n' +
'Impact:' + task.impact + '\n' +
'Manageability:' + task.manageability + '\n' +
'Proximity(Deadline):' + task.proximity + '\n' +
'Hours:' + task.hours + '\n'
)
def open_add_task():
taskwin = Toplevel(root)
taskwin.focus_force()
#TITLE
titlelabel = Label(taskwin, text='Title task concisely:').grid(column=1, row=0)
name_entry = Entry(taskwin, width=40, justify='center')
name_entry.grid(column=1, row=1)
#TYPE
typelabel = Label(taskwin, text='Type').grid(column=0, row=2)
type_var = StringVar(value=task_types[2])
OptionMenu(taskwin, type_var, *task_types).grid(column=0, row=3, sticky='nsew')
#IMPACT
impactlabel = Label(taskwin, text='Impact').grid(column=1, row=2)
imp_var = StringVar(value=0)
OptionMenu(taskwin, imp_var, *range(0, 10+1)).grid(column=1, row=3, sticky='ns')
#MANAGEABILITY
manlabel = Label(taskwin, text='Manageability').grid(column=2, row=2)
man_var = StringVar(value=0)
OptionMenu(taskwin, man_var, *range(0, 10+1)).grid(column=2, row=3, sticky='nsew')
#PROXIMITY
proximity_label = Label(taskwin, text = 'Choose a deadline', justify='center')
proximity_label.grid(column=1, row=4)
cal = Calendar(taskwin, selectmode='day', year=2021, month=4, day=27)
cal.grid(column=1, row=5)
def get_date():
proximity_output_date.config(text=cal.get_date()) ##the .config didn't work until i did .grid(column=, row=) on seperate lines
#HOURS(required)
hourlabel = Label(taskwin, text='Whole hours \n required').grid(column=1, row=16)
hour_entry = Entry(taskwin, width=4, justify='center')
hour_entry.grid(column=1, row=17)
def add_task():
if name_entry.get() != '': # If textbox inputfield is NOT empty do this:
task_list.append(Task(name_entry.get(), type_var.get(), imp_var.get(), man_var.get(), cal.get_date(), hour_entry.get()))
show_tasks()
listbox_tasks.insert(tkinter.END, name_entry.get())
name_entry.delete(0, tkinter.END)
taskwin.destroy()
else:
tkinter.messagebox.showwarning(title='Whoops', message='You must enter a task')
next_button = Button(taskwin, text='Next', command=add_task).grid(column=2, row=18, sticky='ew')
def sort_tasks():
pass
def delete_task():
pass
#try:
#task_index = listbox_tasks.curselection()[0]
#listbox_tasks.delete(task_index)
#except:
#tkinter.messagebox.showwarning(title='Oops', message='You must select a task to delete')
def save_tasks():
pass
#tasks = listbox_tasks.get(0, listbox_tasks.size())
#pickle.dump(tasks, open('tasks.dat', 'wb'))
root = Tk()
task_frame = Frame()
# Create UI
your_tasks_label = Label(root, text='THESE ARE YOUR TASKS:', font=('Roboto',10, 'bold'), justify='center')
your_tasks_label.pack()
scrollbar_tasks = tkinter.Scrollbar(root)
scrollbar_tasks.pack(side=tkinter.RIGHT, fill=tkinter.Y)
listbox_tasks = tkinter.Listbox(root, height=10, width=50, font=('Roboto',10), justify='center') # tkinter.Listbox(where it should go, height=x, width=xx)
listbox_tasks.pack()
listbox_tasks.config(yscrollcommand=scrollbar_tasks.set)
scrollbar_tasks.config(command=listbox_tasks.yview)
try:
#tasks = pickle.load(open('tasks.dat', 'rb'))
listbox_tasks.delete(0, tkinter.END)
for task in task_list:
listbox_tasks.insert(tkinter.END, task)
except:
tkinter.messagebox.showwarning(title='Phew', message='You have no tasks')
#BUTTONS
Add_Button = Button(root, text='Add New', width=42, command=open_add_task)
Add_Button.pack()
button_delete_task = Button(root, text='Delete task', width=42, command=delete_task)
button_delete_task.pack()
button_save_tasks = Button(root, text='Save tasks', width=42, command=save_tasks)
button_save_tasks.pack()
#sort_type = StringVar(value='All')
#OptionMenu(btn_frame, sort_type, 'All', *task_types).grid(column=0, row=0, sticky='nsew')
#sort_imp = StringVar(value='Any')
#OptionMenu(btn_frame, sort_imp,'Any', *range(0, 10+1)).grid(column=1, row=0, sticky='nsew')
#Button(btn_frame, text='Sort', command=sort_tasks).grid(column=1, row=1, sticky='nsew')
root.mainloop()
Replace:
for task in task_list:
with:
task = task_list[-1]
since you want to print details for a single task and not every task in the list. You'll also want to unindent the print statement.

No matter where I put "score = 0" It ignores it and comes up with an error about local variable used before assignment

On the python debugger the score is read first and I have tried globalising it to see if anything would work. Also I know the code is messy and there are better ways of doing it but I just want to solve this problem first. This is my first time using stack overflow so I don't know how to link the zip folders to the question if you are wanting to run the code. The folders contain PNG images which are named what is in the array. That bit works without any problems. This is also my first time using tkinter.
global score
score = 0
from tkinter import *
from PIL import ImageTk, Image
from random import randint
import os
root = Tk()
root.title("Flashcard")
#root.iconbitmap('c:/')
root.geometry("500x500")
global dir_path
dir_path = os.path.dirname(os.path.realpath(__file__))
def score0():
score = 0
def scoreadd():
score = score+1
def scoreminus():
score = score-1
def checkcorrectcs(comp_questions, random_number,):
answer = answer_input.get()
answer = answer.replace(" ", "")
if answer.lower() == comp_questions[random_number]:
checked = "Correct"
scoreadd()
else:
checked = "Incorrect it was " + comp_questions[random_number].title()
scoreminus()
answer_label.config(text=checked)
def checkcorrectmaths(maths, random_number2,):
answer = answer_input.get()
answer = answer.replace(" ", "")
if answer.lower() == math_questions[random_number2]:
checked = "Correct"
scoreadd()
else:
checked = "Incorrect it was " + math_questions[random_number2].title()
scoreminus()
answer_label.config(text=checked)
def checkcorrectph(physics_questions, random_number3,):
answer = answer_input.get()
answer = answer.replace(" ", "")
if answer.lower() == physics_questions[random_number3]:
checked = "Correct"
scoreadd()
else:
checked = "Incorrect it was " + physics_questions[random_number3].title()
scoreminus()
answer_label.config(text=checked)
def checkcorrectbio(biology_questions, random_number4,):
answer = answer_input.get()
answer = answer.replace(" ", "")
if answer.lower() == biology_questions[random_number4]:
checked = "Correct"
scoreadd()
else:
checked = "Incorrect it was " + biology_questions[random_number4].title()
scoreminus()
answer_label.config(text=checked)
def checkcorrectchem(chemistry_questions, random_number5,):
answer = answer_input.get()
answer = answer.replace(" ", "")
if answer.lower() == chemistry_questions[random_number5]:
checked = "Correct"
scoreadd()
else:
checked = "Incorrect it was " + chemistry_questions[random_number5].title()
scoreminus()
answer_label.config(text=checked)
#Computer science function
def computer_science():
hide_any_windows()
computer_science_window.pack(fill="both",expand=1)
title = Label(computer_science_window, text="Computer science").pack()
comp_questions = ["and", "binary", "denary", "hexadecimal", "or"]
random_number = randint(0, len(comp_questions)-1)
random_comp_question = f"{dir_path}/ComputerScienceQuestionBank/" + comp_questions[random_number] +".png"
global comp_question_photo
comp_question_photo = ImageTk.PhotoImage(Image.open(random_comp_question))
show_comp_question = Label(computer_science_window, image=comp_question_photo)
show_comp_question.pack(pady=15)
#answer box
global answer_input
answer_input = Entry(computer_science_window, font=("Comic Sans", 20))
answer_input.pack(pady = 15)
confirm_button = Button(computer_science_window, text ="Confirm", command=lambda: checkcorrectcs(comp_questions, random_number))
confirm_button.pack(pady=5)
random_button = Button(computer_science_window, text= "New question", command=computer_science)
random_button.pack(pady=10)
global answer_label
answer_label = Label(computer_science_window, text="")
answer_label.pack(pady=15)
#Maths function
def maths():
hide_any_windows()
maths_window.pack(fill="both",expand=1)
title = Label(maths_window, text="Maths").pack()
math_questions = ["144", "test2"]
random_number2 = randint(0, len(math_questions)-1)
random_math_question = f"{dir_path}/MathQuestionBank/" + math_questions[random_number2] +".png"
global math_question_photo
math_question_photo = ImageTk.PhotoImage(Image.open(random_math_question))
show_math_question = Label(maths_window, image=math_question_photo)
show_math_question.pack(pady=15)
#answer box
global answer_input
answer_input = Entry(maths_window, font=("Comic Sans", 20))
answer_input.pack(pady = 15)
confirm_button = Button(maths_window, text ="Confirm", command=lambda: checkcorrectcs(math_questions, random_number2))
confirm_button.pack(pady=5)
random_button = Button(maths_window, text= "New question", command=maths)
random_button.pack(pady=10)
global answer_label
answer_label = Label(maths_window, text="")
answer_label.pack(pady=15)
#Physics function
def physics():
hide_any_windows()
physics_window.pack(fill="both",expand=1)
title = Label(physics_window, text="Maths").pack()
physics_questions = ["9.81", "test3", "quarks", "speedoflight"]
random_number3 = randint(0, len(physics_questions)-1)
random_physics_question = f"{dir_path}/PhysicsQuestionBank/" + physics_questions[random_number3] +".png"
global physics_question_photo
physics_question_photo = ImageTk.PhotoImage(Image.open(random_physics_question))
show_physics_question = Label(physics_window, image=physics_question_photo)
show_physics_question.pack(pady=15)
#answer box
global answer_input
answer_input = Entry(physics_window, font=("Comic Sans", 20))
answer_input.pack(pady = 15)
confirm_button = Button(physics_window, text ="Confirm", command=lambda: checkcorrectph(physics_questions, random_number3))
confirm_button.pack(pady=5)
random_button = Button(physics_window, text= "New question", command=physics)
random_button.pack(pady=10)
global answer_label
answer_label = Label(physics_window, text="")
answer_label.pack(pady=15)
#Biology function
def biology():
hide_any_windows()
biology_window.pack(fill="both",expand=1)
title = Label(biology_window, text="Biology").pack()
biology_questions = ["test3", "test4"]
random_number4 = randint(0, len(biology_questions)-1)
random_biology_question = f"{dir_path}/BiologyQuestionBank/" + biology_questions[random_number4] +".png"
global biology_question_photo
biology_question_photo = ImageTk.PhotoImage(Image.open(random_biology_question))
show_biology_question = Label(biology_window, image=biology_question_photo)
show_biology_question.pack(pady=15)
#answer box
global answer_input
answer_input = Entry(biology_window, font=("Comic Sans", 20))
answer_input.pack(pady = 15)
confirm_button = Button(biology_window, text ="Confirm", command=lambda: checkcorrectbio(biology_questions, random_number4))
confirm_button.pack(pady=5)
random_button = Button(biology_window, text= "New question", command=biology)
random_button.pack(pady=10)
global answer_label
answer_label = Label(biology_window, text="")
answer_label.pack(pady=15)
#Chemistry function
def chemistry():
hide_any_windows()
chemistry_window.pack(fill="both",expand=1)
title = Label(chemistry_window, text="Chemistry").pack()
chemistry_questions = ["jameschadwick", "loweractivationenergy", "mendeleev", "postive", "protondonors",]
random_number5 = randint(0, len(chemistry_questions)-1)
random_chemistry_question = f"{dir_path}/ChemistryQuestionBank/" + chemistry_questions[random_number5] +".png"
global chemistry_question_photo
chemistry_question_photo = ImageTk.PhotoImage(Image.open(random_chemistry_question))
show_chemistry_question = Label(chemistry_window, image=chemistry_question_photo)
show_chemistry_question.pack(pady=15)
#answer box
global answer_input
answer_input = Entry(chemistry_window, font=("Comic Sans", 20))
answer_input.pack(pady = 15)
confirm_button = Button(chemistry_window, text ="Confirm", command=lambda: checkcorrectchem(chemistry_questions, random_number5))
confirm_button.pack(pady=5)
random_button = Button(chemistry_window, text= "New question", command=chemistry)
random_button.pack(pady=10)
global answer_label
answer_label = Label(chemistry_window, text="")
answer_label.pack(pady=15)
def hide_any_windows():
for widget in computer_science_window.winfo_children():
widget.destroy()
for widget in maths_window.winfo_children():
widget.destroy()
for widget in physics_window.winfo_children():
widget.destroy()
for widget in biology_window.winfo_children():
widget.destroy()
for widget in chemistry_window.winfo_children():
widget.destroy()
computer_science_window.pack_forget()
maths_window.pack_forget()
physics_window.pack_forget()
biology_window.pack_forget()
chemistry_window.pack_forget()
#menu
my_menu = Menu(root)
root.config(menu=my_menu)
#Subjects for the menu
subjects_menu = Menu(my_menu)
my_menu.add_cascade(label = "Subjects", menu=subjects_menu)
subjects_menu.add_command(label="Computer science", command=computer_science)
subjects_menu.add_command(label="Maths", command=maths)
subjects_menu.add_command(label="Physics", command=physics)
subjects_menu.add_command(label="Biology", command=biology)
subjects_menu.add_command(label="Chemistry", command=chemistry)
subjects_menu.add_separator()
subjects_menu.add_command(label="Exit", command=root.quit)
#Making the window
computer_science_window = Frame(root, width=500, height=500)
maths_window = Frame(root, width=500, height=500)
physics_window = Frame(root, width=500, height=500)
biology_window = Frame(root, width=500, height=500)
chemistry_window = Frame(root, width=500, height=500)
# all_windows = [computer_science_window, maths_window, physics_window, biology_window, chemistry_window]
root.mainloop()
You can either add a global declaration for the variable score in every function that modifies it. (easy and expedient, but not recommended)
score = 0
def score0():
global score
score = 0
def scoreadd():
global score
score = score + 1
def scoreminus():
global score
score = score - 1
or maybe create a small Score class to keep score: (recommended)
class Score:
def __init__(self):
self.score = 0
def increment(self):
self.score += 1
def decrement(self):
self.score -= 1
def reset(self):
self.score = 0
that you can use as follows:
the_score = Score()
the_score.increment()
the_score.decrement()
the_score.reset()

clearing multiple labels values

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.

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 do I backspace and clear the last equation and also a quit button?

I tried this:
self.btnquit = button(calc_frame, "Quit", tk.destroy)
self.btnquit.pack(side = LEFT)
before self.input = ...
But it came out invalid syntax. And the backspace only works if its in front of the number but I want it to be able to ackspace the last number entered, clear the last equation and then:
from tkinter import *
from tkinter.font import Font
def button(frame, text, command=None):
ft = Font(family=('Verdana'), size=14)
return Button(frame, text=text, font=ft, width=3, command=command)
def frame(frame, side=LEFT, bg="black"):
f = Frame(frame, background=bg, padx=5, pady=5)
f.pack(side=side, expand=YES, fill=BOTH)
return f
class App:
def __init__(self, tk):
ft = Font(family=('Verdana'), size=14)
main = frame(tk)
l_frame = frame(main)
r_frame = frame(main)
calc_frame = frame(l_frame)
self.input = Entry(calc_frame, font=ft, width=15, background="white")
self.input.pack(side=TOP)
self.btn_frame = frame(calc_frame)
x, y = 0, 0
for key in ("()%C", "+-*/", "1234", "5678", "90.="):
for c in key:
if c == "=":
btn = button(self.btn_frame, c, self.equalAction)
elif c == "C":
btn = button(self.btn_frame, c, self.cleanAction)
else:
btn = button(self.btn_frame, c, lambda i=c: self.input.insert(INSERT, i))
btn.grid(row=x, column=y)
y += 1
x += 1
y = 0
self.log = Text(r_frame, font=Font(family=('Verdana'), size=10), width=25, height=14, background="yellow")
self.log.pack(side=RIGHT)
def cleanAction(self):
self.input.delete(0, END)
def equalAction(self):
tmp = self.input.get()
try:
result = tmp + "=" + str(eval(tmp))
self.log.insert(1.0, result + "\n");
print(result)
except Exception:
self.log.insert(1.0, "Wrong expression\n");
if __name__ == '__main__':
root = Tk()
root.title("Calculator")
root.geometry()
app = App(root)
root.mainloop()
You can bind function to BackSpace in __init__
only when cursor (focus) is in Entry
self.input.bind_all('<BackSpace>', self.cleanInput)
or for all situations
main.bind_all('<BackSpace>', self.cleanInput)
and than you can delete text in Entry and Text
def cleanInput(self, event):
self.input.delete(0, END)
self.log.delete(1.0, END)
BTW: the same way you can bind other keys - for example digits
else:
btn = button(self.btn_frame, c, lambda i=c: self.input.insert(INSERT, i))
main.bind_all(c, lambda event, i=c:self.input.insert(INSERT, i))
EDIT:
full working code:
(issue: at that moment when cursor is in Entry numbers are inserted twice - normaly and by binding)
# python 2.x
#from Tkinter import *
#from tkFont import Font
# python 3.x
from tkinter import *
from tkinter.font import Font
class App:
def __init__(self, tk):
self.tk = tk
self.tk.title("Calculator")
#self.tk.geometry()
self.button_font = Font(family=('Verdana'), size=14)
main_frame = self.create_frame(self.tk)
left_frame = self.create_frame(main_frame)
right_frame = self.create_frame(main_frame)
calc_frame = self.create_frame(left_frame)
self.btnquit = self.create_button(calc_frame, "Quit", self.tk.destroy)
self.btnquit.pack(side = LEFT)
self.log = Text(right_frame, font=Font(family=('Verdana'), size=10), width=25, height=14, background="yellow")
self.log.pack(side=RIGHT)
self.input_text = StringVar()
self.input = Entry(calc_frame, font=self.button_font, width=15, background="white", textvariable=self.input_text)
self.input.pack(side=TOP)
btn_frame = self.create_frame(calc_frame)
for x, key in enumerate( ("()%C", "+-*/", "1234", "5678", "90.=") ):
for y, c in enumerate(key):
if c == "=":
btn = self.create_button(btn_frame, c, self.equalAction)
elif c == "C":
btn = self.create_button(btn_frame, c, self.cleanAction)
else:
btn = self.create_button(btn_frame, c, lambda number=c: self.insertNumber(number))
#main.bind_all(c, lambda event, number=c: self.insertNumber(number))
btn.grid(row=x, column=y)
self.btn_backspace = self.create_button(btn_frame, "<-", self.deleteLastDigit)
self.btn_backspace.grid(row=5, column=2, columnspan=2, sticky="we")
self.btn_loop = self.create_button(btn_frame, "LOOP", self.loopAction)
self.btn_loop.grid(row=5, column=0, columnspan=2, sticky="we")
main_frame.bind_all('<BackSpace>', self.cleanAction)
main_frame.bind_all('<Escape>', self.deleteLastDigit)
def loopAction(self):
bedmas = [ "()", "x^n", "*/", "+-" ]
for element in bedmas:
self.log.insert(INSERT,"\n"+element)
# event=None to use function in command= and in binding
def deleteLastDigit(self, event=None):
self.input_text.set( self.input_text.get()[:-1] )
def insertNumber(self, number):
self.input_text.set( self.input_text.get() + number )
def cleanAction(self):
self.input_text.set("")
self.log.delete(1.0, END)
def equalAction(self):
tmp = self.input_text.get()
try:
result = tmp + "=" + str(eval(tmp))
self.log.insert(1.0, result + "\n");
print(result)
except Exception:
self.log.insert(1.0, "Wrong expression\n");
def create_button(self, frame, text, command=None):
return Button(frame, text=text, font=self.button_font, width=3, command=command)
def create_frame(self, frame, side=LEFT, bg="black"):
f = Frame(frame, background=bg, padx=5, pady=5)
f.pack(side=side, expand=YES, fill=BOTH)
return f
def run(self):
self.tk.mainloop()
#---------------------------------------------------------------------
if __name__ == '__main__':
App(Tk()).run()

Categories

Resources