【问题标题】:How to maintain the value of a variable that was changed by the program it was ran by?如何维护由运行它的程序更改的变量的值?
【发布时间】:2015-04-26 00:27:00
【问题描述】:

我目前正在尝试通过 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()

如果我要从最初的一对坐标开始,我非常希望能够删除坐标并在我离开的地方,或者更确切地说,在形状离开的地方。将坐标附加到文件不起作用,主要原因是退出主循环后我无法返回更新字典的最终值。

我事先做了一些研究,并研究了数据持久性。所以我第一次遇到了模块,泡菜。通过其他在线示例,我设法将值“转储”到另一个文件中,但是,如果某个变量(称为 a)多次更改,则这些值都附加在文件中(这使我们回到了第一个问题)。我想知道是否有办法让它只存储通过变量分配给对象的最后一个值。

我自己会通过 pickle 模块,但它的术语让我不知所措,而且我不知道在数据持久性方面具体要查找什么。

【问题讨论】:

    标签: python python-3.x tkinter persistence tkinter-canvas


    【解决方案1】:

    我是 OP(原始海报的互联网俚语),我相信我已经找到了我的问题的答案。这只是为那些可能遇到类似情况的人服务,更不用说其他人可以提供更好的解决方案,因为我确信他们存在,但这仍然是一个。

    因此,我最初的解决方案是将值存储在字典中,然后将其附加到文件中以读取回,但是无法获得最终值,也就是说,我必须更新字典并附加它到文件中,但是我无法获得最终值。

    在那之后,我研究了数据持久性,在这里你给一个变量赋值,这个变量引用一个对象,但是,如果我给变量“foobar”赋值,然后“腌制”它,(呃.. . 将其写入文件,但以字节为单位),然后将另一个值分配给 'foobar',您最终会存储这两个值,而不是为同一个对象存储一个常量值。

    我当时所做的是将这两种方法结合起来,更新字典和腌制对象。我腌制了一个我可以更新的字典,因为它指的是同一个对象,所以只有一个值绑定到字典。我不知道为什么这对可变序列不起作用,但我想虽然变量保持不变,但它指向多个对象,尽管我可能是错的,所以如果有人可以添加一些澄清,将不胜感激。

    所以现在一切正常,我可以将画布/小部件上的项目移动到我心中的愿望。

    请记住,如果您需要写入文件,您只想为给定对象存储单个值,其值取决于时间,使用和读取泡菜,这里是链接:

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

    这里是泡菜的例子:

    这一篇特别描述了如何使用pickle保存字典:

    How can I use pickle to save a dict?

    好的维基参考: 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
    

    三个重要的事情:

    1. 你必须用一个列表指定坐标,或者可能是一个元组或其他容器(虽然我只在列表上测试过)

    2. 1234563 /p>
    3. 当您在文件所属的文件之外使用类时,文件会自动创建。如果该文件名为“foorbar.py”,则会在同一文件夹中创建名为“foorbar.coords.py”的文件。无论如何,如果你碰它,那就别碰它,它会搞砸的。

    4. 我知道我说了三个,但我会推这个“社区 wiki”标志,看看它有什么作用,如果这有不良影响,抱歉。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-25
      • 1970-01-01
      • 2014-01-23
      • 2016-09-17
      • 2013-12-04
      • 2013-05-30
      • 1970-01-01
      • 2020-06-13
      相关资源
      最近更新 更多