Я создал класс treeview с флажками, наследующими ttk.Treeview, но флажки не являются ttk.Checkbutton, но изображения отмеченных, непроверенных и тристатных флажков.
import tkinter as tk
import tkinter.ttk as ttk
class CheckboxTreeview(ttk.Treeview):
"""
Treeview widget with checkboxes left of each item.
The checkboxes are done via the image attribute of the item, so to keep
the checkbox, you cannot add an image to the item.
"""
def __init__(self, master=None, **kw):
ttk.Treeview.__init__(self, master, **kw)
# checkboxes are implemented with pictures
self.im_checked = tk.PhotoImage(file='checked.png')
self.im_unchecked = tk.PhotoImage(file='unchecked.png')
self.im_tristate = tk.PhotoImage(file='tristate.png')
self.tag_configure("unchecked", image=self.im_unchecked)
self.tag_configure("tristate", image=self.im_tristate)
self.tag_configure("checked", image=self.im_checked)
# check / uncheck boxes on click
self.bind("", self.box_click, True)
def insert(self, parent, index, iid=None, **kw):
""" same method as for standard treeview but add the tag 'unchecked'
automatically if no tag among ('checked', 'unchecked', 'tristate')
is given """
if not "tags" in kw:
kw["tags"] = ("unchecked",)
elif not ("unchecked" in kw["tags"] or "checked" in kw["tags"]
or "tristate" in kw["tags"]):
kw["tags"] = ("unchecked",)
ttk.Treeview.insert(self, parent, index, iid, **kw)
def check_descendant(self, item):
""" check the boxes of item's descendants """
children = self.get_children(item)
for iid in children:
self.item(iid, tags=("checked",))
self.check_descendant(iid)
def check_ancestor(self, item):
""" check the box of item and change the state of the boxes of item's
ancestors accordingly """
self.item(item, tags=("checked",))
parent = self.parent(item)
if parent:
children = self.get_children(parent)
b = ["checked" in self.item(c, "tags") for c in children]
if False in b:
# at least one box is not checked and item's box is checked
self.tristate_parent(parent)
else:
# all boxes of the children are checked
self.check_ancestor(parent)
def tristate_parent(self, item):
""" put the box of item in tristate and change the state of the boxes of
item's ancestors accordingly """
self.item(item, tags=("tristate",))
parent = self.parent(item)
if parent:
self.tristate_parent(parent)
def uncheck_descendant(self, item):
""" uncheck the boxes of item's descendant """
children = self.get_children(item)
for iid in children:
self.item(iid, tags=("unchecked",))
self.uncheck_descendant(iid)
def uncheck_ancestor(self, item):
""" uncheck the box of item and change the state of the boxes of item's
ancestors accordingly """
self.item(item, tags=("unchecked",))
parent = self.parent(item)
if parent:
children = self.get_children(parent)
b = ["unchecked" in self.item(c, "tags") for c in children]
if False in b:
# at least one box is checked and item's box is unchecked
self.tristate_parent(parent)
else:
# no box is checked
self.uncheck_ancestor(parent)
def box_click(self, event):
""" check or uncheck box when clicked """
x, y, widget = event.x, event.y, event.widget
elem = widget.identify("element", x, y)
if "image" in elem:
# a box was clicked
item = self.identify_row(y)
tags = self.item(item, "tags")
if ("unchecked" in tags) or ("tristate" in tags):
self.check_ancestor(item)
self.check_descendant(item)
else:
self.uncheck_descendant(item)
self.uncheck_ancestor(item)
if __name__ == '__main__':
root = tk.Tk()
t = CheckboxTreeview(root, show="tree")
t.pack()
t.insert("", 0, "1", text="1")
t.insert("1", "end", "11", text="1")
t.insert("1", "end", "12", text="2")
t.insert("12", "end", "121", text="1")
t.insert("12", "end", "122", text="2")
t.insert("122", "end", "1221", text="1")
t.insert("1", "end", "13", text="3")
t.insert("13", "end", "131", text="1")
root.mainloop()
Улучшенная версия CheckboxTreeview
доступен в модуле ttkwidgets .
В man-странице git stash вы можете прочитать это (в разделе «Обсуждение» сразу после описания «Опции»):
Шкатулка представлена в виде коммита, дерево которого записывает состояние рабочего каталога, и его первым родителем является коммит в HEAD при создании тайника.
Таким образом, вы можете рассматривать stash (например, stash@{0}
является первым / верхним тайном) как коммит слияния и использовать:
$ git diff stash@{0}^1 stash@{0} -- <filename>
Объяснение: stash@{0}^1
ярлык означает первого родителя данного тайник, который, как указано в объяснении выше, является коммитом, при котором изменения были спрятаны Мы используем эту форму "git diff" (с двумя коммитами), потому что stash@{0}
/ refs/stash
является коммитом слияния, и мы должны указать git, против какого родителя мы хотим использовать diff. Более загадочно:
$ git diff stash@{0}^! -- <filename>
также должны работать (см. Справочную страницу git rev-parse для объяснения синтаксиса rev^!
в разделе «Задание диапазонов»).
Аналогично, вы можете использовать git checkout , чтобы извлечь один файл из тайника:
$ git checkout stash@{0} -- <filename>
или сохранить его под другим именем:
$ git show stash@{0}:<full filename> > <newfile>
или
$ git show stash@{0}:./<relative filename> > <newfile>
( обратите внимание , что здесь < полное имя файла > является полным путем к файлу относительно верхнего каталога проекта (думаю: относительно stash@{0}
)) .
Возможно, вам потребуется защитить stash@{0}
от расширения оболочки, т. е. использовать "stash@{0}"
или 'stash@{0}'
.
Самая простая концепция для понимания, хотя, возможно, и не самая лучшая, это то, что вы изменили три файла и хотите сохранить один файл.
Если вы сделаете git stash
, чтобы спрятать их все, git stash apply
, чтобы вернуть их снова, а затем git checkout f.c
в рассматриваемом файле, чтобы эффективно сбросить его.
Если вы хотите распаковать этот файл, запустите git reset --hard
, а затем снова запустите git stash apply
, воспользовавшись тем, что git stash apply
не очищает diff из стека.
Если вы используете git stash apply
, а не git stash pop
, он применит тайник к вашему рабочему дереву, но при этом сохранит тайник.
После этого вы можете добавить
/ зафиксировать
файл, который вам нужен, а затем сбросить оставшиеся изменения.
Вы можете получить разницу для тайника с помощью " git show stash @ {0}
" (или любого другого номера тайника; см. "Git stash list"). Раздел diff для одного файла легко извлечь.