(Python-3) How do you maintain the value of a variable that was changed by the program it was ran by? -


i trying build first gui application through python's standard tkinter. came grips computers coordinate system, , indeed found pan things out wish, came realisation drag , drop feature far superior specifying coordinates explicitly. close, have 1 major problem; whilst can keep value of coords of single widget in relation dragged last, cannot multiple widgets.

this code have created far:

from tkinter import *  root = tk()   class move_shape:     data = {'x': 0, 'y': 0}     canvas = canvas(width = root.winfo_screenwidth(), height = root.winfo_screenheight())     shape_coords = open('shape_coords.py', 'r')        def __init__(self, shape, fill = 'white', *coords):          new_coords = self.shape_coords.readline().split(',')          if coords == (): coords = new_coords          if shape == 'line':              tag = 'line'             self.id = self.canvas.create_line(coords, tags = tag, fill = fill)          elif shape == 'rectangle':              tag = 'rect'             self.id = self.canvas.create_rectangle(coords, tags = tag, fill = fill)          ... more code          self.canvas.tag_bind(tag, '<button-1>', self.click)         self.canvas.tag_bind(tag, '<button1-motion>', self.track)         self.canvas.tag_bind(tag, '<buttonrelease-1>', self.release)         self.canvas.grid()       def click(self, event):         self.data.update({'x': event.x, 'y': event.y})         self.item = self.canvas.find_closest(self.data['x'], self.data['y'])      def track(self, event):         x, y = event.x - self.data['x'], event.y - self.data['y']         self.canvas.move(self.item, x, y)         self.data.update({'x': event.x, 'y': event.y})      def release(self, event):         self.data.update({'x': event.x, 'y': event.y})         coords = str(self.canvas.coords(self.item))         coords = coords[1:-1]         shape_coords = open ('shape_coords.py', 'a')         shape_coords.write(coords)         shape_coords.write('\n')         shape_coords.close()    move_shape('rectangle', 'blue', 50, 50, 100, 100) move_shape( 'oval', 'green', 50, 50, 100, 100) move_shape( 'arc', 'red', 50, 50, 100, 100) mainloop() 

if start initial pair of coords, able delete coords , pick left of, or rather, shape left of. appending coordinates file not work, main reason being cannot return final value of updated dictionary, after exiting mainloop.

i did research before hand, , looked data persistence. came across module, pickle, first time. through others examples online, managed 'dump' values file, however, if variable, call a, changes multiple times, values appended within file (which leads square one). know if there way make last value assigned object through variable, stored.

i go through pickle module myself, it's terminology overwhelms me, , not know in specific when comes data persistence.

i op(internet slang original poster), , believe have found answer question. serves whom may run similar situation, not mention others can provide better solutions, sure exist, 1 none less.

so, initial solution store values in dictionary, , append file read back, there no way of obtaining final value, is, had update dictionary , append file, not obtain final value.

after that, looked data persistence, assign value variable, refers object, however, if assigned value variable 'foobar', , 'pickle' it, (erm... writing file, in bytes), , assign value 'foobar', end storing both of values, rather storing 1 constant value same object.

what did then, combine these 2 approaches, of updating dictionary, , pickling objects. pickled dictionary update, , since referring same object, 1 value binded dictionary. don't know why not work mutable sequences, suppose whilst variable stays same, points multiple objects, though may wrong, if add clarification appreciated.

so works, , can move items on canvas/widgets hearts desire.

remember, if need write file want store single value given object, value in dependent on time, use , read pickle, here link:

https://docs.python.org/3.4/library/pickle.html

here exapmles of pickle in action:

this 1 in particular describes how save dict using pickle:

how can use pickle save dict?

good wiki reference: https://wiki.python.org/moin/usingpickle

here latest source code, may adapt see fit, please note, indentation may wrong, because pasting here did weird things indentation levels, sure can handle that:

from tkinter import * import pickle import os import __main__   class drag_shape:     filename = os.path.basename(__main__.__file__)     filename = filename[:filename.index('.')]+'_coords.py'     print(__main__.__file__)       if os.path.isfile(filename) == false:         foorbar = open(filename, 'w')         foorbar.close()      if os.path.getsize(filename) == 0: coords_dict = {}     else:          open(filename, 'rb') shape_cords:             coords_dict = pickle.load(shape_cords)     data = {'x': 0, 'y': 0}          def __init__(self, canvas, *coords, shape = 'rect', fill = 'white', outline = 'black', width = 1, activefill = '',          activeoutline = 'black', activewidth = 1, disabledfill = '', disabledoutline = 'black', disabledwidth = 1,         state = ''):          self.canvas = canvas         self.shape = shape.lower()         print(shape)         print(coords)         in self.coords_dict.keys():             if shape.lower() in i: shape = i.lower()          if coords != (): self.coords_dict.update({shape:coords})         else: coords = self.coords_dict[shape]          if shape in 'line':              tag = 'line'             id = canvas.create_line(coords, tags = tag, fill = fill, width = width,             activefill = activefill, activewidth = activewidth, disabledfill = disabledfill,             disabledwidth = disabledwidth, state = '')          elif shape in 'rectangle':              tag = 'rect'             id = canvas.create_rectangle(coords, tags = tag, fill = fill, outline = outline, width = width,             activefill = activefill, activeoutline = activeoutline, activewidth = activewidth, disabledfill = disabledfill,             disabledoutline = disabledoutline, disabledwidth = disabledwidth, state = '')          elif shape in 'oval':              tag = 'oval'             id = canvas.create_oval(coords, tags = tag, fill = fill, outline = outline, width = width,             activefill = activefill, activeoutline = activeoutline, activewidth = activewidth, disabledfill = disabledfill,             disabledoutline = disabledoutline, disabledwidth = disabledwidth, state = '')          elif shape in 'arc':             tag = 'arc'             id = canvas.create_arc(coords, tags = tag, fill = fill, outline = outline, width = width,             activefill = activefill, activeoutline = activeoutline, activewidth = activewidth, disabledfill = disabledfill,             disabledoutline = disabledoutline, disabledwidth = disabledwidth, state = '')          elif shape in 'polygon':              tag = 'poly'             id = canvas.create_polygon(coords, tags = tag, fill = fill, outline = outline, width = width,             activefill = activefill, activeoutline = activeoutline, activewidth = activewidth, disabledfill = disabledfill,             disabledoutline = disabledoutline, disabledwidth = disabledwidth, state = '')          elif shape in 'window':              tag = 'win'             id = canvas.create_window(coords, tags = tag, fill = fill)          elif shape in 'text':             tag = 'text'             id = canvas.create_text(coords, tags = tag, fill = fill)          elif shape in 'image':             tag = 'img'             id = canvas.create_image(coords, tags = tag, fill = fill)          elif shape in 'bitmap':              tag = 'bitmap'             id = canvas.create_bitmap(coords, tags = tag, fill = fill)          self.id = id         self.tag = tag          open(self.filename, 'wb') shape_coords:             pickle.dump(self.coords_dict, shape_coords)          canvas.tag_bind(tag, '<button-1>', self.click)         canvas.tag_bind(tag, '<button1-motion>', self.track)         canvas.tag_bind(tag, '<buttonrelease-1>', self.release)      def click(self, event):         self.data.update({'x': event.x, 'y': event.y})         self.item = self.canvas.find_closest(self.data['x'], self.data['y'])         return self.item      def track(self, event):         x, y = event.x - self.data['x'], event.y - self.data['y']         self.canvas.move(self.item, x, y)         self.data.update({'x': event.x, 'y': event.y})      def release(self, event):         self.data.update({'x': event.x, 'y': event.y})         coords = list(self.canvas.coords(self.item))         self.coords_dict.update({self.shape : coords})         open(self.filename, 'wb') shape_coords:             pickle.dump(self.coords_dict, shape_coords)         return self.id 

three important things:

  1. you must specify coords list, or possibly tuple or other containers (though have tested on lists)

  2. if want save location of shape on canvas, delete original coords used create shape, otherwise reset it's original position, , should.

  3. a file automagically created when use class outside of file belong too. if file called 'foorbar.py', file called 'foorbar.coords.py', created in same folder. if touch in anyway, don't, mess things up.

  4. i know said three, going push 'community wiki' sign , see does, sorry if has undesired effect.


Comments

Popular posts from this blog

jquery - How do you format the date used in the popover widget title of FullCalendar? -

asp.net mvc - SSO between MVCForum and Umbraco7 -

Python Tkinter keyboard using bind -