tkinter:如何序列化树视图?
tkinter: How to serialize a treeview?
我正在开发一个 python tkinter 应用程序,它将初始数据从 yaml 文件读取到分层 TreeView 中,以供用户进一步编辑。
要实现 "save data" 和 "undo" 功能,我应该遍历树视图并将数据重建为 python 对象以进行序列化(pickle)吗?
或者是否有一个 python 模块允许,例如,指定要保存的树视图和输出文件?
我怀疑是否有任何 Python 模块可以满足您的需求,即使有,我认为您也不想围绕使用它来构建您的应用程序。相反,您最好将事物解耦并将主要数据存储在独立于人机界面的事物中(它可能是图形化的,也可能不是图形化的,将来可能会有所不同或以其他方式更改)。这有时称为应用程序 "Model".
这样做将允许您加载和保存它,而不管当前的人机界面是什么。因此,例如,如果内部模型由一个或多个 Python 对象组成,则您可以自由使用 pickle
。或者,您可以将数据保存回 yaml 格式的文件,这将使稍后再次加载它变得轻而易举,因为程序已经可以做到这一点。
同样,当用户编辑 TreeView 时,应对模型进行等效更改以保持两者同步。
从编码中抽出一些时间来熟悉 Model–View–Controller (MVC) 设计模式。
开箱即用,答案是否定的,你不能序列化一个TreeView
。 dill
可能是开箱即用的序列化的最佳选择……它无法腌制 TreeView
对象。
>>> import ttk
>>> import Tkinter as tk
>>>
>>> f = tk.Frame()
>>> t = ttk.Treeview(f)
>>>
>>> import dill
>>> dill.pickles(t)
False
>>> dill.detect.errors(t)
PicklingError("Can't pickle 'tkapp' object: <tkapp object at 0x10eda75e0>",)
>>>
您可能会想出如何 pickle TreeView
,然后将该方法添加到 pickle
注册表中……但是,这可能需要您付出一些认真的努力才能找到答案事情如何失败。
你可以看到发生了什么,它击中了 Tkinter.Tk
对象的 __dict__
,并在尝试 pickle something.
时死了
>>> dill.detect.trace(True)
>>> dill.dumps(t)
C2: ttk.Treeview
D2: <dict object at 0x1147f5168>
C2: Tkinter.Frame
D2: <dict object at 0x1147f1050>
C2: Tkinter.Tk
D2: <dict object at 0x1148035c8>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.3.dev0-py2.7.egg/dill/dill.py", line 194, in dumps
dump(obj, file, protocol, byref, fmode)#, strictio)
File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.3.dev0-py2.7.egg/dill/dill.py", line 184, in dump
pik.dump(obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
self.save(obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 725, in save_inst
save(stuff)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.3.dev0-py2.7.egg/dill/dill.py", line 678, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 681, in _batch_setitems
save(v)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 725, in save_inst
save(stuff)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.3.dev0-py2.7.egg/dill/dill.py", line 678, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 681, in _batch_setitems
save(v)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 725, in save_inst
save(stuff)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.3.dev0-py2.7.egg/dill/dill.py", line 678, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 681, in _batch_setitems
save(v)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 313, in save
(t.__name__, obj))
pickle.PicklingError: Can't pickle 'tkapp' object: <tkapp object at 0x10eda7648>
>>>
那个东西是一个tkapp
对象。
因此,如果您想进一步挖掘,可以使用 dill.detect
中的方法来帮助您准确地发现它没有酸洗的原因……并尝试绕过它。
我怀疑 pickle 小部件是否正确。您可能也不想走将状态从 treeview
拉出到影子 class 并保存 class 的路线。问题是树视图并没有真正考虑到保存状态的良好分离。
如果您可以重新设计以将应用程序的 state 与 widgets 本身完全分开,那么这更有可能实现您的目标想。所以,当你问 How to serialize a treeview
时,这真的不是你要问的。您想知道如何保存应用程序的状态。
有些包可以很容易地完成类似的事情。我建议您查看 enaml
and/or traits
。 enaml
是一个声明性标记,要求您构建一个 class 来描述您的应用程序界面的工作方式。它迫使您将要显示的内容的内部工作与操作用户界面所必需的代码分开……并且它以一种非常容易构建的方式实现——应用程序的状态与用户界面是分开的接线。因此,您构建的 class 的实例随时包含应用程序的状态——无论它是否有一个 UI,或者两个或三个 UI对于这个问题。它使保存应用程序的状态变得非常容易,因为您永远不必
担心 保存 UI 的状态——UI 没有状态——它只是绘制在应用程序顶部的布局。然后你就不用担心酸洗小部件了……
在此处查看 enaml
:https://github.com/nucleic/enaml
和traits
这里:http://docs.enthought.com/traits
另一个问答展示了如何在退出时 pickle 树视图并在启动时重新加载它:
OP 的信息如下:
#----------TreeViewlist----------------------
Header =['Website','Username','Password','etc']
树状视图的要点是记录OP访问的每个网站,使用的用户ID和使用的密码。
总结接受的答案:
退出时将树视图保存到 pickle
x=[tree.item(x)['values'] for x in tree.get_children()]
filehandler = open('data.pickle', 'wb')
pickle.dump(x,filehandler)
filehandler.close()
加载 pickle 以在启动时构建树视图
items = []
try:
filehandler = open('data.pickle', 'rb')
items = pickle.load(filehandler)
filehandler.close()
except:
pass
for item in items:
tree.insert('','end',values=item)
答案似乎很直接(对我来说),但如果您有任何问题 post 请在下方发表评论。如果您在代码 post 中发现缺陷或错误,请在上面的 link 中发表评论。
我正在开发一个 python tkinter 应用程序,它将初始数据从 yaml 文件读取到分层 TreeView 中,以供用户进一步编辑。
要实现 "save data" 和 "undo" 功能,我应该遍历树视图并将数据重建为 python 对象以进行序列化(pickle)吗? 或者是否有一个 python 模块允许,例如,指定要保存的树视图和输出文件?
我怀疑是否有任何 Python 模块可以满足您的需求,即使有,我认为您也不想围绕使用它来构建您的应用程序。相反,您最好将事物解耦并将主要数据存储在独立于人机界面的事物中(它可能是图形化的,也可能不是图形化的,将来可能会有所不同或以其他方式更改)。这有时称为应用程序 "Model".
这样做将允许您加载和保存它,而不管当前的人机界面是什么。因此,例如,如果内部模型由一个或多个 Python 对象组成,则您可以自由使用 pickle
。或者,您可以将数据保存回 yaml 格式的文件,这将使稍后再次加载它变得轻而易举,因为程序已经可以做到这一点。
同样,当用户编辑 TreeView 时,应对模型进行等效更改以保持两者同步。
从编码中抽出一些时间来熟悉 Model–View–Controller (MVC) 设计模式。
开箱即用,答案是否定的,你不能序列化一个TreeView
。 dill
可能是开箱即用的序列化的最佳选择……它无法腌制 TreeView
对象。
>>> import ttk
>>> import Tkinter as tk
>>>
>>> f = tk.Frame()
>>> t = ttk.Treeview(f)
>>>
>>> import dill
>>> dill.pickles(t)
False
>>> dill.detect.errors(t)
PicklingError("Can't pickle 'tkapp' object: <tkapp object at 0x10eda75e0>",)
>>>
您可能会想出如何 pickle TreeView
,然后将该方法添加到 pickle
注册表中……但是,这可能需要您付出一些认真的努力才能找到答案事情如何失败。
你可以看到发生了什么,它击中了 Tkinter.Tk
对象的 __dict__
,并在尝试 pickle something.
>>> dill.detect.trace(True)
>>> dill.dumps(t)
C2: ttk.Treeview
D2: <dict object at 0x1147f5168>
C2: Tkinter.Frame
D2: <dict object at 0x1147f1050>
C2: Tkinter.Tk
D2: <dict object at 0x1148035c8>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.3.dev0-py2.7.egg/dill/dill.py", line 194, in dumps
dump(obj, file, protocol, byref, fmode)#, strictio)
File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.3.dev0-py2.7.egg/dill/dill.py", line 184, in dump
pik.dump(obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
self.save(obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 725, in save_inst
save(stuff)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.3.dev0-py2.7.egg/dill/dill.py", line 678, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 681, in _batch_setitems
save(v)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 725, in save_inst
save(stuff)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.3.dev0-py2.7.egg/dill/dill.py", line 678, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 681, in _batch_setitems
save(v)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 725, in save_inst
save(stuff)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.3.dev0-py2.7.egg/dill/dill.py", line 678, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 681, in _batch_setitems
save(v)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 313, in save
(t.__name__, obj))
pickle.PicklingError: Can't pickle 'tkapp' object: <tkapp object at 0x10eda7648>
>>>
那个东西是一个tkapp
对象。
因此,如果您想进一步挖掘,可以使用 dill.detect
中的方法来帮助您准确地发现它没有酸洗的原因……并尝试绕过它。
我怀疑 pickle 小部件是否正确。您可能也不想走将状态从 treeview
拉出到影子 class 并保存 class 的路线。问题是树视图并没有真正考虑到保存状态的良好分离。
如果您可以重新设计以将应用程序的 state 与 widgets 本身完全分开,那么这更有可能实现您的目标想。所以,当你问 How to serialize a treeview
时,这真的不是你要问的。您想知道如何保存应用程序的状态。
有些包可以很容易地完成类似的事情。我建议您查看 enaml
and/or traits
。 enaml
是一个声明性标记,要求您构建一个 class 来描述您的应用程序界面的工作方式。它迫使您将要显示的内容的内部工作与操作用户界面所必需的代码分开……并且它以一种非常容易构建的方式实现——应用程序的状态与用户界面是分开的接线。因此,您构建的 class 的实例随时包含应用程序的状态——无论它是否有一个 UI,或者两个或三个 UI对于这个问题。它使保存应用程序的状态变得非常容易,因为您永远不必
担心 保存 UI 的状态——UI 没有状态——它只是绘制在应用程序顶部的布局。然后你就不用担心酸洗小部件了……
在此处查看 enaml
:https://github.com/nucleic/enaml
和traits
这里:http://docs.enthought.com/traits
另一个问答展示了如何在退出时 pickle 树视图并在启动时重新加载它:
OP 的信息如下:
#----------TreeViewlist----------------------
Header =['Website','Username','Password','etc']
树状视图的要点是记录OP访问的每个网站,使用的用户ID和使用的密码。
总结接受的答案:
退出时将树视图保存到 pickle
x=[tree.item(x)['values'] for x in tree.get_children()]
filehandler = open('data.pickle', 'wb')
pickle.dump(x,filehandler)
filehandler.close()
加载 pickle 以在启动时构建树视图
items = []
try:
filehandler = open('data.pickle', 'rb')
items = pickle.load(filehandler)
filehandler.close()
except:
pass
for item in items:
tree.insert('','end',values=item)
答案似乎很直接(对我来说),但如果您有任何问题 post 请在下方发表评论。如果您在代码 post 中发现缺陷或错误,请在上面的 link 中发表评论。