如何维护由 运行 的程序更改的变量值?
How to maintain the value of a variable that was changed by the program it was ran by?
我目前正在尝试通过 python 的标准 Tkinter 构建我的第一个 GUI 应用程序。我很快就掌握了计算机坐标系,事实上我发现我可以随心所欲地平移东西,但我开始意识到拖放功能比明确指定坐标要好得多。我很接近,但我有一个主要问题;虽然我可以保持单个小部件的坐标值相对于我最后拖动它的位置,但我不能对多个小部件执行此操作。
这是我目前创建的代码:
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()
如果我要从一对初始坐标开始,我非常希望能够删除坐标并从我离开的地方拾取,或者更确切地说,从形状离开的地方拾取。将坐标附加到文件不起作用,主要原因是退出主循环后我无法 return 更新字典的最终值。
我事先做了一些研究,研究了数据持久性。所以我第一次遇到了模块 pickle。通过其他在线示例,我设法将值 'dump' 放入另一个文件中,但是,如果某个变量(称为 a)多次更改,这些值将全部附加到文件中(这使我们回到原点) .我想知道是否有办法只存储通过变量分配给对象的最后一个值。
我会自己研究 pickle 模块,但它的术语让我不知所措,而且我不知道在数据持久性方面具体要查找什么。
我是 OP(原发帖者的互联网俚语),我相信我已经找到了问题的答案。这只是为那些可能 运行 遇到类似情况的人服务,更不用说其他人可以提供更好的解决方案,因为他们肯定存在,但这是一个 none 少。
所以,我最初的解决方案是将值存储在字典中,然后将其附加到文件中以回读,但是无法获取最终值,也就是说,我必须更新字典并将其附加到文件中,但是我无法获得最终值。
在那之后,我研究了数据持久性,在这里你给一个变量赋值,它指的是一个对象,但是,如果我给变量赋值 'foobar',和 'pickle'它,(erm ... 将其写入文件,但以字节为单位),然后将另一个值分配给 'foobar',您最终会存储这两个值,而不是为同一对象存储一个常量值。
我当时所做的是结合这两种方法,即更新字典和酸洗对象。我腌制了一本我可以更新的字典,因为它指的是同一个对象,所以只有一个值被绑定到字典。我不知道为什么这对可变序列不起作用,但我想虽然变量保持不变,但它指向多个对象,尽管我可能是错的,所以如果有人可以添加一些澄清,我将不胜感激。
所以现在一切正常,我可以将 canvas/widgets 上的项目移动到我心中的愿望。
记住,如果你需要写入一个文件,而你只想存储给定对象的单个值,其值取决于时间,请使用并读取 pickle,这里是 link:
https://docs.python.org/3.4/library/pickle.html
以下是 pickle 的实际应用示例:
这个特别描述了如何使用 pickle 保存字典:
How can I use pickle to save a dict?
很好的 wiki 参考资料:
https://wiki.python.org/moin/UsingPickle
这是最新的源代码,您可以根据自己的需要进行调整,请注意,缩进可能有误,因为将其粘贴到此处会对缩进级别造成一些奇怪的影响,但我相信您可以处理那:
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:
with open(filename, 'rb') as 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)
for i 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
with open(self.filename, 'wb') as 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})
with open(self.filename, 'wb') as shape_coords:
pickle.dump(self.coords_dict, shape_coords)
return self.ID
三件重要的事情:
你必须用列表指定坐标,或者可能是元组或其他容器(虽然我只在列表上测试过)
如果你想实际保存形状在 canvas 上的位置,请删除用于创建形状的原始坐标,否则它只会重置回原始坐标位置,所以它应该。
当您在文件所属的文件外部使用 class 时,文件会自动创建。如果文件名为 'foorbar.py',则会在同一文件夹中创建名为 'foorbar.coords.py' 的文件。如果你无论如何都碰这个,那就别碰,它会把事情搞砸的。
我知道我说了三个,但我要推动这个 'community wiki' 标志,看看它有什么作用,如果这有不良影响,我们深表歉意。
我目前正在尝试通过 python 的标准 Tkinter 构建我的第一个 GUI 应用程序。我很快就掌握了计算机坐标系,事实上我发现我可以随心所欲地平移东西,但我开始意识到拖放功能比明确指定坐标要好得多。我很接近,但我有一个主要问题;虽然我可以保持单个小部件的坐标值相对于我最后拖动它的位置,但我不能对多个小部件执行此操作。
这是我目前创建的代码:
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()
如果我要从一对初始坐标开始,我非常希望能够删除坐标并从我离开的地方拾取,或者更确切地说,从形状离开的地方拾取。将坐标附加到文件不起作用,主要原因是退出主循环后我无法 return 更新字典的最终值。
我事先做了一些研究,研究了数据持久性。所以我第一次遇到了模块 pickle。通过其他在线示例,我设法将值 'dump' 放入另一个文件中,但是,如果某个变量(称为 a)多次更改,这些值将全部附加到文件中(这使我们回到原点) .我想知道是否有办法只存储通过变量分配给对象的最后一个值。
我会自己研究 pickle 模块,但它的术语让我不知所措,而且我不知道在数据持久性方面具体要查找什么。
我是 OP(原发帖者的互联网俚语),我相信我已经找到了问题的答案。这只是为那些可能 运行 遇到类似情况的人服务,更不用说其他人可以提供更好的解决方案,因为他们肯定存在,但这是一个 none 少。
所以,我最初的解决方案是将值存储在字典中,然后将其附加到文件中以回读,但是无法获取最终值,也就是说,我必须更新字典并将其附加到文件中,但是我无法获得最终值。
在那之后,我研究了数据持久性,在这里你给一个变量赋值,它指的是一个对象,但是,如果我给变量赋值 'foobar',和 'pickle'它,(erm ... 将其写入文件,但以字节为单位),然后将另一个值分配给 'foobar',您最终会存储这两个值,而不是为同一对象存储一个常量值。
我当时所做的是结合这两种方法,即更新字典和酸洗对象。我腌制了一本我可以更新的字典,因为它指的是同一个对象,所以只有一个值被绑定到字典。我不知道为什么这对可变序列不起作用,但我想虽然变量保持不变,但它指向多个对象,尽管我可能是错的,所以如果有人可以添加一些澄清,我将不胜感激。
所以现在一切正常,我可以将 canvas/widgets 上的项目移动到我心中的愿望。
记住,如果你需要写入一个文件,而你只想存储给定对象的单个值,其值取决于时间,请使用并读取 pickle,这里是 link:
https://docs.python.org/3.4/library/pickle.html
以下是 pickle 的实际应用示例:
这个特别描述了如何使用 pickle 保存字典:
How can I use pickle to save a dict?
很好的 wiki 参考资料: https://wiki.python.org/moin/UsingPickle
这是最新的源代码,您可以根据自己的需要进行调整,请注意,缩进可能有误,因为将其粘贴到此处会对缩进级别造成一些奇怪的影响,但我相信您可以处理那:
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:
with open(filename, 'rb') as 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)
for i 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
with open(self.filename, 'wb') as 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})
with open(self.filename, 'wb') as shape_coords:
pickle.dump(self.coords_dict, shape_coords)
return self.ID
三件重要的事情:
你必须用列表指定坐标,或者可能是元组或其他容器(虽然我只在列表上测试过)
如果你想实际保存形状在 canvas 上的位置,请删除用于创建形状的原始坐标,否则它只会重置回原始坐标位置,所以它应该。
当您在文件所属的文件外部使用 class 时,文件会自动创建。如果文件名为 'foorbar.py',则会在同一文件夹中创建名为 'foorbar.coords.py' 的文件。如果你无论如何都碰这个,那就别碰,它会把事情搞砸的。
我知道我说了三个,但我要推动这个 'community wiki' 标志,看看它有什么作用,如果这有不良影响,我们深表歉意。