This question already has answers here:
Tkinter: AttributeError: NoneType object has no attribute <attribute name>
(4 answers)
Closed 7 years ago.
Let me start by saying I am new to Linux. I am working on modifying some code from github. The original program runs fine(a strip chart). When I try to enter the variables from the entry boxes I receive the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.2/tkinter/__init__.py", line 1426, in __call__
return self.func(*args)
File "/home/pi/SCRAP.py", line 49, in show_entry_fields
frequency = float (e1.get())
AttributeError: 'NoneType' object has no attribute 'get'
The code I have added is between the two editing start and editing end comments. Any help is greatly appreciated. The code I have is as follows:
from tkinter import *
import math, random, threading, time
class StripChart:
def __init__(self, root):
self.gf = self.makeGraph(root)
self.cf = self.makeControls(root)
self.gf.pack()
self.cf.pack()
self.Reset()
def makeGraph(self, frame):
self.sw = 1000
self.h = 200
self.top = 2
gf = Canvas(frame, width=self.sw, height=self.h+10,
bg="#002", bd=0, highlightthickness=0)
gf.p = PhotoImage(width=2*self.sw, height=self.h)
self.item = gf.create_image(0, self.top, image=gf.p, anchor=NW)
return(gf)
def makeControls(self, frame):
cf = Frame(frame, borderwidth=1, relief="raised")
Button(cf, text="Run", command=self.Run).grid(column=2, row=4)
Button(cf, text="Stop", command=self.Stop).grid(column=4, row=4)
Button(cf, text="Reset", command=self.Reset).grid(column=6, row=4)
#editing start
Button(cf, text="Cycle", command=self.show_entry_fields).grid(column=7, row=4)
Label(cf, text="Frequency(Hz)").grid(column=1, row=2)
Label(cf, text="P-P Current(mA)").grid(column=1, row=3)
global e1,e2
e1=Entry(cf).grid(column=2, row=2)
e2=Entry(cf).grid(column=2, row=3)
#editing end
self.fps = Label(cf, text="0 fps")
self.fps.grid(column=2, row=5, columnspan=5)
return(cf)
#editing start
def show_entry_fields(self):
#print("Frequency: %s\nMilliamps: %s\n" % (e1.get(),e2.get()))
frequency = float (e1.get())
currrent = float (e2.get())
#print(check_var.get())
print(frequency+1)
print(current+1)
#editing end
def Run(self):
self.go = 1
for t in threading.enumerate():
if t.name == "_gen_":
print("already running")
return
threading.Thread(target=self.do_start, name="_gen_").start()
def Stop(self):
self.go = 0
for t in threading.enumerate():
if t.name == "_gen_":
t.join()
def Reset(self):
self.Stop()
self.clearstrip(self.gf.p, '#345')
def do_start(self):
t = 0
y2 = 0
tx = time.time()
while self.go:
y1 = 0.2*math.sin(0.02*math.pi*t)
y2 = 0.9*y2 + 0.1*(random.random()-0.5)
self.scrollstrip(self.gf.p,
(0.25+y1, 0.25, 0.7+y2, 0.6, 0.7, 0.8),
( '#ff4', '#f40', '#4af', '#080', '#0f0', '#080'),
"" if t % 65 else "#088")
t += 1
if not t % 100:
tx2 = time.time()
self.fps.config(text='%d fps' % int(100/(tx2 - tx)))
tx = tx2
# time.sleep(0.001)
def clearstrip(self, p, color): # Fill strip with background color
self.bg = color # save background color for scroll
self.data = None # clear previous data
self.x = 0
p.tk.call(p, 'put', color, '-to', 0, 0, p['width'], p['height'])
def scrollstrip(self, p, data, colors, bar=""): # Scroll the strip, add new data
self.x = (self.x + 1) % self.sw # x = double buffer position
bg = bar if bar else self.bg
p.tk.call(p, 'put', bg, '-to', self.x, 0,
self.x+1, self.h)
p.tk.call(p, 'put', bg, '-to', self.x+self.sw, 0,
self.x+self.sw+1, self.h)
self.gf.coords(self.item, -1-self.x, self.top) # scroll to just-written column
if not self.data:
self.data = data
for d in range(len(data)):
y0 = int((self.h-1) * (1.0-self.data[d])) # plot all the data points
y1 = int((self.h-1) * (1.0-data[d]))
ya, yb = sorted((y0, y1))
for y in range(ya, yb+1): # connect the dots
p.put(colors[d], (self.x,y))
p.put(colors[d], (self.x+self.sw,y))
self.data = data # save for next call
def main():
root = Tk()
root.title("StripChart")
app = StripChart(root)
root.mainloop()
main()
You called grid() when you defined e1. Since you did this, e1 is set to what grid() returned, which is None:
>>> e1=Entry(cf).grid(column=2, row=2)
>>> e1
None
Instead, create the widget and then grid it on a separate line:
>>> e1=Entry(cf)
>>> e1.grid(column=2, row=2)
>>> e1
<Tkinter.Entry instance at 0x01D43BC0>
Related
In this code, lines created by mouse button in the canvas. With the help of Undo and Redo button remove these lines.
I also want to add UNDO/REDO to the Invoker so that I can go backawards and forwards through time.
from tkinter import *
root = Tk()
my_canvas = Canvas(root, bg = "white", height=500, width=500, cursor="cross")
#Draw Line using mouse
coords = {"x": 0, "y": 0, "x2": 0, "y2": 0}
final = []
lines = []
def click(e):
coords["x"] = e.x
coords["y"] = e.y
lines.append(my_canvas.create_line(coords["x"], coords["y"], coords["x"], coords["y"], fill='red', width=2))
def release(l):
lis = []
lis.append(coords["x"]);
lis.append(coords["y"]);
lis.append(coords["x2"]);
lis.append(coords["x2"])
final.append(lis)
def drag(e):
coords["x2"] = e.x
coords["y2"] = e.y
my_canvas.coords(lines[-1], coords["x"], coords["y"], coords["x2"], coords["y2"])
my_canvas.bind("<ButtonPress-1>", click)
my_canvas.bind("<B1-Motion>", drag)
my_canvas.bind('<ButtonRelease-1>', release)
def undo():
return
def redo()
return
undo_btn = Button(root, text="Undo", command=undo)
undo_btn.pack()
redo_btn = Button(root, text="Redo", command=undo)
redo_btn.pack()
my_canvas.pack()
mainloop()
You'll need to store the information of the lines to be able to undo them an play them back. For the former action, you just need the line's ID on the canvas. For the latter, you'll also need its coordinates. You can use a dataclasses.dataclass() to store the line information.
from dataclasses import dataclass
from tkinter import *
root = Tk()
my_canvas = Canvas(root, bg = "white", height=500, width=500, cursor="cross")
#Draw Line using mouse
coords = {"x": 0, "y": 0, "x2": 0, "y2": 0}
final = []
lines = []
deleted_lines = []
#dataclass
class Line:
"""Information about a drawn line."""
id: int
x: int
y: int
x2: int
y2: int
fill: str = 'red'
width: int = 2
def set_coords(self, x: int, y: int, x2: int, y2: int) -> None:
self.x = x
self.y = y
self.x2 = x2
self.y2 = y2
def click(e):
coords["x"] = e.x
coords["y"] = e.y
id_ = my_canvas.create_line(coords["x"], coords["y"], coords["x"], coords["y"], fill='red', width=2)
lines.append(Line(id_, coords["x"], coords["y"], coords["x"], coords["y"], fill='red', width=2))
def drag(e):
coords["x2"] = e.x
coords["y2"] = e.y
line = lines[-1]
my_canvas.coords(line.id, coords["x"], coords["y"], coords["x2"], coords["y2"])
line.set_coords(coords["x"], coords["y"], coords["x2"], coords["y2"])
my_canvas.bind("<ButtonPress-1>", click)
my_canvas.bind("<B1-Motion>", drag)
def undo():
try:
line = lines.pop()
except IndexError:
print('No lines to delete.')
return
deleted_lines.append(line)
my_canvas.delete(line.id)
def redo():
try:
line = deleted_lines.pop()
except IndexError:
print('No deleted lines to redo.')
return
id_ = my_canvas.create_line(line.x, line.y, line.x2, line.y2, fill=line.fill, width=line.width)
line = Line(id_, line.x, line.y, line.x2, line.y2, fill=line.fill, width=line.width)
lines.append(line)
undo_btn = Button(root, text="Undo", command=undo)
undo_btn.pack()
redo_btn = Button(root, text="Redo", command=redo)
redo_btn.pack()
my_canvas.pack()
mainloop()
I have a program written in Python, that makes a window where you can draw, using Tkinter. Every time you left-click your mouse, you make a point in your canvas. When you double-click, a polygon is made, filled with the color you chose. I found a way to change the colors from the boxes, when you right-click a box, but the problem is that the selected color is not saved and i cannot make it replace the previous one. Does anyone know how to solve this problem?
import tkinter as tk
from tkinter import colorchooser
class Point():
def __init__(self, canvas, x, y):
self.x = x
self.y = y
canvas.create_oval(x-2, y-2, x+2, y+2, fill='white')
class Poly():
def __init__(self, canvas, board, p_list=[] ):
self.p_list = p_list
self.canvas = canvas
self.board = board
def draw_poly(self):
points = []
for p in self.p_list:
points.extend([p.x, p.y])
points.extend(points[:2])
self.canvas.create_polygon(points, fill=self.board.current_color, outline=self.board.current_color)
def add_point(self, p):
self.p_list.append(p)
if len(self.p_list)>1:
p1 = self.p_list[-1]
p2 = self.p_list[-2]
self.canvas.create_line(p1.x, p1.y, p2.x, p2.y, fill="white", width=2)
class Palette():
def __init__(self, frame, board, colors):
self.colors = colors
self.board = board
self.allColors = []
for color in self.colors:
f = tk.Frame(frame, bg='lightgrey', bd=3)
f.pack(expand=1, fill='both', side='left')
if self.board.current_color == color: f.config(bg='red')
self.allColors.append(f)
l = tk.Label(f, bg=color)
l.pack(expand=1, fill='both', padx=2, pady=2)
l.bind("<1>", self.set_color)
l.bind("<Button-3>", self.do_popup)
def do_popup(self, event):
clsheet = tk.colorchooser.askcolor()
self.current_color = clsheet[1]
def set_color(self, e):
self.board.current_color = e.widget['bg']
self.selected_color(e.widget.master)
def selected_color(self, colorFrame):
for f in self.allColors: f.config(bg = 'lightgrey')
colorFrame.config(bg="red")
class Board():
def __init__(self, root):
self.colors = ['#B4FE98', '#77E4D4', '#F4EEA9', '#F0BB62', '#FF5F7E', "#9A0680"]
self.root = root
self.current_color = self.colors[0]
self.f1 = tk.Frame(self.root)
self.f1.pack(expand=1, fill='both', padx=5)
self.f2 = tk.Frame(self.root)
self.f2.pack(expand=1, fill='both')
self.canvas = tk.Canvas(self.f2, bg="#000D6B", height=550)
self.canvas.pack(expand=1, fill='both', padx=5, pady=5)
self.pallette = Palette(self.f1, self, self.colors )
self.canvas.bind("<1>", self.draw_point)
self.canvas.bind("<Double-Button-1>", self.draw_poly)
self.poly = None
def draw_point(self, evnt):
if self.poly: self.poly.add_point(Point(self.canvas, evnt.x, evnt.y))
else: self.poly = Poly(self.canvas, self, [Point(self.canvas, evnt.x, evnt.y)])
def draw_poly(self, evnt):
if self.poly and len(self.poly.p_list) > 2:
self.poly.add_point(Point(self.canvas, evnt.x, evnt.y))
self.poly.draw_poly()
self.poly = None
else: self.draw_point(evnt)
#main program
root = tk.Tk()
root.title('my program')
root.geometry("600x700")
root.resizable(0,0)
Board(root)
tk.mainloop()
To fix the part where right-clicking a color was not working i changed two things in your script:
You stored your frame widgets and their sub-widget labels in Palette.allColors. I handed over the index of the selected color to the do_popup event by using partial. Then you can simply iterate over all widgets in Palette.allColors and if the index from the event matches the index in the list, you access the children and further the !label key of those and change the background color to the selected color.
I matched Board.current_color and Palette.current_color
Most changes were made in Palette.do_popup(). Might not be the most elegant solution but it looks like its working like you intend. Full code:
import tkinter as tk
from tkinter import colorchooser
from functools import partial
class Point():
def __init__(self, canvas, x, y):
self.x = x
self.y = y
canvas.create_oval(x - 2, y - 2, x + 2, y + 2, fill='white')
class Poly():
def __init__(self, canvas, board, p_list=[]):
self.p_list = p_list
self.canvas = canvas
self.board = board
def draw_poly(self):
points = []
for p in self.p_list:
points.extend([p.x, p.y])
points.extend(points[:2])
self.canvas.create_polygon(points, fill=self.board.current_color, outline=self.board.current_color)
def add_point(self, p):
self.p_list.append(p)
if len(self.p_list) > 1:
p1 = self.p_list[-1]
p2 = self.p_list[-2]
self.canvas.create_line(p1.x, p1.y, p2.x, p2.y, fill="white", width=2)
class Palette():
def __init__(self, frame, board, colors):
self.colors = colors
self.board = board
self.allColors = []
for idx, color in enumerate(self.colors):
f = tk.Frame(frame, bg='lightgrey', bd=3)
f.pack(expand=1, fill='both', side='left')
if self.board.current_color == color: f.config(bg='red')
self.allColors.append(f)
l = tk.Label(f, bg=color)
l.pack(expand=1, fill='both', padx=2, pady=2)
l.bind("<1>", self.set_color)
l.bind("<Button-3>", partial(self.do_popup, idx))
def do_popup(self, idx, event):
clsheet = tk.colorchooser.askcolor()
self.current_color = clsheet[1].upper()
print(f"You chose: {self.current_color}")
self.board.current_color = self.current_color # required?
self.selected_color(event.widget.master)
for frm_idx, frm in enumerate(self.allColors):
if frm_idx == idx:
frm.children["!label"].config(bg=self.current_color)
def set_color(self, e):
self.board.current_color = e.widget['bg']
self.selected_color(e.widget.master)
def selected_color(self, colorFrame):
for f in self.allColors: f.config(bg='lightgrey')
colorFrame.config(bg="red")
class Board():
def __init__(self, root):
self.colors = ['#B4FE98', '#77E4D4', '#F4EEA9', '#F0BB62', '#FF5F7E', "#9A0680"]
self.root = root
self.current_color = self.colors[0]
self.f1 = tk.Frame(self.root)
self.f1.pack(expand=1, fill='both', padx=5)
self.f2 = tk.Frame(self.root)
self.f2.pack(expand=1, fill='both')
self.canvas = tk.Canvas(self.f2, bg="#000D6B", height=550)
self.canvas.pack(expand=1, fill='both', padx=5, pady=5)
self.pallette = Palette(self.f1, self, self.colors)
self.canvas.bind("<1>", self.draw_point)
self.canvas.bind("<Double-Button-1>", self.draw_poly)
self.poly = None
def draw_point(self, evnt):
if self.poly:
self.poly.add_point(Point(self.canvas, evnt.x, evnt.y))
else:
self.poly = Poly(self.canvas, self, [Point(self.canvas, evnt.x, evnt.y)])
def draw_poly(self, evnt):
if self.poly and len(self.poly.p_list) > 2:
self.poly.add_point(Point(self.canvas, evnt.x, evnt.y))
self.poly.draw_poly()
self.poly = None
else:
self.draw_point(evnt)
# main program
root = tk.Tk()
root.title('my program')
root.geometry("600x700")
root.resizable(0, 0)
Board(root)
tk.mainloop()
I'm looking for a way to create a "custom animation" for various texts. In my case, everything is done in sequence. I'm looking for a solution where when I add a widget to my method, the widget is played first after the first widget is finished
from tkinter import *
class MainWindow(Tk):
def __init__(self):
super().__init__()
self._animate = TAnimation()
self.textLabel = Label(self, bg="black", text="FontAnimation Text1", font=("Microsoft YuHei", 30))
self.textLabel.pack(fill="both", expand="yes")
self.textLabel2 = Label(self, bg="black", text="FontAnimation Text2", font=("Microsoft YuHei", 30))
self.textLabel2.pack(fill="both", expand="yes")
self._animate.animateTextColor(self.textLabel, 0, 40, 50)
self._animate.animateTextColor(self.textLabel2, 0, 120, 100) ## want to make other widgets "waiting" maybe one sec maybe 60 secs
class TAnimation(Frame):
def __init__(self):
super().__init__()
self.r = 0
self.g = 0
self.b = 0
def animateTextColor(self, widget, start, wait, speed):
if start < wait:
widget.after(wait, lambda: self.animateTextColor(widget, start, wait, speed))
start += 5
print(start)
elif start == wait:
if self.b < 255:
widget.configure(fg=self.rgbColor((self.r, self.g, self.b)))
widget.after(speed, lambda : self.animateTextColor(widget,start, wait, speed))
self.r += 1
self.g += 1
self.b += 1
else:
self.r = 0
self.g = 0
self.b = 0
def rgbColor(self, rgb):
return "#%02x%02x%02x" % rgb
if __name__ == '__main__':
mw = MainWindow()
x1, y1 = mw.winfo_screenwidth() / 2, mw.winfo_screenheight() / 2
x2, y2 = mw.winfo_screenwidth() / 4, mw.winfo_screenheight() / 4
mw.geometry("%dx%d+%d+%d" % (x1, y1, x2, y2))
mw.mainloop()
The problem here is that "widget2" assumes the same animation, actually this animation should only start when "widget1" is finished
A simple way would be to add items to a queue(list) and once one animation is completed start another.
check the example below
from tkinter import *
class MainWindow(Tk):
def __init__(self):
super().__init__()
self._animate = TAnimation()
self.textLabel = Label(self, bg="black", text="FontAnimation Text1", font=("Microsoft YuHei", 30))
self.textLabel.pack(fill="both", expand="yes")
self.textLabel2 = Label(self, bg="black", text="FontAnimation Text2", font=("Microsoft YuHei", 30))
self.textLabel2.pack(fill="both", expand="yes")
self._animate.addToQueue(self.textLabel, 5, 20)
self._animate.addToQueue(self.textLabel2, 10, 5) ## want to make other widgets "waiting" maybe one sec maybe 60 secs
class TAnimation(Frame):
def __init__(self):
super().__init__()
self.thresh = 255
def animate(self, item, wait, rgb: list):
if any(x>=self.thresh for x in rgb):
return
rgb = [x+1 for x in rgb]
item.config(fg=self.rgbColor(rgb))
self.after(wait, self.animate, item, wait, rgb)
def addToQueue(self, widget, wait, start_after: int):
self.after(start_after, self.animate, widget, wait, [0, 0, 0])
def rgbColor(self, rgb):
return "#{0:02x}{1:02x}{2:02x}".format(*rgb)
if __name__ == '__main__':
mw = MainWindow()
x1, y1 = mw.winfo_screenwidth() / 2, mw.winfo_screenheight() / 2
x2, y2 = mw.winfo_screenwidth() / 4, mw.winfo_screenheight() / 4
mw.geometry("%dx%d+%d+%d" % (x1, y1, x2, y2))
mw.mainloop()
I am trying to simulate a stellar system. I aim to manipulate the parameters via slider widgets, see the (reduced) code below. The slider widget in my code accepts a new value for the sun mass, which was set via a StellarSys instance. However the slider.set method fails with TypeError: 'NoneType' object is not subscriptable. Does somebody have a solution or can explain what I'm doing wrong? Many thanks.
import tkinter as tk
import math
class Space(tk.Frame):
def __init__(self, master, size, bg=None):
super().__init__(master)
frame = tk.Frame(self, border=5)
frame.pack()
self.width, self.height = size
self.canvas = tk.Canvas(frame, width=self.width,height=self.height,
borderwidth=0, highlightthickness=0, bg=bg)
self.canvas.pack()
self.bodies = None
def place_bodies(self):
for body in self.bodies:
x1, y1 = int(body.loc[0]-body.size/2.0),int(body.loc[1]-body.size/2.0)
x2, y2 = x1 + body.size, y1 + body.size
body.tk_id = self.canvas.create_oval(x1, y1, x2, y2, fill=body.color)
class SpaceBody:
def __init__(self, **kwargs):
self.name = kwargs['name']
self.size = kwargs['size']
self.mass = kwargs['mass']
self.loc = kwargs['loc']
self.speed = kwargs['speed']
self.color = kwargs['color']
self.dxdy = (0,0)
self.tk_id = None
def __repr__(self):
return f"\n{self.name} is {self.color}"
class Dashboard(tk.Frame):
def __init__(self, master, bg=None):
super().__init__(master)
frame = tk.Frame(self, border=5, bg=bg)
frame.pack()
sun_frame=tk.Frame(frame)
sun_frame.grid(row=1)
w, h = 15, 3
tk.Label(sun_frame, text = '').grid(row=0)
tk.Label(sun_frame, text = 'SUN MASS').grid(row=1)
self.sun_mass = tk.Scale(sun_frame, from_=0, to=1000, orient='horizontal')
self.sun_mass.bind("<ButtonRelease-1>", self.update)
# self.sun_mass.set(500) # this works
self.sun_mass.set(space.bodies[0].mass) # This doesn't work
self.sun_mass.grid(row=2)
def update(self, event):
space.bodies[0].mass = self.sun_mass.get()
print(space.bodies[0].mass)
class StellarSys:
def __init__(self):
sun = SpaceBody(name='Sun', size=30, mass=500, loc=(500,400),speed=(0, 0), color='yellow')
earth = SpaceBody(name='Earth',size=15, mass=1, loc=(500,200),speed=(15,0), color='green')
space.bodies = [sun, earth]
space.place_bodies()
# MAIN
root = tk.Tk()
root.title('UNIVERSE')
size = (1000, 800)
space = Space(root, size, bg='black')
space.grid(row=0, column = 0,sticky="nsew")
dashboard = Dashboard(root)
dashboard.grid(row=0, column = 1,sticky="nsew")
stellarsys = StellarSys()
root.mainloop()
You initialize self.bodies to None, and then try to subscript that value. As the error says, you can't use subscripts on a value of None.
You need to rework your logic so that self.bodies is a non-empty list before trying to reference an item in the list.
I was writing code for a minesweeper program but I keep on getting an error message that states that "pyimage1" does not exist. The error, I suspect originates from "def frame" and or "class control". I have seen others post similar questions yet to no avail. The images themselves block.png and flag.png are not corrupt. Previous tests show that it worked but started to fail when I integrated multiple windows(one with the visuals and the other with the control buttons)
C:\Users\akiva\PycharmProjects\helloOpencv\venv\Scripts\python.exe C:/Users/akiva/PycharmProjects/helloOpencv/operation.py
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\akiva\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:\Users\akiva\PycharmProjects\helloOpencv\mine_sweeper.py", line 72, in frame
self.canvas.create_image(x1, y1, image=self.block_pic)
File "C:\Users\akiva\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 2489, in create_image
return self._create('image', args, kw)
File "C:\Users\akiva\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 2480, in _create
*(args + self._options(cnf, kw))))
_tkinter.TclError: image "pyimage1" doesn't exist
from tkinter import *
from tkinter import Canvas
from PIL import ImageTk, Image
from time import sleep
class ResizingCanvas(Canvas):
def __init__(self,parent,**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)
class Minesweeper(Tk):
def __init__(self, master):
Tk.__init__(self)
fr = Frame(self)
fr.pack(fill=BOTH, expand=YES)
self.canvas = ResizingCanvas(fr, width=940, height=920, bg="black", highlightthickness=0)
self.count = 0
self.start = 0
self.newWindow = Toplevel(self.master)
self.app = Control(self, self.newWindow)
self.title("MineSweeper")
self.canvas.pack(fill=BOTH, expand=YES)
x1 = 20
y1 = 20
x2 = 80
y2 = 80
self.block_pic = PhotoImage(file='C:/Users/akiva/OneDrive/Desktop/akiva/Python Files/block.PNG')
self.flag_pic = PhotoImage(file='C:/Users/akiva/OneDrive/Desktop/akiva/Python Files/flag.PNG')
for k in range(14):
for i in range(15):
self.canvas.create_rectangle(x1, y1, x2, y2, fill='white')
x1 += 60
x2 += 60
x1 = 20
x2 = 80
y1 += 60
y2 += 60
def shift_image(self):
if self.count == 0:
Tk.canvas.itemconfig(self.block_pic, image=self.flag_pic)
def end(self):
self.start = 0
del self.block_pic
print("Game has ended")
self.after(2000, quit())
def frame(self):
self.start += 1
if self.start == 1:
x1 = 50
y1 = 50
for i in range(14):
for k in range(15):
self.canvas.create_image(x1, y1, image=self.block_pic)
x1 += 60
x1 = 50
y1 += 60
self.canvas.pack()
else:
print("Game has already started")
class Control(Toplevel):
def __init__(self, parent, master):
self.master = master
self.frame = Frame(self.master)
start_button = Button(self.frame, text="Start Game", command=parent.frame,)
stop_button = Button(self.frame, text="End Game", command=parent.end)
start_button.pack()
stop_button.pack()
self.quitButton = Button(self.frame, text='Quit', width=25, command=self.close_windows)
self.quitButton.pack()
self.frame.pack()
def close_windows(self):
self.master.destroy()