I am trying to create a program where you click on a Tkinter canvas and a RawTurtle moves to the mouse, but my code is not working. The canvas has a Button-1 event binded to it to tell the program the coordinates of the mouse.
But, when you click on the canvas, instead of the turtle going to the mouse, it kind of mirrors what you would expect it to do (moves away from the mosue as if another mosue is being mirrored). Both the event and the turtle position coordinates are the same when they are printed out.
Code:
import turtle
from tkinter import *
def move(event):
global t
x = event.x
y = event.y
t.setpos(x,y)
print(t.pos())
print(event)
def penState(event):
global penDown,t
if penDown == True:
t.penup()
penDown = False
else:
t.pendown()
penDown = True
def changeWidth(w):
t.pensize(w)
def changeColour(e=None):
global colourBox
t.color(colourBox.get())
colourBox.configure(fg=colourBox.get())
def doCircle():
global checkFillIsTrue,circleSizeBox
if checkFillIsTrue.get() == 1:
begin_fill()
t.circle(int(circleSizeBox.get()))
end_fill()
else:
circle(int(circleSizeBox.get()))
window = Tk('Paint')
window.title('onionPaint')
root = Frame(window)
root.pack(side=LEFT)
cv = Canvas(window,width=500,height=500)
t = turtle.RawTurtle(cv)
t.resizemode('user')
cv.bind('<Button-1>',move)
cv.bind('<Button-2>',penState)
cv.pack(side=RIGHT)
checkFillIsTrue=IntVar()
penDown = True
#Pen width box
sizeLabel = Label(root, text="Pen Width")
sizeLabel.grid()
sizeScale = Scale( root, variable = \
'var',orient=HORIZONTAL,command=changeWidth )
sizeScale.grid()
#Colour box
colourLabel = Label(root, text="Color(HEX or name):")
colourLabel.grid()
colourFrame = Frame(root)
colourFrame.grid()
colourBox = Entry(colourFrame, bd=1)
colourBox.pack(side=LEFT)
colourSubmit = Button(colourFrame,text="OK",command=changeColour)
colourSubmit.pack(side=RIGHT)
#Fill
fillLabel = Label(root,text='Fill')
fillLabel.grid()
fillFrame = Frame(root)
fillFrame.grid()
beginFill = Button(fillFrame,text='Begin Fill',command=t.begin_fill)
endFill = Button(fillFrame,text='End Fill',command=t.end_fill)
beginFill.pack(side=LEFT)
endFill.pack(side=RIGHT)
#Mmore shapes
Label(root,text='Shapes').grid()
#Circle form
Label(root,text='Circle',font=('Heveltica',8)).grid()
circleSize = Frame(root)
circleSize.grid()
circleSizeBox = Entry(circleSize,bd=1)
circleSizeBox.insert(0,'Radius')
circleSizeBox.pack(side=LEFT)
fillCheck =
Checkbutton(circleSize,text='Fill',variable=checkFillIsTrue).pack(side=LEFT)
circleSizeSubmit =
Button(circleSize,text='Draw',command=doCircle).pack(side=RIGHT)
#Text form
Label(root,text='Text',font=('Heveltica',8)).grid()
textFrame = Frame(root)
textFrame.grid()
window.mainloop()
Any help with this problem would be greatly appreciated.
Your code is a disaster. You should specifically read up on the 'global' keyword in Python and when it must be used. And Python code style in general. I believe the key fix to your program is to introduce a TurtleScreen overlay on the canvas and then switch to turtle event handing rather than tkinter event handing.
I've reworked your code below, fixing as many problems as I could:
import turtle
from tkinter import *
FONT = ('Helvetica', 8)
def move(x, y):
terrapin.setpos(x, y)
print(terrapin.pos())
def penState(x, y):
global penDown
if penDown:
terrapin.penup()
penDown = False
else:
terrapin.pendown()
penDown = True
def changeWidth(w):
terrapin.pensize(w)
def changeColour():
color = colourBox.get()
terrapin.color(color)
colourBox.configure(fg=color)
def doCircle():
radius = int(circleSizeBox.get())
if checkFillIsTrue.get():
terrapin.begin_fill()
terrapin.circle(radius)
terrapin.end_fill()
else:
terrapin.circle(radius)
window = Tk('Paint')
window.title('onionPaint')
root = Frame(window)
root.pack(side=LEFT)
canvas = Canvas(window, width=500, height=500)
screen = turtle.TurtleScreen(canvas)
terrapin = turtle.RawTurtle(screen)
screen.onclick(move, btn=1)
screen.onclick(penState, btn=2)
canvas.pack(side=RIGHT)
checkFillIsTrue = BooleanVar()
penDown = True
# Pen width box
sizeLabel = Label(root, text="Pen Width")
sizeLabel.grid()
sizeScale = Scale(root, variable='var', orient=HORIZONTAL, command=changeWidth)
sizeScale.grid()
# Colour box
colourLabel = Label(root, text="Color(HEX or name):")
colourLabel.grid()
colourFrame = Frame(root)
colourFrame.grid()
colourBox = Entry(colourFrame, bd=1)
colourBox.pack(side=LEFT)
colourSubmit = Button(colourFrame, text="OK", command=changeColour)
colourSubmit.pack(side=RIGHT)
# Fill
fillLabel = Label(root, text='Fill')
fillLabel.grid()
fillFrame = Frame(root)
fillFrame.grid()
beginFill = Button(fillFrame, text='Begin Fill', command=terrapin.begin_fill)
endFill = Button(fillFrame, text='End Fill', command=terrapin.end_fill)
beginFill.pack(side=LEFT)
endFill.pack(side=RIGHT)
# More shapes
Label(root, text='Shapes').grid()
# Circle form
Label(root, text='Circle', font=FONT).grid()
circleSize = Frame(root)
circleSize.grid()
circleSizeBox = Entry(circleSize, bd=1)
circleSizeBox.insert(0, 'Radius')
circleSizeBox.pack(side=LEFT)
fillCheck = Checkbutton(circleSize, text='Fill', variable=checkFillIsTrue).pack(side=LEFT)
circleSizeSubmit = Button(circleSize, text='Draw', command=doCircle).pack(side=RIGHT)
# Text form
Label(root, text='Text', font=FONT).grid()
textFrame = Frame(root)
textFrame.grid()
window.mainloop()
Related
So I am making an Tkinter painting application but I keep getting a Value:Error which is blocking me from proceeding and I don't know how to solve it.
here is my code
from tkinter import *
from tkinter import Scale
from tkinter import colorchooser, filedialog, messagebox
import PIL.ImageGrab as ImageGrab
class Paint(): # the class adds the screen for all the widgets to be added on
def __init__(self,root):
global color
self.root = root
self.root.title("Paint")
self.root.geometry("800x520")
self.root.configure(background='white')
self.root.resizable(100,100)
self.pen_color ="black"
self.eraser_color = "white"
# Adding the widgets
self.color_frame = LabelFrame(self.root, text='Color Palette', font=("Lucida's Caligraphy",15),bd=10, relief=RIDGE, bg='pink')
self.color_frame.place(x=0,y=0,width=145,height=190)
colors = ["#ff00ff", "#ff0000", "#ffa600", "#ffff00", "#80ff80", "#00ff00", "#09ff90", "#0ff8c0", "#00d0ff", "#00ffff", "#ffffff", "#fff3d4", "#808080", "#404040", "#202020", "#000000"]
i=j=0
for color in colors: # this is the creation for the positioning of the colors
Button(self.color_frame,bg=color,bd=2,relief=RIDGE,width=3,command=lambda col=color:self.select_color(col)).grid(row=i,column=j) # this is the creation for the color buttons
i+=1
if i==4:
i=0
j+=1
self.eraser_button = Button(self.root,text='Eraser',bg='violet',bd=2,relief=GROOVE,width=3,command=self.eraser) # this is the creation for the eraser button
self.eraser_button.place(x=0, y=187, width=60, height=30)
self.clear_button = Button(self.root,text='Clear',bg='light blue',bd=2,relief=GROOVE,width=3,command=lambda : self.canvas.delete("all")) # this is the creation for the clear button
self.clear_button.place(x=0, y=217, width=60, height=30)
self.save_button = Button(self.root,text='Save',bg='light green',bd=2,relief=GROOVE,width=3,command=self.save_paint) # this is the creation for the save button
self.save_button.place(x=0, y=247, width=60, height=30)
self.canvas_button = Button(self.root,text="Canvas",bg='light cyan', bd=4, width=8,relief=GROOVE,command=self.canvas_color) # this is the creation for the canvas button
self.canvas_button.place(x=0, y=277)
self.pen_scale_frame = LabelFrame(self.root,text='size', bg='white', bd=5, font=('arial', 15), relief=RIDGE,) # this is the creation for the box that contains the colors
self.pen_scale_frame.place(x=0, y=310, width=70, height=200)
self.pen_scale = Scale(self.pen_scale_frame, orient=VERTICAL,from_=100, to=0,length=150) # this is the creation for the scale
self.pen_scale.set(1)
self.pen_scale.place(x=5,y=10)
self.canvas = Canvas(self.root, bg='light cyan', bd=4, relief=GROOVE, width=1105, height=630) # this is the creation for the canvas
self.canvas.place(x=150, y=0)
self.canvas.bind("<B1-Motion>",self.paint) # this binds the mouse motion with the canvas
def paint(self,event): # this is the function for the ink to be shown on the canvas
x1,y1 = (event.x-0),(event.y-0)
x2,y2 = (event.x+0), (event.y+0)
self.canvas.create_oval(x1,y1,x2,y2,fill=self.pen_color,outline=self.pen_color,width=self.pen_scale.get())
def select_color(self, col): # this is the function for selecting colors for my pen
self.pen_color = col
def eraser(self): # this is the function for copying the colors that my canvas has for my eraser
self.pen_color = self.eraser_color
def canvas_color(self): # this is the function for selecting colors for my canvas
color = colorchooser.askcolor()
self.canvas.configure(background=color[1])
self.eraser_color = color[1]
self.pen_color = color[1]
def save_paint(self): # this is the function for screenshotting whatever is on the canvas
global filename
filename = filedialog.asksaveasfilename(initialdir='C:/',filetypes=[('All files','.*'), ('Picture Files','.png*')])
print(filename)
cx = self.root.winfo_rootx() + self.canvas.winfo_x()
print(cx, self.root.winfo_rootx())
cy = self.root.winfo_rooty() + self.canvas.winfo_y()
print(cy)
cx1 = cx + self.canvas.winfo_width()
print(cx1)
cy1 = cy + self.canvas.winfo_height()
print(cy1)
filename = filename + '.jpeg'
ImageGrab.grab().crop((cx1, cy1, cx, cy)).save(filename) # <-- The value:Error redirects me here
messagebox.showinfo('paint sys','image is saved as '+ str(filename))
if __name__ == "__main__":
root = Tk()
p = Paint(root)
root.mainloop()
the error
**ImageGrab.grab().crop((cx1, cy1, cx, cy)).save(filename) line 1171, in crop
raise ValueError("Coordinate 'right' is less than 'left'")
ValueError: Coordinate 'right' is less than 'left'
**
Whats wrong with my code?
I have a Python Tkinter Windows program with many buttons. I need a button to change its background color forth and back when the pointer is on it and off it. This issue has been dicussed here before, and I tried to use the code snippets given to solve my problem but did not succeed. The best solution for me would be such that the method would be on such a level that it is needed only once. In my program the user can define the background color for the buttons, however similar to all, and the pointer-on color should be able to be affected by the choice.
Below a minimal code where I have tried to use bind. randint simulates user choice. But, as said, it does not work. What changes do I require? I am new with Python and Tkinter, so please give your answer as clear changes to the code below.
import tkinter as tk
from random import randint
class PointerOnOff:
def __init__ (self, root):
root.geometry ("200x140+100+100")
color = randint (0, 2)
if color == 0:
off_color = "#aaffaa"
on_color = "#99ff99"
elif color == 1:
off_color = "#ffffaa"
on_color = "#ffff99"
else:
off_color = "#ffaaaa"
on_color = "#ff9999"
self.OK = tk.Button (root, text = "OK", bg = off_color, command = self.OKPush)
self.OK.place (x = 50, y = 20, width = 100, height = 30)
self.Cancel = tk.Button (root, text = "Cancel", bg = off_color, command = self.CancelPush)
self.Cancel.place (x = 50, y = 60, width = 100, height = 30)
self.PushedButton = tk.Label (root, text = "")
self.PushedButton.place (x = 20, y = 100, width = 160, height = 30)
def on_enter (anybutton):
anybutton.widget.config (bg = on_color)
def on_leave (anybutton):
anybutton.widget.config (bg = off_color)
self.OK.bind("<Enter>", on_enter)
self.OK.bind("<Leave>", on_leave)
self.Cancel.bind("<Enter>", on_enter)
self.Cancel.bind("<Leave>", on_leave)
def OKPush (self):
self.PushedButton.config (text = "You pushed OK button")
def CancelPush (self):
self.PushedButton.config (text = "You pushed Cancel button")
root = tk.Tk ()
master = PointerOnOff (root)
root.mainloop ()
I'm python beginner and I'm not sure of my answer but the code for changing the background color is this in my opinion:
from tkinter import *
from random import randint
t = Tk()
t.geometry('200x200')
def change_bg():
color = ("#" + str(randint(100000, 999999)))
f = Frame(t, bg=color)
f.place(x=0, y=0, width=200, height=200)
The issue is due to incorrect indentation of the two functions: on_enter() and on_leave(). They need to be inner functions inside __init__():
class PointerOnOff:
def __init__ (self, root):
...
self.PushedButton = tk.Label (root, text = "")
self.PushedButton.place (x = 20, y = 100, width = 160, height = 30)
def on_enter (anybutton):
anybutton.widget.config (bg = on_color)
def on_leave (anybutton):
anybutton.widget.config (bg = off_color)
self.OK.bind("<Enter>", on_enter)
self.OK.bind("<Leave>", on_leave)
self.Cancel.bind("<Enter>", on_enter)
self.Cancel.bind("<Leave>", on_leave)
If you don't want to call the two bindings for every button, you better create a custom button class to embed the hover feature:
class HoverButton(tk.Button):
_colors = [
# off # on
('#aaffaa', '#99ff99'),
('#ffffaa', '#ffff99'),
('#ffaaaa', '#ff9999'),
]
def __init__(self, master=None, *args, **kw):
# if "colors" option not provided, use random choice from internal colors
self._off_color, self._on_color = kw.pop("colors", self._colors[randint(0, 2)])
super().__init__(master, *args, **kw)
self["bg"] = self._off_color
self.bind("<Enter>", lambda e: self.config(bg=self._on_color))
self.bind("<Leave>", lambda e: self.config(bg=self._off_color))
Then use this custom button class for those buttons you want to have hover effect:
def class PointOnOff:
def __init___(self, root):
...
self.OK = HoverButton(root, text="OK", colors=("orange", "gold"), command=self.OKPush)
self.OK.place(x=50, y=20, width=100, height=30)
self.Cancel = HoverButton(root, text="Cancel", command=self.CancelPush)
self.Cancel.place(x=50, y=60, width=100, height=30)
...
So I have been trying to make a scrollable frame. I've had been searching and these 3 had the most impact:
https://stackoverflow.com/questions/16188420/tkinter-scrollbar-for-frame\
https://stackoverflow.com/questions/3085696/adding-a-scrollbar-to-a-group-of-widgets-in-tkinter\
How could I get a Frame with a scrollbar in Tkinter?
And I have come up with the following code:
from tkinter import *
class Test_tk_stuff():
def __init__(self):
self.screen = Tk()
self.screen.geometry("500x500")
self.structure()
self.screen.mainloop()
def scroller(self, canvas):
canvas.configure(scrollregion = canvas.bbox("all"))
def frame_expander(self, event):
canvas_width = event.width
self.canvas.itemconfig(self.frame, width = canvas_width)
def structure(self):
parent = Frame(self.screen)
parent.pack(expand = True, fill = BOTH)
self.canvas = Canvas(parent, bg = "green", highlightthickness = 0, relief = RAISED)
self.frame = Frame(self.canvas, bg = "blue")
myscrollbar = Scrollbar(parent, orient = "vertical", command = self.canvas.yview)
self.canvas.configure(yscrollcommand = myscrollbar.set)
myscrollbar.pack(side = RIGHT, fill = Y)
self.canvas.pack(side = LEFT, fill = BOTH, expand = True)
self.canvas.create_window((0, 0), window = self.frame)
# can't do: self.frame.pack(expand = True, fill = BOTH) because it will become unscrollable
# Event Bind
self.frame.bind("<Configure>", lambda event, canvas = self.canvas: self.scroller(self.canvas))
self.canvas.bind("<Configure>", self.frame_expander)
# initialize number of minimum columns
for num_columns in range(3):
self.frame.columnconfigure(num_columns, weight = 1)
a = "Button Text!"
# fill it to - 1.) test scrollbar 2.) actually using the frame inside
for place2 in range(10):
Button(self.frame, text = a, bg = "black", fg = "white").grid(row = place2, column = 1, sticky = "NSEW", ipady = 15)
if __name__ == "__main__":
Test_tk_stuff()
But somehow when I run it, it shows a _tkinter.TclError. I tried searching what that is and how to fix it, but, as you can see, I wasn't able to fix it.
Is there something wrong with my implementation?
Thanks in advance.
canvas.itemconfig() is used on canvas item returned by canvas.create_xxxxx() functions, not on tkinter widget (self.frame).
Save the canvas item ID for the self.frame and use it in canvas.itemconfig():
def frame_expander(self, event):
canvas_width = event.width
self.canvas.itemconfig(self.frame_item, width=canvas_width)
def structure(self):
...
self.frame_item = self.canvas.create_window((0, 0), window = self.frame)
...
use self.frame.config(width=canvas_width) instead of canvas.itemconfig()
I am trying to make a simple card game, something like Solitaire.
I am not experienced in coding, so forgive me if it's a simple question.
I want to move some canvas objects. New objects have the right value, but when i am dragging an already existing card it shows the wrong value (waarde in Dutch). I would like to bind the value (waarde) to a card, but don't know how to do that...
Thought about tags, binding, ID....
from tkinter import *
from random import randint
window = Tk()
deck = [1,2,3,4,5,6]
def pakkaart():
rand_card = randint(0,len(deck)-1)
global waarde
waarde = deck[rand_card]
deck.pop(rand_card)
global kaart
kaart = Canvas(window, width = 40, height = 40, bg='yellow')
kaart.place(x=50, y=50, anchor=CENTER)
kaart.create_text(20,20,text=(waarde))
kaart.bind("<B1-Motion>", drag)
def drag(event):
event.widget.place(x=event.x_root, y=event.y_root,anchor=CENTER)
print(waarde)
button1 = Button(window, text="Nieuwe Kaart", command=pakkaart)
button1.pack()
window.mainloop()
So essentially looking for a way to bind a value to a canvas.
Your above code works fine, it shows the correct value, but if you want you can try this
from tkinter import *
from random import randint
window = Tk()
ws = window.winfo_screenwidth()
hs = window.winfo_screenheight()
w = 500 # width for the Tk root
h = 300 # height for the Tk root
x = (ws / 2) - (w / 2)
y = (hs / 2) - (h / 2)
window.geometry('%dx%d+%d+%d' % (w, h, x, y))
deck = [1, 2, 3, 4, 5, 6]
def pick_card():
global waarde, kaart
rand_card = randint(0, len(deck)-1)
card_number = deck[rand_card]
deck.remove(card_number)
card = Canvas(window, width=40, height=40, bg='yellow')
card.place(x=50, y=50, anchor=CENTER)
card_number_text = card.create_text(20, 20, text=card_number, tags=card_number)
card.bind("<Button-1>", lambda event: get_number(event, card_number_text)) # or you can use: card.bind("<Button-1>", lambda event: print(card_number))
card.bind("<B1-Motion>", drag)
def drag(event):
# This is better for move a widget
cx = window.winfo_pointerx() - window.winfo_rootx()
cy = window.winfo_pointery() - window.winfo_rooty()
event.widget.place(x=cx, y=cy)
def get_number(event, number):
print(event.widget.itemcget(number, "text"))
button1 = Button(window, text="Generate Card", command=pick_card)
button1.pack()
window.mainloop()
I've modified the drag(event) function and wrote two ways for get the current card value, for store it you can use some global varibles or create a class, the second would be better
i am trying to create a list of dictionaries, based on the information I take out from the image(coordinates and image type) by selecting it with a rectangle. On button release, i want to append the dictionary extracted to an empty list. The code works fine for the first dictionary, but when i select the second triangle the dictionary i obtain overrides the first one.
Could you please come up with a solution so that in the end i get the list of dictionaries like this:
[{'bottom_right_coords': [447, 349], 'type': 'middle name', 'top_left_coords': [290, 311]}, {'bottom_right_coords': [447, 349], 'type': 'first name', 'top_left_coords': [290, 311]}, etc etc etc. ]
import Tkinter as tk
from Tkinter import *
import PIL
from PIL import Image, ImageTk
import pygame
import Pmw
from collections import OrderedDict
pygame.init()
global d, D, dict_list
global DEFAULTVALUE_OPTION
global options
DEFAULTVALUE_OPTION = "Select an option"
options = ['address',
'name',
'occupation']
d = {}
dict_list = [None] * 2000
list = range(2000)
D = OrderedDict.fromkeys(list)
class ExampleApp(tk.Tk):
def __init__(self, parent = None):
tk.Tk.__init__(self, parent)
self.x = self.y = 0
self.canvas = tk.Canvas(self, width=700, height=700, cursor="cross", relief=SUNKEN)
self.canvas.bind("<ButtonPress-1>", self.on_button_press)
self.canvas.bind("<B1-Motion>", self.on_move_press)
self.canvas.bind("<ButtonRelease-1>", self.on_button_release)
self.rect = None
self.start_x = None
self.start_y = None
self._draw_image()
def _draw_image(self):
self.sbarV = Scrollbar(self, orient=VERTICAL)
self.sbarH = Scrollbar(self, orient=HORIZONTAL)
self.sbarV.config(command=self.canvas.yview)
self.sbarH.config(command=self.canvas.xview)
self.canvas.config(yscrollcommand=self.sbarV.set)
self.canvas.config(xscrollcommand=self.sbarH.set)
self.sbarV.pack(side=RIGHT, fill=Y)
self.sbarH.pack(side=BOTTOM, fill=X)
self.canvas.pack(side="top", fill="both", expand=True)
self.im = Image.open("/home/madalina/madalina/image/page-001.jpg")
width, height = self.im.size
self.canvas.config(scrollregion=(0, 0, width, height))
self.tk_im = ImageTk.PhotoImage(self.im)
self.canvas.create_image(0,0,anchor="nw",image=self.tk_im)
def on_button_press(self, event):
# save mouse drag start position
self.start_x = event.x
self.start_y = event.y
d["top_left_coords"] = [self.start_x, self.start_y]
# create rectangle if not yet exist
#if not self.rect:
self.rect = self.canvas.create_rectangle(self.x, self.y, 100, 100, width = 2, outline = "gold")
def on_move_press(self, event):
curX, curY = (event.x, event.y)
# expand rectangle as you drag the mouse
self.canvas.coords(self.rect, self.start_x, self.start_y, curX, curY)
def on_button_release(self, event):
top = Tk()
Label(top, text="New Option").grid(row=0)
Label(top, text = "Coordinates").grid(row=1)
E1 = Entry(top, bd = 5)
E2 = Entry(top, bd = 5)
# e1 = E1.get()
# e2 = E2.get()
E1.grid(row=0, column=1)
E2.grid(row=1, column=1)
def addOption():
d["type"] = E1.get()
print d
def createDict():
dict_list.append(d)
print "lista de dictionare este " + str(dict_list)
B1 = Button(top, text = "ADD", command = addOption)
B1.grid(row=3, column=0, sticky=W, pady=4)
B1 = Button(top, text = "Create Dict", command = createDict)
B1.grid(row=3, column=1, sticky=W, pady=4)
d["bottom_right_coords"] = [event.x, event.y]
if __name__ == "__main__":
app = ExampleApp()
app.mainloop()
Finding your Problem
Let's look at this function here
def on_button_press(self, event):
# save mouse drag start position
self.start_x = event.x
self.start_y = event.y
d["top_left_coords"] = [self.start_x, self.start_y]
I like those first two lines. So I suspect that last one is the culpret.
d["top_left_coords"] = [self.start_x, self.start_y]
Not Your Problem But Worth Mentioning
My first impression was: "d is undeclared, so this will crash". Not so, since you've declared it as a global variable. So my first recomendation is: make sure you definately need a global variable there. As this 2000+ voted answer says
I imagine the reason for it is that, since global variables are so dangerous, Python wants to make sure that you really know that's what you're playing with by explicitly requiring the global keyword.
Here's somewhere to start if you want to remove globals.
If you decide global variable is the way to go, please please name it something more helpful than d
But Onto Your problem
Make d a list of dictionaries and append to it. And by the way, tuples might make more sense than lists for coordinates, since they're immutable
d = []
...
d.append({self.start_x,self.start_y})
...
#retrieving last click
print d[-1]
# adding other things to the 'last click dictionary'
d[-1]['type'] = 'foobar'