Python Tkinter Graph - python

I'd like to make a program which takes an integer from user and makes as many entries in a Tkinkter window. Than from those entries take data and make a graph base on them. But when i turn on my program evereything is fine only a graph is wrong. It shows me an empty graph without any data on it, with no title and no "labels names". Here is my code. Please help. I'm using Python 2.7.5, PyDev for Eclipse
# -*- coding: utf-8 -*-
import matplotlib.pyplot as mp
import Tkinter as T, sys
def end():
sys.exit()
def check():
z = e.get()
try:
z = int(z)
e.config(bg = 'green')
e.after(1000, lambda: e.config(bg = 'white'))
x = []
y = []
global x1, y1
x1 = []
y1 = []
l2 = T.Label(main, text = 'X',bg = 'yellow')
l2.pack()
for i in range(0,z):
x.append(T.Entry(main, justify = 'center'))
x[i].pack()
x1.append(x[i].get())
l3 = T.Label(main, text = 'Y', bg = '#3366ff')
l3.pack()
for i in range(0,z):
y.append(T.Entry(main, justify = 'center'))
y[i].pack()
y1.append(y[i].get())
except:
e.config(bg = 'red')
e.after(1000, lambda: e.config(bg = 'white'))
return x1,y1
def graph():
mp.ion()
mp.plot(x1,y1)
mp.title('Wykres')
mp.xlabel('x')
mp.ylabel('y')
mp.draw()
#====================================================================#
y1 = []
x1 = []
z = 0
main = T.Tk()
main.title('GRAPH')
main.geometry('600x600')
main.config(bg = "#3366ff")
e = T.Entry(main,justify = 'center')
l = T.Label(main,text = 'Podaj liczbę parametrów N =',bg = '#3366ff')
b1 = T.Button(main, text = 'OK', command = check)
b2 = T.Button(main, text = 'Rysuj', command = graph)
b = T.Button(main,text = 'Zakończ', command = end)
l.pack()
e.pack()
b1.pack()
b2.pack()
b.pack()
main.mainloop()

GB: x1, x2 have only empty strings. You have to get values from Entry in graph() function when Entry have some value - and remember to convert it from string to integer.
PL: x1, x2 zawierają tylko puste stringi. Musisz pobrać wartości z Entry w funkcji graph() kiedy Entry już zawierają jakieś wartości - i pamiętaj przekonwertować je z napisów na liczby
working code / działający kod
# -*- coding: utf-8 -*-
import matplotlib.pyplot as mp
import Tkinter as T, sys
class Application():
def __init__(self, root):
self.root = root
self.x1 = []
self.y2 = []
self.z = 0
self.root.title('GRAPH')
self.root.geometry('600x600')
self.root.config(bg="#3366ff")
self.e = T.Entry(self.root, justify='center')
self.l = T.Label(self.root, text='Podaj liczbę parametrów N =', bg='#3366ff')
self.b1 = T.Button(self.root, text='OK', command=self.check)
self.b2 = T.Button(self.root, text='Rysuj', command=self.graph)
self.b = T.Button(self.root, text='Zakończ', command=self.end)
self.l.pack()
self.e.pack()
self.b1.pack()
self.b2.pack()
self.b.pack()
#------------------------------------------------------------
def run(self):
self.root.mainloop()
#------------------------------------------------------------
def end(self):
sys.exit()
#------------------------------------------------------------
def check(self):
try:
self.entry_x = []
self.entry_y = []
self.z = int(self.e.get())
self.e.config(bg='green')
self.e.after(1000, lambda: self.e.config(bg='white'))
self.l2 = T.Label(self.root, text='X', bg='yellow')
self.l2.pack()
for i in range(self.z):
self.entry_x.append(T.Entry(self.root, justify='center'))
self.entry_x[-1].pack()
self.l3 = T.Label(self.root, text='Y', bg='#3366ff')
self.l3.pack()
for i in range(self.z):
self.entry_y.append(T.Entry(self.root, justify='center'))
self.entry_y[-1].pack()
except:
self.e.config(bg='red')
self.e.after(1000, lambda: self.e.config(bg='white'))
#------------------------------------------------------------
def graph(self):
self.x1 = []
self.y1 = []
for i in range(len(self.entry_x)):
self.x1.append(float(self.entry_x[i].get()))
for i in range(len(self.entry_y)):
self.y1.append(float(self.entry_y[i].get()))
mp.ion()
mp.plot(self.x1, self.y1)
mp.title('Wykres')
mp.xlabel('x')
mp.ylabel('y')
mp.draw()
#====================================================================#
Application(T.Tk()).run()

Related

Tkinter is opening a second windows when the first one is closing

I am creating a budget manager and I have added a textBox in the main window.
However, there seems to be a bug: When I close the window while running the script for the first time since I started my IDE, the window opens, then restarts when I close it, but I can't figure it out.
Here are all the programs:
Main
from moneyTable import moneyTable
from textBoxManager import textBox
import tkinter as tk
import fileLoader as fl
import miscAdditions as ma
import categoryAddOrRemove as caor
filesLoaded = fl.loadFile('/home/thanatos_0173/Desktop')
isFileNotEmpty = filesLoaded[0]
moneyClass = filesLoaded[1]
moneyQuantity = filesLoaded[2]
mainWindow = tk.Tk()
mainWindow.resizable(True, True)
mainWindow.title("budgetGestionnary.th")
mainWindow.attributes('-zoomed',True)
mainWindow.config(background=(ma.rgb_to_hex(100, 100, 100)))
moneyTable(mainWindow,moneyClass,moneyQuantity,350,350,isFileNotEmpty)
textBox = tk.Text(mainWindow,height=10,width = 228)
textBox.place(x=10,y=830)
textBox.config(state = tk.DISABLED)
sb = tk.Scrollbar(tk.Frame(mainWindow))
sb.pack(side=tk.RIGHT, fill=tk.BOTH)
textBox.config(yscrollcommand=sb.set)
sb.config(command=textBox.yview)
def removeCategory():
window = tk.Toplevel()
window.minsize(200,200)
window.resizable(False,False)
clicked = tk.StringVar()
clicked.set(moneyClass[0])
dropdown = tk.OptionMenu(window, clicked, *moneyClass)
dropdown.place(x=10,y=10)
def remove():
window.destroy()
elementRemoved = caor.removeElement(moneyClass,moneyQuantity,clicked.get(),moneyQuantity[moneyClass.index(clicked.get())])
moneyTable(mainWindow,elementRemoved[0],elementRemoved[1],350,350,isFileNotEmpty)
if len(moneyClass) == 0:
remove_category_button.config(state=tk.DISABLED)
button = tk.Button(window,text = "Delete category", command = remove)
button.place(x=10,y=50)
def addCategory():
window = tk.Toplevel()
window.minsize(200,200)
window.resizable(False,False)
clicked = tk.StringVar()
clicked.set('Category Name')
nameEntry = tk.Entry(window,textvariable=clicked)
nameEntry.place(x=10,y=10)
clicked2 = tk.StringVar()
clicked2.set('Category Default Money')
moneyEntry = tk.Entry(window,textvariable=clicked2)
moneyEntry.place(x=10,y=40)
def add():
window.destroy()
elementAdded = caor.addElement(moneyClass,moneyQuantity,clicked.get(),clicked2.get())
moneyTable(mainWindow,elementAdded[0],elementAdded[1],350,350,isFileNotEmpty)
remove_category_button.config(state='normal')
button = tk.Button(window,text = "Add category", command = add)
button.place(x=10,y=150)
def addMessageMain(message):
textBox.config(state = tk.NORMAL)
textBox.insert('end',message+"\n")
textBox.config(state = tk.DISABLED)
remove_category_button = tk.Button(mainWindow,text="Remove a category",command = removeCategory)
add_category_button = tk.Button(mainWindow,text="Add a category",command = addCategory)
remove_category_button.place(x=30, y=785, height=33)
add_category_button.place(x=190, y=785, height=33)
if not isFileNotEmpty:
remove_category_button.config(state=tk.DISABLED)
mainWindow.mainloop()
moneyTable.py
import tkinter as tk
from tkinter import ttk
import miscAdditions as ma
def moneyTable(window,categoryList:list,quantityList:list,sizeX:int,sizeY:int,isEmpty:bool,*arg:str):
if len(categoryList) != len(quantityList):
raise ValueError("The list:",categoryList,"haven't the same length than the list:",quantityList)
elementList = []
total = 0
for i in range(len(categoryList)):
tempList = []
tempList.append(categoryList[i])
tempList.append(str(quantityList[i])+" €")
total += quantityList[i]
elementList.append(tempList)
elementList.append(["TOTAL", str(total) + " €"])
frame = tk.LabelFrame(window)
frame.grid(padx=30, pady=30,ipadx=sizeX, ipady=sizeY, row=0)
frame.config(background=(ma.rgb_to_hex(100, 100, 100)),bd=3)
tree = ttk.Treeview(frame)
column_list = ["Category", "Money"]
tree['columns'] = column_list
tree["show"] = "headings"
for column in column_list:
tree.heading(column, text=column)
max = 0
for i in range(len(categoryList)):
if len(categoryList[i]) > max:
max = len(categoryList[i])
if column == column_list[0]:
tree.column(column, width=max*8)
else:
tree.column(column, width=50)
tree.place(relheight=1, relwidth=1)
treescrollY = tk.Scrollbar(frame)
treescrollY.configure(command=tree.yview)
tree.configure(yscrollcommand=treescrollY.set)
treescrollY.pack(side="right", fill="y")
treescrollX = tk.Scrollbar(frame, orient=tk.HORIZONTAL)
treescrollX.configure(command=tree.xview)
tree.configure(xscrollcommand=treescrollX.set)
treescrollX.pack(side="bottom", fill="x")
def handle_click(event):
if tree.identify_region(event.x, event.y) == "separator":
return "break"
tree.bind('<Button-1>', handle_click)
if not isEmpty or arg[0] == "--devmode":
ma.reloadTreeview(tree, elementList)
return tree
textBoxManager.py
import tkinter as tk
def textBox(window,x,y,height,width):
textBox = tk.Text(
window,
height=height,
width = width,
wrap = 'word'
)
textBox.place(x=x,y=y)
textBox.config(state = tk.DISABLED)
sb = tk.Scrollbar(tk.Frame(window))
sb.pack(side=tk.RIGHT, fill=tk.BOTH)
textBox.config(yscrollcommand=sb.set)
sb.config(command=textBox.yview)
return textBox
fileLoader.py
import miscAdditions as ma
import customFileSaver as cfs
#Create the arrays outside of the function to access it from other class
__spec__ = 'test'
def loadFile(defaultPath:str):
moneyComingCategory = []
moneyAvailableComingCategory = []
cfs.loadOrCreateDirectory(defaultPath,".budgetGestionnary")
defaultPath += "/.budgetGestionnary"
cfs.loadOrCreateFile(defaultPath,".savedata.txt")
with open(".savedata.txt") as f:
lines = f.readlines()
cfs.loadOrCreateDirectory(defaultPath,".removedMoney")
defaultPath += "/.removedMoney"
cfs.loadOrCreateFile(defaultPath, ".removedMoney.txt")
with open('.removedMoney.txt') as f:
lines2 = f.readlines()
removedMoneyList = []
for i in lines2:
removedMoneyList.append(ma.str_to_list(i))
if lines != []:
moneyComingCategory = ma.str_to_list(lines[0])
moneyAvailableComingCategory = [eval(i) for i in ma.str_to_list(lines[1])]
isFileNotEmpty = True
else:
isFileNotEmpty = False
return [isFileNotEmpty,moneyComingCategory,moneyAvailableComingCategory]
miscAdditions.py
import tkinter as tk
def rgb_to_hex(r, g, b):
return("#"+"0"*(2-len(hex(r)[2:]))+hex(r)[2:]+"0"*(2-len(hex(g)[2:]))+hex(g)[2:]+"0"*(2-len(hex(b)[2:]))
+ hex(b)[2:])
def str_to_list(arg):
arg = arg.split()
return arg
def list_to_string(arg):
strl1 = ""
for ele in arg:
strl1 += str(ele) + " "
return strl1
def reloadTreeview(tree, list):
tree.delete(*tree.get_children())
for row in list:
tree.insert("", "end", values=row)
def convertActualMoneyList(list, char, list1, list2):
list.clear()
total = 0
for i in range(len(list)):
tempList = []
tempList.append(list1[i])
tempList.append(str(list2[i])+" "+char)
total += list2[i]
list.append(tempList)
list.append(["TOTAL", str(total) + " €"])
return list
def disableAndEnabledDropdownWhenListContainOneElement(list, element, dropdown):
if len(list) == 1 and list == [element]:
dropdown.config(state=tk.DISABLED)
else:
dropdown.config(state="normal")
def dropdownReloader(screen,StringVar,list,dropdown,x,y):
StringVar = tk.StringVar()
StringVar.set(list[0])
dropdown = tk.OptionMenu(screen, StringVar,*list)
dropdown.place(x=x,y=y)
def listTransformer(list:list):
for k in list:
tempList = []
for i in range(len(list)):
if i <= 2:
tempList.append(k[i])
elif i == 3:
tempList.append(str(k[i]+" €"))
else:
tempVariable = ""
for v in range(4, len(k)):
tempVariable += k[v] + " "
tempList.append(tempVariable)
list[list.index(k)] = tempList
return list
space = " "
customFileSaver.py
import os
import miscAdditions as ma
def loadOrCreateDirectory(path, dirToCheckOrCreate):
os.chdir(path)
customDir = path +"/"+ dirToCheckOrCreate
if not os.path.exists(customDir):
os.system("mkdir " + dirToCheckOrCreate)
def loadOrCreateFile(path,fileToCheckOrCreate):
os.chdir(path)
customdir = path + "/" + fileToCheckOrCreate
if not os.path.exists(customdir):
os.system("touch " + fileToCheckOrCreate)
def saveRemovedMoney(list,path,fileToOpen):
os.chdir(path)
with open(fileToOpen,"a") as file:
file.write(ma.list_to_string(list)+os.linesep)
def saveActualMoney(list1,list2,path,fileToOpen):
os.chdir(path)
file = open(fileToOpen,"a")
l1 = ma.list_to_string(list1)
l2 = ma.list_to_string(list2)
file.writelines([l1+os.linesep, l2+os.linesep])
Ok. So, the error is that I imported main (testeeeeee.py) into categoryAddOrRemove. The window initialization was not in a function, so it was initializing the window at once.

How do I make it so a button can only be clicked if a condition is met that is set in another class?

In the ShowMoneyButton class, I want the activation function to only activate if self.button_activated is False, and I set it as False when the SongButton class's activation function is triggered, yet it's not registering. It stays True. Is there a way I can make it so the ShowMoneyButton class's activation function is executed only if the SongButton class's activation function is executed, except for the first time?
import tkinter as tk, random, subprocess, time, os, datetime, pprint
class Song:
def __init__(self):
self.files = []
self.path = "/users/eliasrahoui/desktop/songy"
for filename in os.listdir(self.path):
self.files.append(self.path + "/" + filename)
class Money_Value:
def __init__(self):
with open("money_counter.txt", "r") as f:
a = f.read()
a = int(a)
self.current_value = a
class Clock:
def __init__(self, root):
money = Money_Value()
self.money = money.current_value
self.root = root
self.label = tk.Label(self.root, text = "$" + str(self.money), foreground = "green", font = ('calibri', 100, 'bold'))
self.label.pack()
def countup(self, *args):
root = self.root
money_per_hour = 1000
self.money += 1
self.label['text'] = "$" + str(self.money)
self.root_id = root.after(money_per_hour, self.countup)
def stop(self):
root = self.root
root.after_cancel(self.root_id)
with open("money_counter.txt", "w") as f:
f.write(str(self.money))
def save(self):
with open("money_counter.txt", "w") as f:
f.write(str(self.money))
self.root.destroy()
class Button:
all_buttons = {}
windows = []
return_code = []
button_activated = False
def __init__(self, root, text, command):
self.text = text
button = tk.Button(root, text = text, command = command)
self.all_buttons[self.text] = button
def remove(self, button):
button.pack_forget()
def show_button(self, button):
button.pack(side ="bottom")
class SongButton(Button):
def __init__(self, root, clock):
self.root = root
self.root_clock = clock
super().__init__(self.root, text = "stop song", command = self.activation)
def activation(self):
windows = self.windows
for i in windows:
i.destroy()
code = self.return_code[-1]
code.kill()
self.remove(self.all_buttons["stop song"])
self.root_clock.countup()
self.button_activated = False
class ShowMoneyButton(Button):
def __init__(self, root, clock):
self.root = root
super().__init__(self.root, "show me the money", self.activation)
song = Song()
self.songs = song.files
money_show_button = self.all_buttons["show me the money"]
self.show_button(money_show_button)
self.pic = tk.PhotoImage(file = "/users/eliasrahoui/desktop/IMG_7465.png")
#self.button_activated = False
self.label = tk.Label(self.root, text = "")
self.root_clock = clock
def activation(self):
if self.button_activated == False:
self.root_clock.stop()
num = Money_Value()
money = num.current_value
self.label.config(text =f'Money {money}')
self.label.pack()
random_song = random.choice(self.songs)
a = SongButton(self.root, self.root_clock)
return_cod = subprocess.Popen(["afplay", random_song])
self.return_code.append(return_cod)
self.show_button(self.all_buttons["stop song"])
self.button_activated = True
for _ in range(30):
root = self.root
window = tk.Toplevel(self.root)
self.windows.append(window)
window.minsize(100, 100)
window_label = tk.Label(window, image = self.pic)
window_label.pack()
ws = root.winfo_screenwidth() # width of the screen
hs = root.winfo_screenheight() # height of the screen
x = random.randint(0, ws)
y = random.randint(0, hs)
w = 200
h = 200
window.geometry('%dx%d+%d+%d' % (w, h, x, y))
class Timer(Button):
def __init__(self, root, start_time, name, counter = False):
self.count_down_start_time = start_time
self.root = root
self.name = name
self.counter = counter
self.tmp_counter = counter
super().__init__(self.root, text = name, command = self.timer_window)
self.show_button(self.all_buttons[self.name])
self.timer_id = None
self.window_label = None
self.orignial = start_time
self.window = None
self.current_question = 1
self.questions_answered = {}
self.times = [self.orignial]
self.positive = False
self.min_max = {}
def timer_window(self):
self.window = tk.Toplevel(self.root)
self.window.geometry('%dx%d+%d+%d' % (300, 200, 500, 300))
self.window_label = tk.Label(self.window, text = "", font = ('calibri', 100, 'bold'))
self.counter_label = tk.Label(self.window, text = f'Current Question: {self.current_question}')
self.window_label.pack()
self.timer()
def timer(self):
mins, secs = divmod(self.count_down_start_time, 60)
mins = abs(mins)
secs = abs(secs)
timerr = '{:02d}:{:02d}'.format(mins, secs)
if self.count_down_start_time == -1:
self.positive = True
self.window_label["foreground"] = "red"
if self.positive:
self.count_down_start_time += 1
else:
self.count_down_start_time -= 1
self.window_label["text"] = timerr
self.window.protocol("WM_DELETE_WINDOW", self.callback)
if self.counter == True:
button = tk.Button(self.window, text = "Question Done!", command = self.counter_func)
button.pack(side = "bottom")
button_report = tk.Button(self.window, text = "Report", command = self.report)
self.counter = False
self.counter_label.pack()
button_report.pack(side = "bottom")
self.timer_id = self.window.after(1000, self.timer)
def callback(self):
self.window.after_cancel(self.timer_id)
self.window.destroy()
self.count_down_start_time = self.orignial
if self.tmp_counter == True:
self.counter = True
self.current_question = 1
self.questions_answered = {}
self.positive = False
self.times = [self.orignial]
def counter_func(self):
self.questions_answered[self.current_question] = str(datetime.timedelta(seconds = self.times[-1] - self.count_down_start_time))
self.times.append(self.count_down_start_time)
self.current_question += 1
self.counter_label["text"] = f'Current Question: {self.current_question}'
def report(self):
vals = self.times_min_max()
new_window = tk.Toplevel(self.window)
new_window.minsize(300,300)
a = self.questions_answered[1]
data_pretty = pprint.pformat(self.questions_answered)
label = tk.Label(new_window, text = data_pretty)
label.pack()
mx = {f'Maximum time took per question: {vals[0]} question numbers': vals[2]}
mn = {f'Minimum time took per question: {vals[1]} question numbers': vals[-1]}
mx_label = tk.Label(new_window, text = mx, font = ('calibri', 14, 'bold'))
mn_label = tk.Label(new_window, text = mn, font = ('calibri', 14, 'bold'))
mn_label.pack(side = "bottom")
mx_label.pack(side = "bottom")
def times_min_max(self):
f = {}
big = []
small = []
for i in range(1, len(self.questions_answered) + 1):
val = self.questions_answered[i]
if ":" in val:
q = val.split(":")
secs = int(q[-1])
mins = q[0]
secs = secs/60
secs = str(secs)
secs = secs.split(".")
secs = secs[-1]
final = mins + "." + secs
final = (float(final)) * 60
final = round(final)
f[i] = final
else:
f[i] = int(val)
max_val = max(f, key = f.get) #max(f.items(), key=operator.itemgetter(1))[0]
min_val = min(f, key=f.get)#min(f.keys(), key=(lambda key: f[key]))#min(f.items(), key = operator.intemgetter(1))[0]
min_val = f[min_val]
max_val = f[max_val]
for i in f.keys():
if f[i] == max_val:
big.append(i)
if f[i] == min_val:
small.append(i)
return (self.questions_answered[big[0]], self.questions_answered[small[0]], big, small)
main function:
import clocky_classy as cm
import tkinter as tk
root = tk.Tk()
root.minsize(400,200)
my_clock = cm.Clock(root)
money_button = cm.ShowMoneyButton(root, my_clock)
root.protocol("WM_DELETE_WINDOW", my_clock.save)
timer = cm.Timer(root, 120, "2 min timer")
timer = cm.Timer(root, 1800, "30 min timer", counter = True)
my_clock.countup()
root.mainloop()

here in this code when i select option A i am getting total = 0 as a output instead of output total = 10, how to solve it?

total = 0
def round1():
import tkinter
t =tkinter. Tk()
t.title('Round 1')
t.geometry('1000x800')
v1 = tkinter.IntVar()
def marks():
global total
if v1.get() == 1:
total = total + 10
print("total", total)
l1 = tkinter.Label(t,text = "Q 1 - Is python a case sensitive language?").grid(row = 1)
r1 = tkinter.Radiobutton(t,text = "A - true",variable = v1,value = 1).grid(row = 2)
r2 = tkinter.Radiobutton(t,text = "B - false",variable = v1,value = 2).grid(row = 3)
b = tkinter.Button(t, text = 'Submit',command = marks).place(x = 300, y = 300)
t.mainloop()
def call():
import tkinter
t = tkinter.Tk()
t.title('Instruction')
t.geometry('1000x800')
b1 = tkinter.Button(t, text = 'next',command = round1).pack()
t.mainloop()
call()
This is a well known side effect of using Tk more than once. Use Tk to create the first window, and use Toplevel to make additional windows. It works the same but you don't need a mainloop call.
Also, imports always go on the top, never in a function, and don't initialize and layout a widget on the same line (leads to common bugs).
import tkinter
total = 0
def round1():
t =tkinter.Toplevel()
t.title('Round 1')
t.geometry('1000x800')
v1 = tkinter.IntVar()
def marks():
global total
if v1.get() == 1:
total = total + 10
print("total", total)
l1 = tkinter.Label(t,text = "Q 1 - Is python a case sensitive language?")
l1.grid(row = 1)
r1 = tkinter.Radiobutton(t,text = "A - true",variable = v1,value = 1)
r1.grid(row = 2)
r2 = tkinter.Radiobutton(t,text = "B - false",variable = v1,value = 2)
r2.grid(row = 3)
b = tkinter.Button(t, text = 'Submit',command = marks)
b.place(x = 300, y = 300)
def call():
t = tkinter.Tk()
t.title('Instruction')
t.geometry('1000x800')
b1 = tkinter.Button(t, text = 'next',command = round1)
b1.pack()
t.mainloop()
call()

Widgets become invisible when i shrink my window - Tkinter - Python

I have been creating a GUI application for university using Tkinter and python.
I am however having a problem where when the application first loads, or when i make the window smaller, the only widget visible is the Plotter (extends canvas) widget. If i expand the window however, the others become visible.
This is my code:
from assign2_support import *
import tkinter as tk
from tkinter import *
from tkinter.messagebox import *
import random
from tkinter.filedialog import askopenfilename
def get_station_name(filename):
temp1 = list(filename.split("/"))
temp = list((temp1[len(temp1) - 1]).split("."))
return temp[0]
def isInDict(value, dic):
if value in dic:
return True
else:
return False
#TemperaturePlotApp class
class TemperaturePlotApp(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.stations = TemperatureData()
self.color = ['#f90909', '#ffa405', '#c0c203', '#1abd04', '#058096', '#042ee1',
'#d30af1','#ec06b3']
self.selected = dict()
self.usedColors = dict()
self.master.title("Max Temperature")
self.button = tk.Button(self, text="File", command=self.load_file, width=10)
self.button.pack(side = 'top', anchor = tk.W)
self.plotter = Plotter(self,width=850, height=400, bg="white", highlightthickness=0)
self.plotter.pack(fill='both', expand=tk.YES)
self.plotter.bind("<B1-Motion>", self.onPlotClicked)
self.plotter.bind("<Button 1>", self.onPlotClicked)
# tag all of the drawn widgets TODO delete
self.plotter.addtag_all("all")
self.df = DataFrame(self)
self.df.pack(fill = tk.X, anchor = tk.N, pady = 10)
self.sf = SelectionFrame(self)
self.sf.pack(fill = tk.X, anchor = tk.N)
self.pack(fill = 'both', side = 'left', expand = tk.YES)
def loadStation(self, stationName):
self.stations.load_data(stationName + ".txt")
def onPlotClicked(self, event):
x = event.x
year = self.ct.get_year(x)
self.df.setYear(year)
try:
self.plotter.delete(self.l)
except:
pass
self.l = self.plotter.create_line(x, 0, x, self.plotter.winfo_height(), fill = "black")
for s in self.stations.get_stations():
if self.selected[s] == True:
temp = self.stations.get_data()[s].get_temp(int(year))
print(temp)
self.df.setDatumText(s, temp)
def plotData(self):
self.plotter.delete(tk.ALL)
minY, maxY, minT, maxT = self.stations.get_ranges()
self.ct = CoordinateTranslator(self.plotter.winfo_width(),self.plotter.winfo_height(), minY, maxY, minT, maxT)
self.i = 0
data = self.stations.get_data()
for s in self.stations.get_stations():
firstRun = True
if s in self.usedColors:
pass
else:
self.usedColors[s] = random.choice(self.color)
if self.sf.isCheckButton(s) == False:
self.sf.addCheckButton(s, self.usedColors[s], lambda: self.toggleCheckButton(s))
self.selected[s] = self.stations.is_selected(self.i)
if self.selected[s] == True:
if self.df.isInDataFrameLabels(s) == False:
self.df.addDatum("", self.usedColors[s], s)
if self.df.isHidden(s) == True:
self.df.showDatum(s)
for d in data[s].get_data_points():
if firstRun:
self.lastX, self.lastY = self.ct.temperature_coords(d[0], d[1])
firstRun = False
else:
x, y = self.ct.temperature_coords(d[0], d[1])
self.plotter.create_line(self.lastX, self.lastY, x, y, fill = self.usedColors[s])
self.lastX = x
self.lastY = y
else:
self.df.hideDatum(s)
self.i = self.i + 1
def toggleCheckButton(self, stationName):
if self.selected[stationName] == True:
self.selected[stationName] = False
else:
self.selected[stationName] = True
self.plotData()
def load_file(self):
fname = askopenfilename(filetypes=([("Text files","*.txt")]))
if fname:
fn = get_station_name(fname)
self.loadStation(fn)
self.plotData()
try:
print(fname) # TODO Delete
except:
showinfo("Failed to read file", "failed to read file: " + fname)
return
# Start DataFrame class
class DataFrame(tk.Frame):
def __init__(self,parent, *args,**kwargs):
tk.Frame.__init__(self, parent,*args,**kwargs)
self.lb = dict()
self.l = tk.Label(self, text="Data for ")
self.l.pack(side = 'left')
self.year = tk.Label(self, text="")
self.year.pack(side = 'left')
self.hidden = dict()
def addDatum(self, txt, color, stationName):
l1 = tk.Label(self, text=txt, fg = color)
self.lb[stationName] = l1
l1.pack(side = 'left')
self.hidden[stationName] = False
def setDatumText(self, stationName, txt):
self.lb[stationName].configure(text = txt)
def hideDatum(self, stationName):
self.lb[stationName].pack_forget()
self.hidden[stationName] = True
def showDatum(self, stationName):
self.lb[stationName].pack(side = 'left')
self.hidden[stationName] = False
def isHidden(self, stationName):
return self.hidden[stationName]
def setYear(self, year):
self.year.configure(text = str(year) + ":")
def getDataFrameLabels(self):
return self.lb
def isInDataFrameLabels(self,stationName):
return isInDict(stationName, self.lb)
# Start SelectionFrame Class
class SelectionFrame(tk.Frame):
def __init__(self,parent,*args,**kwargs):
tk.Frame.__init__(self, parent,*args,**kwargs)
self.cb = dict()
self.l = tk.Label(self, text="Station Selection: ").pack(side = 'left')
def addCheckButton(self, text, color, com):
c = tk.Checkbutton(self, text = text, fg = color, activeforeground = color, command = com)
self.cb[text] = c
c.select()
c.pack(side = 'left')
def getCheckButtons(self):
return self.cb
def isCheckButton(self, stationName):
if stationName in self.cb:
return True
else:
return False
# Start Plotter Class
class Plotter(tk.Canvas):
def __init__(self, parent,*args,**kwargs):
Canvas.__init__(self,parent,**kwargs)
self.bind("<Configure>", self.on_resize)
self.height = self.winfo_reqheight()
self.width = self.winfo_reqwidth()
def on_resize(self,event):
# determine the ratio of old width/height to new width/height
wscale = float(event.width)/self.width
hscale = float(event.height)/self.height
self.width = event.width
self.height = event.height
# resize the canvas
self.config(width=self.width, height=self.height)
# rescale all the objects tagged with the "all" tag
self.scale("all",0,0,wscale,hscale)
#Begin TemperatureData class
class TemperatureData:
def __init__(self):
self._data = dict()
self._stationNames = list()
self._stationsSelected = list()
def load_data(self, filename):
station_name = get_station_name(filename)
self._stationNames.append(station_name)
self._stationsSelected.append(True)
station = Station(filename)
self._data[station_name] = station
def get_data(self):
return self._data
def toggle_selected(self, i):
if self._stationsSelected[i] == True:
self._stationsSelected[i] = False
else:
self._stationsSelected[i] = True
def is_selected(self, i):
return self._stationsSelected[i]
def get_stations(self):
return self._stationNames
def get_ranges(self):
min_year = None
max_year = None
min_temp = None
max_temp = None
for k, v in self._data.items():
if min_year == None or max_year == None or min_temp == None or max_temp == None:
min_year, max_year = v.get_year_range()
min_temp, max_temp = v.get_temp_range()
else:
t_min_year, t_max_year = v.get_year_range()
t_min_temp, t_max_temp = v.get_temp_range()
min_year = min(min_year, t_min_year)
max_year = max(max_year, t_max_year)
min_temp = min(min_temp, t_min_temp)
max_temp = max(max_temp, t_max_temp)
return (min_year, max_year, min_temp, max_temp)
#End TemperatureData class
# My support
def load_stations(stations_file):
"""Return the list of station names
load_stations() -> list(str)
"""
fd = open(stations_file, "r")
stations = []
for line in fd:
line = line.strip()
if not line:
continue
stations.append(line)
fd.close()
return stations
##################################################
# !!!!!! Do not change (or add to) the code below !!!!!
###################################################
def main():
root = tk.Tk()
app = TemperaturePlotApp(root)
app.pack()
root.geometry("800x400")
root.mainloop()
if __name__ == '__main__':
main()
If someone wouldnt mind pointing out to me why this is happening, i would much appreciate it, as the assignment is due in 4 hours, and i have no idea what to do.
EDIT:
assign2_support.py file code:
#
# Support for assignment 2
#
# Imports for use in your assignment
import tkinter as tk
import os.path
from tkinter import filedialog
from tkinter import messagebox
# colours for drawing lines and text
COLOURS = ['#f90909', '#ffa405', '#c0c203', '#1abd04', '#058096', '#042ee1',
'#d30af1','#ec06b3']
def load_data_points(filename):
"""Return the data contained in the given file.
load_data_points(str) -> dict(int:float)
"""
fd = open(filename, 'r')
data = {}
for line in fd:
parts = line.split(',')
data[int(parts[0])] = float(parts[1])
return data
class FileExtensionException(Exception):
pass
class Station(object):
"""A class for storing yearly average temperature data for a given station
"""
def __init__(self, stationfile):
""" Constructor: Station(str)"""
self._data = load_data_points(stationfile)
keys = self._data.keys()
self._min_year = min(keys)
self._max_year = max(keys)
temps = self._data.values()
self._min_temp = min(temps)
self._max_temp = max(temps)
base = os.path.basename(stationfile)
if not base.endswith('.txt'):
raise(FileExtensionException())
self._name = base.replace(".txt", "")
def get_temp(self, year):
"""Return the temperature average for the given year.
get_temp(int) -> float
"""
return self._data.get(year)
def get_data_points(self):
"""Return the data as a list of points in year order
get_data_points() -> list((int, float))
"""
return [(year, self._data[year]) for year in sorted(self._data.keys())]
def get_year_range(self):
""" Return the range of years in the data
get_year_range() -> (int, int)
"""
return (self._min_year, self._max_year)
def get_temp_range(self):
"""Return the range of temperatures in the data
get_temp_range() -> (float, float)
"""
return (self._min_temp, self._max_temp)
def get_name(self):
return self._name
def __repr__(self):
return "Station({0})".format(self._name)
class CoordinateTranslator(object):
"""A class which manages translation of data values into (x, y) coordinates.
The application manages real-world data (year, temp), but the Canvas
drawings require (x, y) coordinates. This class
converts between the two.
"""
def __init__(self, width, height, min_year, max_year, min_temp, max_temp):
"""
Create a CoordinateTranslator with the given canvas width/height,
the smallest and largest years and
the smallest and largest temperatures
Constructor: CoordinateTranslator(int, int, int, int, float, float)
"""
self._min_year = min_year
self._max_year = max_year
self._min_temp = min_temp
self._max_temp = max_temp
self.resize(width, height)
def resize(self, width, height):
"""Adjust the scaling factors to account for a new width/height.
After the Canvas resizes, call this method to fix the scaling.
"""
self._xscale = (self._max_year - self._min_year) / width
self._yscale = (self._max_temp - self._min_temp) / height
self._width = width
self._height = height
def temperature_coords(self, year, temperature):
"""Given a year and a temperature,
return (x, y) coordinates to plot.
temperature_coords(int, float) -> (float, float)
"""
return ((year - self._min_year)/ self._xscale,
self._height - (temperature - self._min_temp) / self._yscale)
def get_year(self, x):
"""Given an x coordinate on the Canvas, return the year that it
corresponds to.
get_year(float) -> int
"""
return int(x * self._xscale + 0.5) + self._min_year
## CSSE7030
def best_fit(points):
"""Given points are a list of (x,y) points ordered by x
this function computes the best line fit over that range and
returns the coords of end points of the line.
best_fit(list((floatt, float)) -> ((float, float), (float, float))
"""
count = len(points)
if count == 0:
# needed to avoid division by zero
# return something that will not appear on screen if drawn
return ((-1,-1), (-1, -1))
x_values = [x for x, _ in points]
y_values = [y for _, y in points]
sum_x = sum(x_values)
sum_y = sum(y_values)
sum_x2 = sum(x**2 for x in x_values)
sum_y2 = sum(y**2 for y in y_values)
sum_xy = sum(x*y for x,y in points)
x_mean = sum_x/count
y_mean = sum_y/count
slope = (sum_xy - sum_x * y_mean) / (sum_x2 - sum_x * x_mean)
y_inter = y_mean - slope * x_mean
return ((x_values[0], slope * x_values[0] + y_inter),
(x_values[-1], slope * x_values[-1] + y_inter))
Thanks heaps
Corey :)
You are creating a canvas with a requested size of 850x400. You are fixing the window size to be 800x400. Because there's not enough room in the window to fit everything in, Tkinter has to start reducing widgets, or removing widgets from view. It won't attempt to reduce a widget below its requested size, so it's not going to shrink your canvas. So, it's next option is to start hiding widgets from view.
When tkinter has to start hiding part or all of a widget from view, it starts with the widget last in the "packing list" -- the last widget to have called pack(...). Thus, if you pack the canvas last, before the bottom frame, it will be the one that starts getting shrunk below its requested size.
A simple fix is to remove the width and height attributes of the canvas, and also remove the binding on <Configure>. This lets tkinter decide the size of the canvas, which when set up properly, means that it will grow and shrink to fit the available space.
You can also save packing of the canvas to the very last, which makes it the first widget to start getting "chopped off" when there isn't enough room.
For the complete description of the packing algorithm see http://tcl.tk/man/tcl8.5/TkCmd/pack.htm#M26

Python How to clear window in tkinter

I need to clear window before I load a new map. But menu buttons have to stay. I was trying self.frame.destroy(), but it kill my menu buttons too. Basically I need to clear class Sokoban, but this class is not in class Window. Problem is in def map1(self): and def map2(self):
import tkinter
from tkinter import *
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.master.title('Sokoban')
self.pack(fill = BOTH, expand = 1)
menu = Menu(self.master)
self.master.config(menu=menu)
file = Menu(menu)
file.add_command(label='Mapa1', command = self.map1)
menu.add_cascade(label='Mapy', menu=file)
edit = Menu(menu)
edit.add_command(label='Mapa2', command = self.map2)
menu.add_cascade(label='Edit', menu=edit)
def map1(self):
self.frame.forget()
Sokoban('map1.txt')
def map2(self):
self.frame.forget()
Sokoban('map2.txt')
class Sokoban:
def __init__(self, subor):
t = open(subor, 'r')
self.pole = [None] * 8
self.box = []
for a in range(8):
self.pole[a] = list(t.readline().strip())
for b in range(len(self.pole[a])):
if self.pole[a][b] == '$':
self.player = Player(a,b)
self.pole[a][b] = '.'
if self.pole[a][b] == '#':
self.box.append(Box(a,b))
self.pole[a][b] = '.'
t.close()
self.game = self.g = tkinter.Canvas(bg = 'white', width = 650, height = 240,
cursor = 'cross')
self.g.pack()
self.farba = [['gray'],['khaki'],['#FF4500'],['yellow'],['brown']]
stena = '*'
policko = '.'
player = '$'
box = '#'
ciel = '+'
## self.newButt = self.g.create_rectangle(511, 0, 650, 45, fill = 'red')
## self.newButtText = self.g.create_text(580.5, 22.5, text = 'New Game',
## font = 'arial 19 italic bold',
## fill = 'yellow')
## self.map1Butt = self.g.create_rectangle(511, 46, 650, 86, fill = 'red')
## self.map1ButtText = self.g.create_text(580.5, 66, text = 'Map - 1',
## font = 'arial 19 italic bold',
## fill = 'yellow')
## self.map2Butt = self.g.create_rectangle(511, 87, 650, 127, fill = 'red')
## self.map2ButtText = self.g.create_text(580.5, 109, text = 'Map - 2',
## font = 'arial 19 italic bold',
## fill = 'yellow')
## self.map3Butt = self.g.create_rectangle(511, 128, 650, 168, fill = 'red')
## self.map3ButtText = self.g.create_text(580.5, 148, text = 'Map - 3',
## font = 'arial 19 italic bold',
## fill = 'yellow')
self.kresli()
self.g.bind_all('<Up>', self.up)
self.g.bind_all('<Down>', self.down)
self.g.bind_all('<Left>', self.left)
self.g.bind_all('<Right>', self.right)
## self.g.bind('<1>', self.Buttons)
def up(self, e):
self.move(-1, 0)
def down(self, e):
self.move(1, 0)
def left(self, e):
self.move(0, -1)
def right(self, e):
self.move(0, 1)
## def newGame(self):
## self.game.pack_forget()
## Sokoban()
## def map1(self):
## self.game.pack_forget()
## Sokoban('map1.txt')
##
## def map2(self):
## self.game.pack_forget()
## Sokoban('map2.txt')
## def Buttons(self, e):
## if '<1>' and self.newButt:
## self.newGame()
## if '<1>' and self.map1Butt:
## self.map1()
##
## if '<1>' and self.map2Butt:
## self.map2()
def kresli(self):
for a in range(8):
for b in range(17):
x,y = b*30, a*30
f = self.farba['*.+'.index(self.pole[a][b])]
self.g.create_rectangle(x,y,x+30,y+30,fill=f)
self.player.kresli(self.g, self.farba[3])
for box in self.box:
box.kresli(self.g, self.farba[4])
def setBox(self, r, s):
for a in range(len(self.box)):
if self.box[a].r==r and self.box[a].s==s:
return a
return -1
def move(self, dr, ds):
r = self.player.r + dr
s = self.player.s + ds
if r<0 or r>=8 or s<0 or s>=510 or self.pole[r][s] == '*':
return
c = self.setBox(r, s)
if c >= 0:
rr = r + dr
ss = s + ds
if rr < 0 or rr>=8 or ss<0 or ss>=510 or self.pole[rr][ss] == '*':
return
if self.setBox(rr, ss) >= 0:
return
self.box[c].move(dr, ds)
self.player.move(dr, ds)
for c in self.box:
if self.pole[c.r][c.s] != '+':
return
class Player:
def __init__(self, r, s):
self.r = r
self.s = s
def kresli(self, g, farba):
self.g = g
x,y = self.s*30, self.r*30
self.plr = tkinter.PhotoImage(file='player.png')
self.id1 = g.create_image(x+15, y+15, image = self.plr)
def move(self, dr, ds):
self.r = self.r + dr
self.s = self.s + ds
self.g.move(self.id1, ds*30, dr*30)
class Box:
def __init__(self, r, s):
self.r = r
self.s = s
def kresli(self, g, farba):
self.g = g
x,y = self.s*30, self.r*30
self.bx = tkinter.PhotoImage(file='box.png')
self.id2 = g.create_image(x+15, y+15, image = self.bx)
def move(self, dr, ds):
self.r = self.r + dr
self.s = self.s + ds
self.g.move(self.id2, ds*30, dr*30)
root = Tk()
root.geometry('510x240')
app = Window(root)
root.mainloop()
Sokoban()
That not-working wall of code is very hard to work with so I will try to answer your menu buttons have to stay part with an example code.
Basically you create two frames, one holds widgets going to be cleared and second one holds other widgets plus first frame.
import tkinter as tk
root = tk.Tk()
root.geometry("300x300")
frame1 = tk.Frame(root)
frame2 = tk.Frame(frame1)
frame1.pack()
frame2.pack()
menubar = tk.Menu(frame1)
menubar.add_command(label="Bring Back!", command=frame2.pack)
menubar.add_command(label="Quit!", command=root.destroy)
tk.Button(frame2, text="Forget only frame2", command=frame2.pack_forget).pack()
tk.Label(frame2, text="Label on frame2").pack()
root.config(menu=menubar)
root.mainloop()

Categories