1

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()
  • I think this is fine as a first time user (good job!), but in the future you might get better results if you work on minimizing the amount of code you submit. I expect this could be widdled down to one function posted, in which case it might even be a duplicate – en_Knight Mar 03 '16 at 14:29

1 Answers1

0

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'
Community
  • 1
  • 1
en_Knight
  • 5,301
  • 2
  • 26
  • 46