diff --git a/TermTk/TTkGui/theme.py b/TermTk/TTkGui/theme.py index a6aa24ab..648daaca 100644 --- a/TermTk/TTkGui/theme.py +++ b/TermTk/TTkGui/theme.py @@ -115,8 +115,6 @@ class TTkTheme(): └ ─ ┴ ┘ ''' - - buttonBox = ( ('┌','─','┐', '│',' ','│', @@ -136,6 +134,10 @@ class TTkTheme(): hscroll = ('◀','┄','▓','▶') vscroll = ('▲','┊','▓','▼') + tree = ('•','▶','▼',' ', + '│','╿') + + # 0 1 2 3 4 5 menuBar = ('├','─','┤','┄','┄','▶') @@ -268,3 +270,6 @@ class TTkTheme(): tabOffsetColorFocus = tabOffsetColor tabBorderColorFocus = TTkColor.fg("#ffff88") tabSelectColorFocus = TTkColor.fg("#ffff88")+TTkColor.bg("#000066")+TTkColor.BOLD + + treeHeaderColor = TTkColor.fg("#ffffff")+TTkColor.bg("#444444")+TTkColor.BOLD + treeSelectedColor = TTkColor.fg("#ffff88")+TTkColor.bg("#000066")+TTkColor.BOLD \ No newline at end of file diff --git a/TermTk/TTkWidgets/splitter.py b/TermTk/TTkWidgets/splitter.py index b5182b28..6c20f0cc 100644 --- a/TermTk/TTkWidgets/splitter.py +++ b/TermTk/TTkWidgets/splitter.py @@ -32,7 +32,7 @@ class TTkSplitter(TTkFrame): __slots__ = ( '_splitterInitialized', '_orientation', '_separators', '_separatorsRef', '_sizeRef', '_initSizes', - '_separatorSelected', '_mouseDelta') + '_separatorSelected') def __init__(self, *args, **kwargs): self._splitterInitialized = False # self._splitterInitialized = True @@ -194,11 +194,9 @@ class TTkSplitter(TTkFrame): def mousePressEvent(self, evt): self._separatorSelected = None - self._mouseDelta = (evt.x, evt.y) x,y = evt.x, evt.y # TTkLog.debug(f"{self._separators} {evt}") - for i in range(len(self._separators)): - val = self._separators[i] + for i, val in enumerate(self._separators): if self._orientation == TTkK.HORIZONTAL: if x == val: self._separatorSelected = i diff --git a/TermTk/TTkWidgets/treewidget.py b/TermTk/TTkWidgets/treewidget.py index d0631c7c..218f24bd 100644 --- a/TermTk/TTkWidgets/treewidget.py +++ b/TermTk/TTkWidgets/treewidget.py @@ -22,22 +22,40 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from TermTk.TTkCore.cfg import TTkCfg +from TermTk.TTkCore.color import TTkColor +from TermTk.TTkCore.constant import TTkK from TermTk.TTkCore.log import TTkLog +from TermTk.TTkWidgets.treewidgetitem import TTkTreeWidgetItem from TermTk.TTkAbstract.abstractscrollarea import TTkAbstractScrollView from TermTk.TTkCore.signal import pyTTkSlot +from dataclasses import dataclass + class TTkTreeWidget(TTkAbstractScrollView): - __slots__ = ( '_items', '_header', '_columnsPos', '_cache', '_selected') + __slots__ = ( '_items', '_header', '_columnsPos', '_cache', + '_selectedId', '_selected', '_separatorSelected', '_mouseDelta', + '_headerColor', '_selectedColor') + @dataclass(frozen=True) + class _Cache: + item: TTkTreeWidgetItem + level: int + data: list def __init__(self, *args, **kwargs): super().__init__(self, *args, **kwargs) self._name = kwargs.get('name' , 'TTkTreeView' ) - self._selected = -1 + self._selected = None + self._selectedId = None + self._separatorSelected = None self._items = [] self._header = kwargs.get('header',[]) self._columnsPos = [] self._cache = [] + self._headerColor = kwargs.get('headerColor',TTkCfg.theme.treeHeaderColor) + self._selectedColor = kwargs.get('selectedColor',TTkCfg.theme.treeSelectedColor) self.setMinimumHeight(1) + self.setFocusPolicy(TTkK.ClickFocus) # Overridden function def viewFullAreaSize(self) -> (int, int): @@ -70,80 +88,140 @@ class TTkTreeWidget(TTkAbstractScrollView): _, oy = self.getViewOffsets() y -= 1-oy if 0 <= y < len(self._cache): - item = self._cache[y][0] + item = self._cache[y].item item.setExpanded(not item.isExpanded()) - self._selected = y + if self._selected: + self._selected.setSelected(False) + self._selectedId = y + self._selected = item + self._selected.setSelected(True) + self.update() return True + def focusOutEvent(self): + self._separatorSelected = None + def mousePressEvent(self, evt): x,y = evt.x, evt.y ox, oy = self.getViewOffsets() - y += oy-1 + x += ox + + self._separatorSelected = None + self._mouseDelta = (evt.x, evt.y) + + # Handle Header Events + if y == 0: + for i, c in enumerate(self._columnsPos): + if x == c: + self._separatorSelected = i + self.update() + return True + # Handle Tree/Table Events + y += oy-1 if 0 <= y < len(self._cache): - item = self._cache[y][0] - level = self._cache[y][1] + item = self._cache[y].item + level = self._cache[y].level if level*2 <= x < level*2+3: item.setExpanded(not item.isExpanded()) else: - self._selected = y + if self._selected: + self._selected.setSelected(False) + self._selectedId = y + self._selected = item + self._selected.setSelected(True) self.update() return True + def mouseDragEvent(self, evt): + ''' + :: + + columnPos (Selected = 2) + 0 1 2 3 4 + ----|-------|--------|----------|---| + Mouse (Drag) Pos + ^ + I consider at least 4 char (3+1) as spacing + Min Selected Pos = (Selected+1) * 4 + + ''' + if self._separatorSelected is not None: + x,y = evt.x, evt.y + ox, oy = self.getViewOffsets() + y += oy + x += ox + ss = self._separatorSelected + pos = max((ss+1)*4, x) + self._columnsPos[ss] = pos + # Align the previous Separators if pushed + for i in range(ss): + self._columnsPos[i] = min(self._columnsPos[i], pos-(ss-i)*4) + # Align the next Separators if pushed + for i in range(ss, len(self._columnsPos)): + self._columnsPos[i] = max(self._columnsPos[i], pos+(i-ss)*4) + self.update() + self.viewChanged.emit() + return True + return False + @pyTTkSlot() def _refreshCache(self): ''' I save a representation fo the displayed tree in a cache array to avoid eccessve recursion over the items and identify quickly the nth displayed line to improve the interaction - _cache is an array of: - [ item, level, txtCol1, txtCol2, txtCol3, ... ] + _cache is an array of TTkTreeWidget._Cache: + [ item, level, data=[txtCol1, txtCol2, txtCol3, ... ]] ''' self._cache = [] def _addToCache(_child, _level): - _entry = [_child, _level] + tt = TTkCfg.theme.tree + _data = [] for _il in range(len(self._header)): - _entry.append(_child.data(_il)) - self._cache.append(_entry) + _data.append(_child.data(_il)) + if not _child.children(): + _data[0] = f"{' '*_level} {tt[0]} {_data[0]}" + elif _child.isExpanded(): + _data[0] = f"{' '*_level} {tt[2]} {_data[0]}" + else: + _data[0] = f"{' '*_level} {tt[1]} {_data[0]}" + self._cache.append(TTkTreeWidget._Cache( + item = _child, + level = _level, + data = _data)) if _child.isExpanded(): for _c in _child.children(): _addToCache(_c, _level+1) for c in self._items: _addToCache(c,0) self.update() + self.viewChanged.emit() def paintEvent(self): x,y = self.getViewOffsets() w,h = self.size() + tt = TTkCfg.theme.tree # Draw header first: for i,l in enumerate(self._header): - hx = 0 if i==0 else self._columnsPos[i-1]+1 - self._canvas.drawText(pos=(hx-x,0), text=l) + hx = 0 if i==0 else self._columnsPos[i-1]+1 + hx1 = self._columnsPos[i] + self._canvas.drawText(pos=(hx-x,0), text=l, width=hx1-hx, color=self._headerColor) # Draw header separators for sx in self._columnsPos: - self._canvas.drawText(pos=(sx-x,0), text='|') + self._canvas.drawChar(pos=(sx-x,0), char=tt[5], color=self._headerColor) + for sy in range(1,h): + self._canvas.drawChar(pos=(sx-x,sy), char=tt[4]) # Draw cache - for i, l in enumerate(self._cache): + for i, c in enumerate(self._cache): if i-y<0 : continue - item = l[0] - level = l[1] - l1 = l[2] - if not item.children(): - l1 = ' '*level + " • " + l1 - elif item.isExpanded(): - l1 = ' '*level + " ▼ " + l1 - else: - l1 = ' '*level + " ▶ " + l1 - - self._canvas.drawText(pos=(-x,i-y+1), text=l1) - for il in range(1,len(self._header)): - lx = self._columnsPos[il-1]+1 - self._canvas.drawText(pos=(lx-x,i-y+1), text=l[2+il]) - - - - - + item = c.item + level = c.level + color = self._selectedColor if item.isSelected() else TTkColor.RST + for il in range(len(self._header)): + lx = 0 if il==0 else self._columnsPos[il-1]+1 + lx1 = self._columnsPos[il] + self._canvas.drawText(pos=(lx-x,i-y+1), text=c.data[il], width=lx1-lx, color=color) diff --git a/TermTk/TTkWidgets/treewidgetitem.py b/TermTk/TTkWidgets/treewidgetitem.py index 85f262f8..357b3a99 100644 --- a/TermTk/TTkWidgets/treewidgetitem.py +++ b/TermTk/TTkWidgets/treewidgetitem.py @@ -30,7 +30,8 @@ from TermTk.TTkAbstract.abstractitemmodel import TTkAbstractItemModel class TTkTreeWidgetItem(TTkAbstractItemModel): - __slots__ = ('_parent', '_data', '_children', '_expanded', '_childIndicatorPolicy', + __slots__ = ('_parent', '_data', '_children', '_expanded', '_selected', + '_childIndicatorPolicy', # Signals 'refreshData') @@ -43,6 +44,7 @@ class TTkTreeWidgetItem(TTkAbstractItemModel): self._parent = kwargs.get('parent', None) self._childIndicatorPolicy = kwargs.get('childIndicatorPolicy', TTkK.DontShowIndicatorWhenChildless) self._expanded = False + self._selected = False self._parent = kwargs.get("parent", None) def addChild(self, child): @@ -79,12 +81,18 @@ class TTkTreeWidgetItem(TTkAbstractItemModel): self._expanded = expand self.emitDataChanged() + def setSelected(self, select): + self._selected = select + # def isDisabled(): # pass def isExpanded(self): return self._expanded + def isSelected(self): + return self._selected + def size(self): if self._expanded: return 1 + sum([c.size() for c in self._children]) diff --git a/demo/demo.py b/demo/demo.py index 3eb048b7..9199cb36 100755 --- a/demo/demo.py +++ b/demo/demo.py @@ -32,9 +32,7 @@ import TermTk as ttk from showcase.layout_basic import demoLayout from showcase.layout_nested import demoLayoutNested from showcase.layout_span import demoLayoutSpan -from showcase.table import demoTable from showcase.tab import demoTab -from showcase.tree import demoTree from showcase.graph import demoGraph from showcase.splitter import demoSplitter from showcase.windows import demoWindows @@ -43,6 +41,9 @@ from showcase.scrollarea import demoScrollArea from showcase.list import demoList from showcase.menubar import demoMenuBar from showcase.colorpicker import demoColorPicker +from showcase.tree import demoTree +from showcase.fancytable import demoFancyTable +from showcase.fancytree import demoFancyTree words = ["Lorem", "ipsum", "dolor", "sit", "amet,", "consectetur", "adipiscing", "elit,", "sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et", "dolore", "magna", "aliqua.", "Ut", "enim", "ad", "minim", "veniam,", "quis", "nostrud", "exercitation", "ullamco", "laboris", "nisi", "ut", "aliquip", "ex", "ea", "commodo", "consequat.", "Duis", "aute", "irure", "dolor", "in", "reprehenderit", "in", "voluptate", "velit", "esse", "cillum", "dolore", "eu", "fugiat", "nulla", "pariatur.", "Excepteur", "sint", "occaecat", "cupidatat", "non", "proident,", "sunt", "in", "culpa", "qui", "officia", "deserunt", "mollit", "anim", "id", "est", "laborum."] def getWord(): @@ -78,9 +79,10 @@ def demoShowcase(root=None, border=True): tabWidgets = ttk.TTkTabWidget(parent=mainFrame, border=False, visible=False) tabWidgets.addTab(demoFormWidgets(), " Form Test ") tabWidgets.addTab(demoList(), " List Test ") - tabWidgets.addTab(demoTable(), " Table Test ") - tabWidgets.addTab(demoTree(), " Tree Test ") + tabWidgets.addTab(demoTree(), " Tree Test") tabWidgets.addTab(demoTab(), " Tab Test ") + tabWidgets.addTab(demoFancyTable(), " Old Table ") + tabWidgets.addTab(demoFancyTree(), " Old Tree ") listMenu.addItem(f"Pickers") tabPickers = ttk.TTkTabWidget(parent=mainFrame, border=False, visible=False) diff --git a/demo/showcase/table.py b/demo/showcase/fancytable.py similarity index 98% rename from demo/showcase/table.py rename to demo/showcase/fancytable.py index 171ffe1d..a3a52195 100755 --- a/demo/showcase/table.py +++ b/demo/showcase/fancytable.py @@ -36,7 +36,7 @@ def getSentence(a,b): table_ii = 1000 -def demoTable(root=None): +def demoFancyTable(root=None): frame = ttk.TTkFrame(parent=root, border=False, layout=ttk.TTkVBoxLayout()) top = ttk.TTkFrame(parent=frame, border=False, layout=ttk.TTkHBoxLayout()) btn1 = ttk.TTkButton(parent=top, maxHeight=3, border=True, text='Add') @@ -88,7 +88,7 @@ def main(): root = ttk.TTk() win_table = ttk.TTkWindow(parent=root,pos = (3,3), size=(150,40), title="Test Table 1", layout=ttk.TTkHBoxLayout(), border=True) - demoTable(win_table) + demoFancyTable(win_table) root.mainloop() if __name__ == "__main__": diff --git a/demo/showcase/fancytree.py b/demo/showcase/fancytree.py new file mode 100755 index 00000000..1517e3f5 --- /dev/null +++ b/demo/showcase/fancytree.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2021 Eugenio Parodi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Demo inspired from: +# https://stackoverflow.com/questions/41204234/python-pyqt5-qtreewidget-sub-item + +import os +import sys +import random +import argparse + +sys.path.append(os.path.join(sys.path[0],'../..')) +import TermTk as ttk + +words = ["Lorem", "ipsum", "dolor", "sit", "amet,", "consectetur", "adipiscing", "elit,", "sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et", "dolore", "magna", "aliqua.", "Ut", "enim", "ad", "minim", "veniam,", "quis", "nostrud", "exercitation", "ullamco", "laboris", "nisi", "ut", "aliquip", "ex", "ea", "commodo", "consequat.", "Duis", "aute", "irure", "dolor", "in", "reprehenderit", "in", "voluptate", "velit", "esse", "cillum", "dolore", "eu", "fugiat", "nulla", "pariatur.", "Excepteur", "sint", "occaecat", "cupidatat", "non", "proident,", "sunt", "in", "culpa", "qui", "officia", "deserunt", "mollit", "anim", "id", "est", "laborum."] +def getWord(): + return random.choice(words) +def getSentence(a,b): + return " ".join([getWord() for i in range(0,random.randint(a,b))]) + +def demoFancyTree(root=None): + # tw = ttk.TTkFancyTreeWidget(parent=rootTree1) + tw = ttk.TTkFancyTree(parent=root) + tw.setHeaderLabels(["Column 1", "Column 2", "Column 3"]) + tw.setColumnSize((-1,20,20)) + tw.setColumnColors(( + ttk.TTkColor.RST, + ttk.TTkColor.fg('#00dddd', modifier=ttk.TTkColorGradient(increment=-4)), + ttk.TTkColor.fg('#cccc00', modifier=ttk.TTkColorGradient(increment=-2)) + )) + l1 = ttk.TTkFancyTreeWidgetItem(["String A", "String B", "String C"]) + l2 = ttk.TTkFancyTreeWidgetItem(["String AA", "String BB", "String CC"]) + l3 = ttk.TTkFancyTreeWidgetItem(["String AAA", "String BBB", "String CCC"]) + l4 = ttk.TTkFancyTreeWidgetItem(["String AAAA", "String BBBB", "String CCCC"]) + l5 = ttk.TTkFancyTreeWidgetItem(["String AAAAA", "String BBBBB", "String CCCCC"]) + + l2.addChild(l5) + + for i in range(3): + l1_child = ttk.TTkFancyTreeWidgetItem(["Child A" + str(i), "Child B" + str(i), "Child C" + str(i)]) + l1.addChild(l1_child) + + for j in range(2): + l2_child = ttk.TTkFancyTreeWidgetItem(["Child AA" + str(j), "Child BB" + str(j), "Child CC" + str(j)]) + l2.addChild(l2_child) + + for j in range(2): + l3_child = ttk.TTkFancyTreeWidgetItem(["Child AAA" + str(j), "Child BBB" + str(j), "Child CCC" + str(j)]) + l3.addChild(l3_child) + + for j in range(2): + l4_child = ttk.TTkFancyTreeWidgetItem(["Child AAAA" + str(j), "Child BBBB" + str(j), "Child CCCC" + str(j)]) + l4.addChild(l4_child) + + for j in range(2): + l5_child = ttk.TTkFancyTreeWidgetItem(["Child AAAAA" + str(j), "Child BBBBB" + str(j), "Child CCCCC" + str(j)]) + l5.addChild(l5_child) + + l6 = ttk.TTkFancyTreeWidgetItem(["RND", "RND", "RND"], childIndicatorPolicy=ttk.TTkK.ShowIndicator) + + def updateChildren(item): + if item.children(): return + for _ in range(0,random.randint(3,8)): + child = ttk.TTkFancyTreeWidgetItem([getWord(),getWord(),getWord()]) + if random.randint(0,10)>5: + child.setChildIndicatorPolicy(ttk.TTkK.ShowIndicator) + child.refreshData.connect(updateChildren) + item.addChild(child) + + + l6.refreshData.connect(updateChildren) + + tw.addTopLevelItem(l1) + tw.addTopLevelItem(l2) + tw.addTopLevelItem(l3) + tw.addTopLevelItem(l4) + tw.addTopLevelItem(l6) + + return tw + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('-f', help='Full Screen', action='store_true') + args = parser.parse_args() + + ttk.TTkLog.use_default_file_logging() + + root = ttk.TTk() + if args.f: + rootTree1 = root + root.setLayout(ttk.TTkGridLayout()) + else: + rootTree1 = ttk.TTkWindow(parent=root,pos = (0,0), size=(70,40), title="Test Tree 1", layout=ttk.TTkGridLayout(), border=True) + demoFancyTree(rootTree1) + root.mainloop() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/demo/showcase/tree.py b/demo/showcase/tree.py index 892de952..af57feea 100755 --- a/demo/showcase/tree.py +++ b/demo/showcase/tree.py @@ -40,49 +40,43 @@ def getSentence(a,b): return " ".join([getWord() for i in range(0,random.randint(a,b))]) def demoTree(root=None): - # tw = ttk.TTkFancyTreeWidget(parent=rootTree1) - tw = ttk.TTkFancyTree(parent=root) + tw = ttk.TTkTree(parent=root) tw.setHeaderLabels(["Column 1", "Column 2", "Column 3"]) - tw.setColumnSize((-1,20,20)) - tw.setColumnColors(( - ttk.TTkColor.RST, - ttk.TTkColor.fg('#00dddd', modifier=ttk.TTkColorGradient(increment=-4)), - ttk.TTkColor.fg('#cccc00', modifier=ttk.TTkColorGradient(increment=-2)) - )) - l1 = ttk.TTkFancyTreeWidgetItem(["String A", "String B", "String C"]) - l2 = ttk.TTkFancyTreeWidgetItem(["String AA", "String BB", "String CC"]) - l3 = ttk.TTkFancyTreeWidgetItem(["String AAA", "String BBB", "String CCC"]) - l4 = ttk.TTkFancyTreeWidgetItem(["String AAAA", "String BBBB", "String CCCC"]) - l5 = ttk.TTkFancyTreeWidgetItem(["String AAAAA", "String BBBBB", "String CCCCC"]) + + l1 = ttk.TTkTreeWidgetItem(["String A", "String B", "String C"]) + l2 = ttk.TTkTreeWidgetItem(["String AA", "String BB", "String CC"]) + l3 = ttk.TTkTreeWidgetItem(["String AAA", "String BBB", "String CCC"]) + l4 = ttk.TTkTreeWidgetItem(["String AAAA", "String BBBB", "String CCCC"]) + l5 = ttk.TTkTreeWidgetItem(["String AAAAA", "String BBBBB", "String CCCCC"]) l2.addChild(l5) for i in range(3): - l1_child = ttk.TTkFancyTreeWidgetItem(["Child A" + str(i), "Child B" + str(i), "Child C" + str(i)]) + l1_child = ttk.TTkTreeWidgetItem(["Child A" + str(i), "Child B" + str(i), "Child C" + str(i)]) l1.addChild(l1_child) for j in range(2): - l2_child = ttk.TTkFancyTreeWidgetItem(["Child AA" + str(j), "Child BB" + str(j), "Child CC" + str(j)]) + l2_child = ttk.TTkTreeWidgetItem(["Child AA" + str(j), "Child BB" + str(j), "Child CC" + str(j)]) l2.addChild(l2_child) for j in range(2): - l3_child = ttk.TTkFancyTreeWidgetItem(["Child AAA" + str(j), "Child BBB" + str(j), "Child CCC" + str(j)]) + l3_child = ttk.TTkTreeWidgetItem(["Child AAA" + str(j), "Child BBB" + str(j), "Child CCC" + str(j)]) l3.addChild(l3_child) for j in range(2): - l4_child = ttk.TTkFancyTreeWidgetItem(["Child AAAA" + str(j), "Child BBBB" + str(j), "Child CCCC" + str(j)]) + l4_child = ttk.TTkTreeWidgetItem(["Child AAAA" + str(j), "Child BBBB" + str(j), "Child CCCC" + str(j)]) l4.addChild(l4_child) for j in range(2): - l5_child = ttk.TTkFancyTreeWidgetItem(["Child AAAAA" + str(j), "Child BBBBB" + str(j), "Child CCCCC" + str(j)]) + l5_child = ttk.TTkTreeWidgetItem(["Child AAAAA" + str(j), "Child BBBBB" + str(j), "Child CCCCC" + str(j)]) l5.addChild(l5_child) - l6 = ttk.TTkFancyTreeWidgetItem(["RND", "RND", "RND"], childIndicatorPolicy=ttk.TTkK.ShowIndicator) + l6 = ttk.TTkTreeWidgetItem(["RND", "RND", "RND"], childIndicatorPolicy=ttk.TTkK.ShowIndicator) def updateChildren(item): if item.children(): return for _ in range(0,random.randint(3,8)): - child = ttk.TTkFancyTreeWidgetItem([getWord(),getWord(),getWord()]) + child = ttk.TTkTreeWidgetItem([getWord(),getWord(),getWord()]) if random.randint(0,10)>5: child.setChildIndicatorPolicy(ttk.TTkK.ShowIndicator) child.refreshData.connect(updateChildren)