簡體   English   中英

tkinter:如何序列化樹視圖?

[英]tkinter: How to serialize a treeview?

我正在開發一個 python tkinter 應用程序,它將初始數據從 yaml 文件讀取到分層的 TreeView 中,以便用戶進一步編輯。

要實現“保存數據”和“撤消”功能,我是否應該遍歷樹視圖並將數據重建為要序列化(pickle)的 python 對象? 或者是否有一個 python 模塊允許,例如,指定要保存的樹視圖和輸出文件?

我懷疑是否有任何 Python 模塊可以滿足您的需求,即使有,我認為您也不希望圍繞使用它來構建您的應用程序。 相反,您最好將事物解耦並將主要數據存儲在獨立於人機界面的東西中(這可能是也可能不是圖形,並且將來可能會發生變化或以其他方式更改)。 這有時稱為應用程序“模型”。

這樣做將允許您加載和保存它,而不管當前的人機界面是什么。 因此,例如,如果內部模型由一個或多個 Python 對象組成,您就可以自由使用pickle 或者,您可以將數據保存回 yaml 格式的文件中,這將使稍后再次加載它變得容易,因為程序已經可以做到這一點。

同樣,當用戶編輯 TreeView 時,應該對模型進行等效的更改以保持兩者同步。

從編碼中抽出一些時間並熟悉模型–視圖–控制器 (MVC)設計模式。

開箱即用,答案是否定的,您不能序列化TreeView dill可能是開箱即用序列化的最佳選擇……它無法pickle 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>",)
>>> 

您也許能夠弄清楚如何腌制TreeView ,然后將該方法添加到pickle注冊表中……但是,您可能需要做一些認真的工作來找出無法腌制的原因。

您可以看到發生了什么,它命中了Tkinter.Tk對象的__dict__ ,並在嘗試腌制某些東西時死亡。

>>> 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的方法來幫助你找出它不酸洗的確切原因……並嘗試繞過它。

我懷疑腌制小部件是否正確。 您可能也不想走將狀態從treeview中提取到影子類中並保存該類的方法。 問題是樹視圖並沒有真正在構建時考慮到保存狀態的良好分離。

如果您可以重新設計以將應用程序的狀態小部件本身完全分開,那么更有可能做您想做的事。 因此,當您詢問How to serialize a treeview ,這實際上不是您要問的。 您想知道如何保存應用程序的狀態。

有一些包可以很容易地做這樣的事情。 我建議你看看enaml和/或traits enaml是一個聲明性標記,它要求您構建一個描述應用程序界面如何工作的類。 它迫使您將所顯示內容的內部工作與操作用戶界面所需的代碼分開……而且它以一種非常容易構建的方式來實現——應用程序的狀態與用戶界面是分開的接線。 因此,您構建的類的實例在任何時候都包含應用程序的狀態——無論它是否有 UI,或者兩個或三個 UI。 它使保存應用程序的狀態變得非常容易,因為您永遠不必擔心保存 UI 的狀態——UI 沒有狀態——它只是在應用程序頂部繪制的布局。 那么你就不必擔心酸洗小部件了......

在此處查看enamlhttps : //github.com/nucleic/enaml

和這里的traitshttp : //docs.enthought.com/traits

另一個問答顯示了如何在退出時pickle 樹視圖並在啟動時重新加載它:

OP 的信息如下:

#----------TreeViewlist----------------------
Header =['Website','Username','Password','etc']

樹狀視圖的要點是記錄 OP 訪問的每個網站、使用的用戶 ID 和使用的密碼。

總結接受的答案:

退出時將樹視圖保存到泡菜

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)

答案看起來很直接(對我來說),但如果您有任何問題,請在下面發表評論。 如果您在代碼中看到缺陷或錯誤,請在上面的鏈接中發表評論。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM