From 93d310dc16228d161f8fa3bbcf26489f95273328 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Sat, 22 May 2021 15:24:52 +0100 Subject: [PATCH 1/5] Collecting Ideas fot the tab menu/helpers buttons --- TermTk/TTkGui/theme.py | 21 ++++++++++++--------- TermTk/TTkWidgets/menubar.py | 10 +++++----- demo/demo.py | 3 ++- demo/showcase/tab.py | 16 ++++++++++------ 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/TermTk/TTkGui/theme.py b/TermTk/TTkGui/theme.py index fe778604..5d647d99 100644 --- a/TermTk/TTkGui/theme.py +++ b/TermTk/TTkGui/theme.py @@ -156,16 +156,19 @@ class TTkTheme(): :: - ┌──────╔══════╗──────┬──────┐ ┌─┌──────╔══════╗──────┬──────┐─┐ - │Label1║Label2║Label3│Label4│ │◀│Label1║Label2║Label3│Label4│▶│ - ╞═╧══════╩══════╩══════╧══════╧════╡ ╞═╧══════╩══════╩══════╧══════╧═╡ - ┌──────╔══════╗──────┬──────┐ ╭─┌──────╔══════╗──────┬──────┐─╮ - │Label1║Label2║Label3│Label4│ │◀│Label1║Label2║Label3│Label4│▶│ - ╞════════╩══════╩══════════════════╡ ╞════════╩══════╩═══════════════╡ + ┌──────╔══════╗──────┬──────┐ ┌─┌──────╔══════╗──────┬──────┐─┐ + │Label1║Label2║Label3│Label4│ │◀│Label1║Label2║Label3│Label4│▶│ + ╞═╧══════╩══════╩══════╧══════╧════╡ ╞═╧══════╩══════╩══════╧══════╧═╡ + ┌──────╔══════╗──────┬──────┐ ╭─┌──────╔══════╗──────┬──────┐─╮ + │Label1║Label2║Label3│Label4│ │◀│Label1║Label2║Label3│Label4│▶│ + ╞════════╩══════╩══════════════════╡ ╞════════╩══════╩═══════════════╡ # Menu Prototype: - ╭──┌──────╔══════╗──────┬──────┐ ╭──┬─┌──────╔══════╗──────┬──────┐─╮ - │⣿⣿│Label1║Label2║Label3│Label4│ │⣿⣿│◀│Label1║Label2║Label3│Label4│▶│ - ╞═════════╩══════╩═══════════════╡ ╞══╧════════╩══════╩═══════════════╡ + ╭──┌──────╔══════╗──────┬──────┐ ╭──┬─┌──────╔══════╗──────┬──────┐─╮ + │XX│Label1║Label2║Label3│Label4│ │XX│◀│Label1║Label2║Label3│Label4│▶│ + ╞═════════╩══════╩═══════════════╡ ╞══╧════════╩══════╩═══════════════╡ + ┌──────╔══════╗──────┬──────┐ ╭─┌──────╔══════╗──────┬──────┐─╮ + XX YY│Label1║Label2║Label3│Label4│JJ KK XX YY│◀│Label1║Label2║Label3│Label4│▶│JJ KK + ╞════════════╩══════╩═══════════════════╡ ╞═════╧════════╩══════╩═══════════════╧═════╡ ┌──────┲━━━━━━┱──────┬──────┐ │Label1┃Label2┃Label3│Label4│ ┝━┷━━━━━━┻━━━━━━┻━━━━━━┷━━━━━━┷━━━━┥ diff --git a/TermTk/TTkWidgets/menubar.py b/TermTk/TTkWidgets/menubar.py index 276815f6..7c0b29d3 100644 --- a/TermTk/TTkWidgets/menubar.py +++ b/TermTk/TTkWidgets/menubar.py @@ -49,7 +49,7 @@ class _TTkMenuListWidget(TTkListWidget): return True elif evt.key == TTkK.Key_Right: if self._highlighted and \ - isinstance(self._highlighted,_TTkMenuButton) and \ + isinstance(self._highlighted,TTkMenuButton) and \ self._highlighted._menu: self._highlighted.menuButtonEvent() return True @@ -65,11 +65,11 @@ class _TTkMenuSpacer(TTkAbstractListItem): def paintEvent(self): self._canvas.drawText(pos=(0,0), text="-"*self.width()) -class _TTkMenuButton(TTkAbstractListItem): +class TTkMenuButton(TTkAbstractListItem): __slots__ = ('_border', '_borderColor', '_shortcut', '_menu', 'menuButtonClicked') def __init__(self, *args, **kwargs): TTkAbstractListItem.__init__(self, *args, **kwargs) - self._name = kwargs.get('name' , '_TTkMenuButton' ) + self._name = kwargs.get('name' , 'TTkMenuButton' ) # signals self.menuButtonClicked = pyTTkSignal(TTkButton) self._color = kwargs.get('color', TTkCfg.theme.menuButtonColor ) @@ -90,7 +90,7 @@ class _TTkMenuButton(TTkAbstractListItem): self.listItemClicked.connect(self.menuButtonEvent) def addMenu(self, text): - button = _TTkMenuButton(text=text, borderColor=self._borderColor, border=False) + button = TTkMenuButton(text=text, borderColor=self._borderColor, border=False) button.menuButtonClicked.connect(self._menuCallback) self._menu.append(button) return button @@ -196,7 +196,7 @@ class TTkMenuLayout(TTkHBoxLayout): self.update() def addMenu(self, text, alignment=TTkK.LEFT_ALIGN): - button = _TTkMenuButton(text=text, borderColor=self._borderColor, border=True) + button = TTkMenuButton(text=text, borderColor=self._borderColor, border=True) if alignment == TTkK.LEFT_ALIGN: self._itemsLeft.addWidget(button) elif alignment == TTkK.CENTER_ALIGN: diff --git a/demo/demo.py b/demo/demo.py index 2620890a..90219ae6 100755 --- a/demo/demo.py +++ b/demo/demo.py @@ -58,6 +58,7 @@ def demoShowcase(root=None, border=True): listMenu.addItem(f"Test") tabTest = ttk.TTkTabWidget(parent=mainFrame, border=False, visible=False) + tabTest.addTab(ttk.TTkLogViewer(), " LogViewer ") tabTest.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.1"), " Label 1.1 ") tabTest.addTab(ttk.TTkTestWidget(border=True, title="Frame1.2"), " Label Test 1.2 ") @@ -116,7 +117,7 @@ def demoShowcase(root=None, border=True): listMenu.textClicked.connect(_listCallback) - listMenu.setCurrentRow(1) + listMenu.setCurrentRow(0) return splitter diff --git a/demo/showcase/tab.py b/demo/showcase/tab.py index e662dc64..a1b6bf0f 100755 --- a/demo/showcase/tab.py +++ b/demo/showcase/tab.py @@ -29,12 +29,16 @@ import TermTk as ttk def demoTab(root= None): tabWidget1 = ttk.TTkTabWidget(parent=root, border=True) - tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.1"), "Label 1.1") - tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.2"), "Label 1.2") - tabWidget1.addTab(ttk.TTkTestWidget(border=True, title="Frame1.3"), "Label Test 1.3") - tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.4"), "Label 1.4") - tabWidget1.addTab(ttk.TTkTestWidget(border=True, title="Frame1.5"), "Label Test 1.5") - tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.6"), "Label 1.6") + tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.1"), "Label 1.1") + tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.2"), "Label 1.2") + tabWidget1.addTab(ttk.TTkTestWidget( border=True, title="Frame1.3"), "Label Test 1.3") + tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.4"), "Label 1.4") + tabWidget1.addTab(ttk.TTkTestWidget( border=True, title="Frame1.5"), "Label Test 1.5") + tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.6"), "Label 1.6") + tabWidget1.addTab(ttk.TTkTestWidget( border=True, title="Frame1.7"), "Label Test 1.7") + tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.8"), "Label 1.8") + #tabWidget1.addTab(ttk.TTkTestWidget( border=True, title="Frame1.9"), "Label Test 1.9") + #tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.10"), "Label 1.10") return tabWidget1 def main(): From 53b286bdfdf58edcfded8a0ca3140d35b278c8ec Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Sun, 23 May 2021 20:15:49 +0100 Subject: [PATCH 2/5] Separate tab element in the TtkTabWidget --- TermTk/TTkWidgets/tabwidget.py | 154 ++++++++++++++++++++++++--------- demo/showcase/tab.py | 12 +-- 2 files changed, 120 insertions(+), 46 deletions(-) diff --git a/TermTk/TTkWidgets/tabwidget.py b/TermTk/TTkWidgets/tabwidget.py index 772ba9c7..d14a18ae 100644 --- a/TermTk/TTkWidgets/tabwidget.py +++ b/TermTk/TTkWidgets/tabwidget.py @@ -29,6 +29,7 @@ from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal from TermTk.TTkWidgets.widget import TTkWidget from TermTk.TTkWidgets.spacer import TTkSpacer from TermTk.TTkWidgets.frame import TTkFrame +from TermTk.TTkLayouts.boxlayout import TTkHBoxLayout from TermTk.TTkLayouts.gridlayout import TTkGridLayout @@ -40,22 +41,24 @@ _labels= │◀│La│Label1║Label2║Label3│Label4│▶│ ╞═══════════╩══════╩═══════════════╡ leftscroller rightScroller ''' -class TTkTabWidget(TTkFrame): + +class _TTkTabs(TTkWidget): __slots__ = ( - '_viewport', '_tabColor', '_tabBorderColor', '_tabSelectColor', '_tabOffsetColor', '_tabColorFocus', '_tabBorderColorFocus', '_tabSelectColorFocus', '_tabOffsetColorFocus', - '_tabWidgets', '_labels', '_labelsPos', - '_offset', '_currentIndex', + '_labels', '_labelsPos', + '_offset', '_currentIndex','_lastIndex', '_leftScroller', '_rightScroller', - '_tabMovable', '_tabClosable') + '_tabMovable', '_tabClosable', + #Signals + 'currentChanged') def __init__(self, *args, **kwargs): - self._tabWidgets = [] self._labels = [] self._labelsPos = [] - self._currentIndex = 0 - self._offset = 0 + self._currentIndex = -1 + self._lastIndex = -1 + self._offset = -1 self._tabMovable = False self._tabClosable = False self._leftScroller = False @@ -68,32 +71,18 @@ class TTkTabWidget(TTkFrame): self._tabBorderColorFocus = TTkCfg.theme.tabBorderColorFocus self._tabSelectColorFocus = TTkCfg.theme.tabSelectColorFocus self._tabOffsetColorFocus = TTkCfg.theme.tabOffsetColorFocus - TTkFrame.__init__(self, *args, **kwargs) - self._name = kwargs.get('name' , 'TTkTabWidget') - self.setLayout(TTkGridLayout()) - self._viewport = TTkWidget(layout=TTkGridLayout()) - self.layout().addWidget(self._viewport,0,0) - #self.layout().addWidget(TTkSpacer(),0,1) - #self.layout().addWidget(TTkSpacer(),1,0) - if self.border(): - self.setPadding(3,1,1,1) - else: - self.setPadding(2,0,0,0) + # Signals + self.currentChanged = pyTTkSignal(int) + TTkWidget.__init__(self, *args, **kwargs) + self._name = kwargs.get('name' , '_TTkTabs') self.setFocusPolicy(TTkK.ClickFocus + TTkK.TabFocus) - - def addTab(self, widget, label): - widget.hide() - self._tabWidgets.append(widget) + def addTab(self, label): self._labels.append(label) - self._viewport.addWidget(widget) self._updateTabs() - def insertTab(self, index, widget, label): - widget.hide() - self._tabWidgets.insert(index, widget) + def insertTab(self, index, label): self._labels.insert(index, label) - self._viewport.addWidget(widget) self._updateTabs() def _updateTabs(self): @@ -115,24 +104,22 @@ class TTkTabWidget(TTkFrame): minLabelLen = labelLen self.setMinimumWidth(minLabelLen+2+4) - for i, widget in enumerate(self._tabWidgets): - if self._currentIndex == i: - widget.show() - else: - widget.hide() + if self._currentIndex == -1: + self._currentIndex = len(self._labels) -1 + + if self._lastIndex != self._currentIndex: + self._lastIndex = self._currentIndex + self.currentChanged.emit(self._currentIndex) + self.update() def resizeEvent(self, w, h): self._updateTabs() def mousePressEvent(self, evt): - x,y = evt.x, evt.y + x = evt.x w = self.width() offset = self._offset - if self.border(): - if y>2: return False - else: - if y>1: return False # Check from the selected to the left and from selected+1 to the right if self._leftScroller and x<2 and offset>0: self._offset -= 1 @@ -196,12 +183,97 @@ class TTkTabWidget(TTkFrame): tabBorderColor = self._tabBorderColor tabSelectColor = self._tabSelectColor tabOffsetColor = self._tabOffsetColor - if self.border(): - self._canvas.drawBox(pos=(0,2),size=(self._width,self._height-2), color=tabBorderColor, grid=9) self._canvas.drawTab( - pos=(0,0), size=self.size(), slim=not self.border(), + pos=(0,0), size=self.size(), slim=(self._height==2), labels=self._labels, labelsPos=self._labelsPos, selected=self._currentIndex, offset=self._offset, leftScroller=self._leftScroller, rightScroller=self._rightScroller, color=tabColor, borderColor=tabBorderColor, selectColor=tabSelectColor, offsetColor=tabOffsetColor) + +''' + ┌────────────────────────────┐ + │ Root Layout │ + │┌────────┬────────┬────────┐│ + ││Right M │ TABS │ Left M ││ + │└────────┴────────┴────────┘│ + │┌──────────────────────────┐│ + ││ Layout ││ + ││ ││ + │└──────────────────────────┘│ + └────────────────────────────┘ +''' + +class TTkTabWidget(TTkFrame): + __slots__ = ( + '_tabBarTopLayout', '_tabBar', + '_tabColor', '_tabBorderColor', '_tabSelectColor', '_tabOffsetColor', + '_tabColorFocus', '_tabBorderColorFocus', '_tabSelectColorFocus', '_tabOffsetColorFocus', + '_tabWidgets', '_labels', '_labelsPos', + '_offset', '_currentIndex', + '_leftScroller', '_rightScroller', + '_tabMovable', '_tabClosable') + + def __init__(self, *args, **kwargs): + self._tabWidgets = [] + self._labels = [] + self._labelsPos = [] + self._currentIndex = 0 + self._offset = 0 + self._tabMovable = False + self._tabClosable = False + self._leftScroller = False + self._rightScroller = False + self._tabColor = TTkCfg.theme.tabColor + self._tabBorderColor = TTkCfg.theme.tabBorderColor + self._tabSelectColor = TTkCfg.theme.tabSelectColor + self._tabOffsetColor = TTkCfg.theme.tabOffsetColor + self._tabColorFocus = TTkCfg.theme.tabColorFocus + self._tabBorderColorFocus = TTkCfg.theme.tabBorderColorFocus + self._tabSelectColorFocus = TTkCfg.theme.tabSelectColorFocus + self._tabOffsetColorFocus = TTkCfg.theme.tabOffsetColorFocus + self._tabBar = _TTkTabs() + self._tabBar.currentChanged.connect(self._tabChanged) + self._tabBarTopLayout = TTkHBoxLayout() + self._tabBarTopLayout.addWidget(self._tabBar) + TTkFrame.__init__(self, *args, **kwargs) + self._name = kwargs.get('name' , 'TTkTabWidget') + self.setLayout(TTkGridLayout()) + if self.border(): + self.setPadding(3,1,1,1) + else: + self.setPadding(2,0,0,0) + self.rootLayout().addItem(self._tabBarTopLayout) + self._tabBarTopLayout.setGeometry(0,0,self._width,self._padt) + self.setFocusPolicy(TTkK.ClickFocus + TTkK.TabFocus) + + @pyTTkSlot(int) + def _tabChanged(self, index): + for i, widget in enumerate(self._tabWidgets): + if index == i: + widget.show() + else: + widget.hide() + + def addTab(self, widget, label): + widget.hide() + self._tabWidgets.append(widget) + self.layout().addWidget(widget) + self._tabBar.addTab(label) + + def insertTab(self, index, widget, label): + widget.hide() + self._tabWidgets.insert(index, widget) + self.layout().addWidget(widget) + self._tabBar.insertTab(index, label) + + def resizeEvent(self, w, h): + self._tabBarTopLayout.setGeometry(0,0,w,self._padt) + + def paintEvent(self): + if self.hasFocus(): + tabBorderColor = self._tabBorderColorFocus + else: + tabBorderColor = self._tabBorderColor + if self.border(): + self._canvas.drawBox(pos=(0,2),size=(self._width,self._height-2), color=tabBorderColor, grid=9) diff --git a/demo/showcase/tab.py b/demo/showcase/tab.py index a1b6bf0f..a3fbd286 100755 --- a/demo/showcase/tab.py +++ b/demo/showcase/tab.py @@ -22,12 +22,12 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -import sys, os +import sys, os, argparse sys.path.append(os.path.join(sys.path[0],'../..')) import TermTk as ttk -def demoTab(root= None): +def demoTab(root=None): tabWidget1 = ttk.TTkTabWidget(parent=root, border=True) tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.1"), "Label 1.1") tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.2"), "Label 1.2") @@ -42,12 +42,14 @@ def demoTab(root= None): return tabWidget1 def main(): - ttk.TTkLog.use_default_file_logging() + parser = argparse.ArgumentParser() + parser.add_argument('-f', help='Full Screen', action='store_true') + args = parser.parse_args() - fullscreen = False + ttk.TTkLog.use_default_file_logging() root = ttk.TTk() - if fullscreen: + if args.f: rootTab = root root.setLayout(ttk.TTkGridLayout()) else: From 17690f7eb687681c62bbcf7ab2fff7724b83f752 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Sun, 23 May 2021 20:50:55 +0100 Subject: [PATCH 3/5] Added Widget iterator in the layout --- TermTk/TTkCore/helper.py | 13 ++----------- TermTk/TTkLayouts/layout.py | 9 +++++++++ TermTk/TTkWidgets/tabwidget.py | 2 -- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/TermTk/TTkCore/helper.py b/TermTk/TTkCore/helper.py index e9ac784b..c13a466e 100644 --- a/TermTk/TTkCore/helper.py +++ b/TermTk/TTkCore/helper.py @@ -228,15 +228,6 @@ class TTkHelper: layout = layout.parent() return (wx, wy) - def _iterWidgets(item): - for child in item.children(): - if child.layoutItemType == TTkK.WidgetItem: - if not child.widget().isVisible(): continue - yield child.widget() - yield from TTkHelper._iterWidgets(child.widget().rootLayout()) - if child.layoutItemType == TTkK.LayoutItem: - yield from TTkHelper._iterWidgets(child) - def nextFocus(widget): rootWidget = TTkHelper.rootOverlay(widget) if not rootWidget: @@ -244,7 +235,7 @@ class TTkHelper: if widget == rootWidget: widget = None first = None - for w in TTkHelper._iterWidgets(rootWidget.rootLayout()): + for w in rootWidget.rootLayout().iterWidgets(): if not first and w.focusPolicy() & TTkK.TabFocus == TTkK.TabFocus: first = w # TTkLog.debug(f"{w._name} {widget}") @@ -267,7 +258,7 @@ class TTkHelper: if widget == rootWidget: widget = None prev = None - for w in TTkHelper._iterWidgets(rootWidget.rootLayout()): + for w in rootWidget.rootLayout().iterWidgets(): # TTkLog.debug(f"{w._name} {widget}") if w == widget: widget=None diff --git a/TermTk/TTkLayouts/layout.py b/TermTk/TTkLayouts/layout.py index dca6df99..5712f663 100644 --- a/TermTk/TTkLayouts/layout.py +++ b/TermTk/TTkLayouts/layout.py @@ -192,6 +192,15 @@ class TTkLayout(TTkLayoutItem): else: return self._parent.parentWidget() + def iterWidgets(self): + for child in self._items: + if child.layoutItemType == TTkK.WidgetItem: + if not child.widget().isVisible(): continue + yield child.widget() + yield from child.widget().rootLayout().iterWidgets() + if child.layoutItemType == TTkK.LayoutItem: + yield from child.iterWidgets() + def _zSortItems(self): self._zSortedItems = sorted(self._items, key=lambda item: item.z) diff --git a/TermTk/TTkWidgets/tabwidget.py b/TermTk/TTkWidgets/tabwidget.py index d14a18ae..d7f22c1e 100644 --- a/TermTk/TTkWidgets/tabwidget.py +++ b/TermTk/TTkWidgets/tabwidget.py @@ -190,7 +190,6 @@ class _TTkTabs(TTkWidget): leftScroller=self._leftScroller, rightScroller=self._rightScroller, color=tabColor, borderColor=tabBorderColor, selectColor=tabSelectColor, offsetColor=tabOffsetColor) - ''' ┌────────────────────────────┐ │ Root Layout │ @@ -245,7 +244,6 @@ class TTkTabWidget(TTkFrame): self.setPadding(2,0,0,0) self.rootLayout().addItem(self._tabBarTopLayout) self._tabBarTopLayout.setGeometry(0,0,self._width,self._padt) - self.setFocusPolicy(TTkK.ClickFocus + TTkK.TabFocus) @pyTTkSlot(int) def _tabChanged(self, index): From 30887287849786df07d9597631e37f3994e9359b Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Sun, 23 May 2021 22:53:40 +0100 Subject: [PATCH 4/5] Added focusChanged Event, propagate the border color to the tab widgets --- TermTk/TTkWidgets/menubar.py | 5 ++- TermTk/TTkWidgets/tabwidget.py | 72 +++++++++++++++++++++++++++++++--- TermTk/TTkWidgets/widget.py | 53 ++++--------------------- demo/showcase/tab.py | 16 ++++++-- 4 files changed, 90 insertions(+), 56 deletions(-) diff --git a/TermTk/TTkWidgets/menubar.py b/TermTk/TTkWidgets/menubar.py index 7c0b29d3..d750a652 100644 --- a/TermTk/TTkWidgets/menubar.py +++ b/TermTk/TTkWidgets/menubar.py @@ -66,7 +66,7 @@ class _TTkMenuSpacer(TTkAbstractListItem): self._canvas.drawText(pos=(0,0), text="-"*self.width()) class TTkMenuButton(TTkAbstractListItem): - __slots__ = ('_border', '_borderColor', '_shortcut', '_menu', 'menuButtonClicked') + __slots__ = ('_border', '_borderColor', '_shortcut', '_menu', 'menuButtonClicked', '_menuOffset') def __init__(self, *args, **kwargs): TTkAbstractListItem.__init__(self, *args, **kwargs) self._name = kwargs.get('name' , 'TTkMenuButton' ) @@ -75,6 +75,7 @@ class TTkMenuButton(TTkAbstractListItem): self._color = kwargs.get('color', TTkCfg.theme.menuButtonColor ) self._border = kwargs.get('border', TTkCfg.theme.menuButtonColor ) self._borderColor = kwargs.get('borderColor', TTkCfg.theme.menuButtonBorderColor ) + self._menuOffset = kwargs.get('menuOffset', (-1,0) ) self._shortcut = [] self._menu = [] while self._text.find('&') != -1: @@ -137,7 +138,7 @@ class TTkMenuButton(TTkAbstractListItem): pos = (self.width(), -1) else: frame = TTkResizableFrame(layout=TTkHBoxLayout(), size=(frameWidth,frameHeight), title=self._text, titleAlign=TTkK.LEFT_ALIGN) - pos = (-1, 0) + pos = self._menuOffset menuListWidget = _TTkMenuListWidget() listw = TTkList(parent=frame, listWidget = menuListWidget) # listw.textClicked.connect(self._menuCallback) diff --git a/TermTk/TTkWidgets/tabwidget.py b/TermTk/TTkWidgets/tabwidget.py index d7f22c1e..e41dad9f 100644 --- a/TermTk/TTkWidgets/tabwidget.py +++ b/TermTk/TTkWidgets/tabwidget.py @@ -29,10 +29,36 @@ from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal from TermTk.TTkWidgets.widget import TTkWidget from TermTk.TTkWidgets.spacer import TTkSpacer from TermTk.TTkWidgets.frame import TTkFrame +from TermTk.TTkWidgets.menubar import TTkMenuButton from TermTk.TTkLayouts.boxlayout import TTkHBoxLayout from TermTk.TTkLayouts.gridlayout import TTkGridLayout +class _TTkTabMenuButton(TTkMenuButton): + def __init__(self, *args, **kwargs): + TTkMenuButton.__init__(self, *args, **kwargs) + self._name = kwargs.get('name' , '_TTkTabMenuButton') + self.setMaximumHeight(0x1000) + + def paintEvent(self): + if self._pressed: + borderColor = self._borderColor + textColor = TTkCfg.theme.menuButtonColorClicked + scColor = TTkCfg.theme.menuButtonShortcutColor + else: + borderColor = self._borderColor + textColor = self._color + scColor = TTkCfg.theme.menuButtonShortcutColor + self._canvas.drawMenuBarButton( + pos=(0,1),text=self._text, + width=self.width(), + shortcuts=self._shortcut, + border=self._border, + submenu=len(self._menu)>0, + color=textColor, + borderColor=borderColor, + shortcutColor=scColor ) + ''' _curentIndex = 2 _labelPos = [0],[1], [2], [3], [4], @@ -41,7 +67,6 @@ _labels= │◀│La│Label1║Label2║Label3│Label4│▶│ ╞═══════════╩══════╩═══════════════╡ leftscroller rightScroller ''' - class _TTkTabs(TTkWidget): __slots__ = ( '_tabColor', '_tabBorderColor', '_tabSelectColor', '_tabOffsetColor', @@ -84,6 +109,10 @@ class _TTkTabs(TTkWidget): def insertTab(self, index, label): self._labels.insert(index, label) self._updateTabs() + + def setBorderColor(self, color): + self._tabBorderColor = color + self._tabBorderColorFocus = color def _updateTabs(self): xpos = 0+2 @@ -194,7 +223,7 @@ class _TTkTabs(TTkWidget): ┌────────────────────────────┐ │ Root Layout │ │┌────────┬────────┬────────┐│ - ││Right M │ TABS │ Left M ││ + ││ Left M │ TABS │ RightM ││ │└────────┴────────┴────────┘│ │┌──────────────────────────┐│ ││ Layout ││ @@ -205,7 +234,7 @@ class _TTkTabs(TTkWidget): class TTkTabWidget(TTkFrame): __slots__ = ( - '_tabBarTopLayout', '_tabBar', + '_tabBarTopLayout', '_tabBar', '_topLeftLayout', '_topRightLayout', '_tabColor', '_tabBorderColor', '_tabSelectColor', '_tabOffsetColor', '_tabColorFocus', '_tabBorderColorFocus', '_tabSelectColorFocus', '_tabOffsetColorFocus', '_tabWidgets', '_labels', '_labelsPos', @@ -233,8 +262,11 @@ class TTkTabWidget(TTkFrame): self._tabOffsetColorFocus = TTkCfg.theme.tabOffsetColorFocus self._tabBar = _TTkTabs() self._tabBar.currentChanged.connect(self._tabChanged) - self._tabBarTopLayout = TTkHBoxLayout() - self._tabBarTopLayout.addWidget(self._tabBar) + self._tabBar.focusChanged.connect(self._focusChanged) + self._tabBarTopLayout = TTkGridLayout() + self._topLeftLayout = None + self._topRightLayout = None + self._tabBarTopLayout.addWidget(self._tabBar,0,1) TTkFrame.__init__(self, *args, **kwargs) self._name = kwargs.get('name' , 'TTkTabWidget') self.setLayout(TTkGridLayout()) @@ -252,6 +284,34 @@ class TTkTabWidget(TTkFrame): widget.show() else: widget.hide() + + @pyTTkSlot(bool) + def _focusChanged(self, focus): + if focus: + tabBorderColor = self._tabBorderColorFocus + else: + tabBorderColor = self._tabBorderColor + + for widget in self._tabBarTopLayout.iterWidgets(): + widget.setBorderColor(tabBorderColor) + widget.update() + + + def addMenu(self, text, position=TTkK.LEFT): + button = _TTkTabMenuButton(text=text, borderColor=self._tabBorderColor, menuOffset=(-1,1)) + button.focusChanged.connect(self._focusChanged) + if position==TTkK.LEFT: + if not self._topLeftLayout: + self._topLeftLayout = TTkHBoxLayout() + self._tabBarTopLayout.addItem(self._topLeftLayout,0,0) + layout = self._topLeftLayout + else: + if not self._topRightLayout: + self._topRightLayout = TTkHBoxLayout() + self._tabBarTopLayout.addItem(self._topRightLayout,0,2) + layout = self._topRightLayout + layout.addWidget(button) + return button def addTab(self, widget, label): widget.hide() @@ -269,7 +329,7 @@ class TTkTabWidget(TTkFrame): self._tabBarTopLayout.setGeometry(0,0,w,self._padt) def paintEvent(self): - if self.hasFocus(): + if any(w.hasFocus() for w in self._tabBarTopLayout.iterWidgets()): tabBorderColor = self._tabBorderColorFocus else: tabBorderColor = self._tabBorderColor diff --git a/TermTk/TTkWidgets/widget.py b/TermTk/TTkWidgets/widget.py index 45c5989a..d937b2f6 100644 --- a/TermTk/TTkWidgets/widget.py +++ b/TermTk/TTkWidgets/widget.py @@ -91,9 +91,13 @@ class TTkWidget(TMouseEvents,TKeyEvents): '_focus','_focus_policy', '_layout', '_canvas', '_widgetItem', '_visible', '_transparent', - '_pendingMouseRelease') + '_pendingMouseRelease', + #Signals + 'focusChanged') def __init__(self, *args, **kwargs): + #Signals + self.focusChanged = pyTTkSignal(bool) self._name = kwargs.get('name', 'TTkWidget' ) self._parent = kwargs.get('parent', None ) @@ -308,21 +312,10 @@ class TTkWidget(TMouseEvents,TKeyEvents): wevt = evt.clone(pos=(x-wx, y-wy)) if mouseEvent: if wevt is not None: - #if not widget._data['mouse']['underMouse']: - # widget._data['mouse']['underMouse'] = True - # widget.enterEvent(wevt) if widget.mouseEvent(wevt): return True - #else: - # if widget._data['mouse']['underMouse']: - # widget._data['mouse']['underMouse'] = False - # widget.leaveEvent(evt) - # if widget._data['layout'] is not None: - # CuWidget._broadcastLeaveEvent(evt, widget._data['layout']) continue - #if widget.event(evt): - # return True elif item.layoutItemType == TTkK.LayoutItem: levt = evt.clone(pos=(x, y)) if TTkWidget._mouseEventLayoutHandle(levt, item): @@ -347,8 +340,6 @@ class TTkWidget(TMouseEvents,TKeyEvents): return True if evt.evt == TTkK.Release: - #if self.hasFocus(): - # self.clearFocus() self._pendingMouseRelease = False if self.mouseReleaseEvent(evt): return True @@ -365,38 +356,8 @@ class TTkWidget(TMouseEvents,TKeyEvents): if evt.key == TTkK.Wheel: if self.wheelEvent(evt): return True - #if self.focusPolicy() & CuT.WheelFocus == CuT.WheelFocus: - # self.setFocus() - #elif evt.type() == CuEvent.KeyPress: - # self.keyPressEvent(evt) - #elif evt.type() == CuEvent.KeyRelease: - # self.keyReleaseEvent(evt) - # Trigger this event to the childs - return False - #def event(self, evt): - # pass -# # handle own events -# if evt.type() == CuEvent.MouseMove: -# if evt.button() == CuT.NoButton: -# self.mouseMoveEvent(evt) -# elif evt.type() == CuEvent.MouseButtonRelease: -# self.mouseReleaseEvent(evt) -# elif evt.type() == CuEvent.MouseButtonPress: -# self.mousePressEvent(evt) -# if self.focusPolicy() & CuT.ClickFocus == CuT.ClickFocus: -# self.setFocus() -# elif evt.type() == CuEvent.Wheel: -# self.wheelEvent(evt) -# if self.focusPolicy() & CuT.WheelFocus == CuT.WheelFocus: -# self.setFocus() -# elif evt.type() == CuEvent.KeyPress: -# self.keyPressEvent(evt) -# elif evt.type() == CuEvent.KeyRelease: -# self.keyReleaseEvent(evt) -# # Trigger this event to the childs -# if self.layout() is not None: -# return CuWidget._eventLayoutHandle(evt, self.layout()) + return False def setLayout(self, layout): self._layout.replaceItem(layout, 0) @@ -572,12 +533,14 @@ class TTkWidget(TMouseEvents,TKeyEvents): TTkHelper.removeOverlay() TTkHelper.setFocus(self) self._focus = True + self.focusChanged.emit(self._focus) self.focusInEvent() def clearFocus(self): if not self._focus: return TTkHelper.clearFocus() self._focus = False + self.focusChanged.emit(self._focus) self.focusOutEvent() def hasFocus(self): diff --git a/demo/showcase/tab.py b/demo/showcase/tab.py index a3fbd286..3f663191 100755 --- a/demo/showcase/tab.py +++ b/demo/showcase/tab.py @@ -27,8 +27,8 @@ import sys, os, argparse sys.path.append(os.path.join(sys.path[0],'../..')) import TermTk as ttk -def demoTab(root=None): - tabWidget1 = ttk.TTkTabWidget(parent=root, border=True) +def demoTab(root=None, border=True): + tabWidget1 = ttk.TTkTabWidget(parent=root, border=border) tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.1"), "Label 1.1") tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.2"), "Label 1.2") tabWidget1.addTab(ttk.TTkTestWidget( border=True, title="Frame1.3"), "Label Test 1.3") @@ -39,6 +39,14 @@ def demoTab(root=None): tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.8"), "Label 1.8") #tabWidget1.addTab(ttk.TTkTestWidget( border=True, title="Frame1.9"), "Label Test 1.9") #tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.10"), "Label 1.10") + + fileMenu = tabWidget1.addMenu("XX") + fileMenu.addMenu("Open") + fileMenu.addMenu("Close") + fileMenu.addMenu("Exit") + + tabWidget1.addMenu("RIGHT", ttk.TTkK.RIGHT) + return tabWidget1 def main(): @@ -52,9 +60,11 @@ def main(): if args.f: rootTab = root root.setLayout(ttk.TTkGridLayout()) + border=False else: rootTab = ttk.TTkWindow(parent=root,pos=(1,1), size=(100,40), title="Test Tab", border=True, layout=ttk.TTkGridLayout()) - demoTab(rootTab) + border=True + demoTab(rootTab, border) root.mainloop() if __name__ == "__main__": From 779e4536d1e05a1d43ad9dca6d132f7efb787d88 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Tue, 22 Jun 2021 21:59:33 +0100 Subject: [PATCH 5/5] Progress on the tabmenu --- TermTk/TTkCore/canvas.py | 24 +++++++++++++-- TermTk/TTkGui/theme.py | 2 +- TermTk/TTkLayouts/layout.py | 4 +-- TermTk/TTkWidgets/menubar.py | 16 +++++----- TermTk/TTkWidgets/tabwidget.py | 55 +++++++++++++++++++++++++--------- demo/showcase/tab.py | 16 ++++++---- 6 files changed, 85 insertions(+), 32 deletions(-) diff --git a/TermTk/TTkCore/canvas.py b/TermTk/TTkCore/canvas.py index 7d2107df..64517b32 100644 --- a/TermTk/TTkCore/canvas.py +++ b/TermTk/TTkCore/canvas.py @@ -323,11 +323,29 @@ class TTkCanvas: self._set(y+size-1,x, TTkCfg.theme.vscroll[3], color) # Down Arrow pass + def drawTabMenuButton( + self, pos, size, text, slim=False, + color=TTkColor.RST, borderColor=TTkColor.RST, + sideBorder=TTkK.LEFT|TTkK.RIGHT): + x,y = pos + w,h = size + textPos = pos + tt = TTkCfg.theme.tab + # phase 0 - Draw the Bottom bar + if not slim: + borderLeft = tt[27] if sideBorder & TTkK.LEFT else tt[12] + borderRight = tt[28] if sideBorder & TTkK.RIGHT else tt[12] + bottomBar = borderLeft+tt[12]*(w-2)+borderRight + self.drawText(pos=(x,y+2), text=bottomBar, color=borderColor) + textPos = (x,y+1) + self.drawText(pos=textPos, text=text, color=color) + def drawTab( self, pos, size, labels, labelsPos, selected, offset, leftScroller, rightScroller, slim=False, menu=False, - color=TTkColor.RST, borderColor=TTkColor.RST, selectColor=TTkColor.RST, offsetColor=TTkColor.RST): + color=TTkColor.RST, borderColor=TTkColor.RST, selectColor=TTkColor.RST, offsetColor=TTkColor.RST, + sideBorder=TTkK.LEFT|TTkK.RIGHT): x,y = pos w,h = size tt = TTkCfg.theme.tab @@ -336,7 +354,9 @@ class TTkCanvas: bottomBar = tt[18]+tt[19]*(w-2)+tt[20] bottomPos = y+1 else: - bottomBar = tt[11]+tt[12]*(w-2)+tt[15] + borderLeft = tt[11] if sideBorder & TTkK.LEFT else tt[13] if leftScroller else tt[12] + borderRight = tt[15] if sideBorder & TTkK.RIGHT else tt[13] if rightScroller else tt[12] + bottomBar = borderLeft+tt[12]*(w-2)+borderRight bottomPos = y+2 self.drawText(pos=(x,bottomPos),text=bottomBar, color=borderColor) # phase 1 - Draw From left to 'Selected' diff --git a/TermTk/TTkGui/theme.py b/TermTk/TTkGui/theme.py index 5d647d99..b63e8e42 100644 --- a/TermTk/TTkGui/theme.py +++ b/TermTk/TTkGui/theme.py @@ -148,7 +148,7 @@ class TTkTheme(): #11 12 13 14 15 16 17 18 19 20 '╞','═','╧','╩','╡','╘','╛','└','─','┘', #21 22 23 24 25 26 27 28 29 30 - '╚','╝','╰','╯','⣿','⣿','X','X','X','X', + '╚','╝','╰','╯','⣿','⣿','╒','╕','X','X', #31 32 '◀','▶' ) diff --git a/TermTk/TTkLayouts/layout.py b/TermTk/TTkLayouts/layout.py index 5712f663..18bb8ec4 100644 --- a/TermTk/TTkLayouts/layout.py +++ b/TermTk/TTkLayouts/layout.py @@ -192,10 +192,10 @@ class TTkLayout(TTkLayoutItem): else: return self._parent.parentWidget() - def iterWidgets(self): + def iterWidgets(self, onlyVisible=True): for child in self._items: if child.layoutItemType == TTkK.WidgetItem: - if not child.widget().isVisible(): continue + if onlyVisible and not child.widget().isVisible(): continue yield child.widget() yield from child.widget().rootLayout().iterWidgets() if child.layoutItemType == TTkK.LayoutItem: diff --git a/TermTk/TTkWidgets/menubar.py b/TermTk/TTkWidgets/menubar.py index d750a652..6f4389dc 100644 --- a/TermTk/TTkWidgets/menubar.py +++ b/TermTk/TTkWidgets/menubar.py @@ -78,13 +78,13 @@ class TTkMenuButton(TTkAbstractListItem): self._menuOffset = kwargs.get('menuOffset', (-1,0) ) self._shortcut = [] self._menu = [] - while self._text.find('&') != -1: - index = self._text.find('&') - shortcut = self._text[index+1] + while self.text.find('&') != -1: + index = self.text.find('&') + shortcut = self.text[index+1] TTkHelper.addShortcut(self, shortcut) self._shortcut.append(index) - self._text = self._text[:index]+self._text[index+1:] - txtlen = len(self._text) + self.text = self.text[:index]+self.text[index+1:] + txtlen = len(self.text) self.resize(txtlen,1) self.setMinimumSize(txtlen+2,1) self.setMaximumSize(txtlen+2,1) @@ -113,7 +113,7 @@ class TTkMenuButton(TTkAbstractListItem): @pyTTkSlot(TTkButton) def _menuCallback(self, button): #self._id = self._list.index(label) - TTkLog.debug(f"Bind Clicked {button._text}") + TTkLog.debug(f"Bind Clicked {button.text}") self.menuButtonClicked.emit(button) TTkHelper.removeOverlay() self.update() @@ -137,7 +137,7 @@ class TTkMenuButton(TTkAbstractListItem): frame = TTkResizableFrame(layout=TTkHBoxLayout(), size=(frameWidth,frameHeight)) pos = (self.width(), -1) else: - frame = TTkResizableFrame(layout=TTkHBoxLayout(), size=(frameWidth,frameHeight), title=self._text, titleAlign=TTkK.LEFT_ALIGN) + frame = TTkResizableFrame(layout=TTkHBoxLayout(), size=(frameWidth,frameHeight), title=self.text, titleAlign=TTkK.LEFT_ALIGN) pos = self._menuOffset menuListWidget = _TTkMenuListWidget() listw = TTkList(parent=frame, listWidget = menuListWidget) @@ -160,7 +160,7 @@ class TTkMenuButton(TTkAbstractListItem): textColor = self._color scColor = TTkCfg.theme.menuButtonShortcutColor self._canvas.drawMenuBarButton( - pos=(0,0),text=self._text, + pos=(0,0),text=self.text, width=self.width(), shortcuts=self._shortcut, border=self._border, diff --git a/TermTk/TTkWidgets/tabwidget.py b/TermTk/TTkWidgets/tabwidget.py index e41dad9f..08e9aa06 100644 --- a/TermTk/TTkWidgets/tabwidget.py +++ b/TermTk/TTkWidgets/tabwidget.py @@ -35,11 +35,23 @@ from TermTk.TTkLayouts.gridlayout import TTkGridLayout class _TTkTabMenuButton(TTkMenuButton): + __slots__ = ('_sideBorder', '_tabPosition') + def __init__(self, *args, **kwargs): + self._sideBorder = TTkK.NONE + self._tabPosition = kwargs.get('tabPosition', TTkK.LEFT) TTkMenuButton.__init__(self, *args, **kwargs) self._name = kwargs.get('name' , '_TTkTabMenuButton') - self.setMaximumHeight(0x1000) - + txtlen = len(self.text) + self.setMinimumSize(txtlen+1,0x1000) + self.setMaximumSize(txtlen+1,0x1000) + + def setSideBorder(self, border): + self._sideBorder |= border + + def unsetSideBorder(self, border): + self._sideBorder &= ~border + def paintEvent(self): if self._pressed: borderColor = self._borderColor @@ -49,15 +61,16 @@ class _TTkTabMenuButton(TTkMenuButton): borderColor = self._borderColor textColor = self._color scColor = TTkCfg.theme.menuButtonShortcutColor - self._canvas.drawMenuBarButton( - pos=(0,1),text=self._text, - width=self.width(), - shortcuts=self._shortcut, - border=self._border, - submenu=len(self._menu)>0, + if self._tabPosition == TTkK.LEFT: + text = f" {self.text}" + else: + text = f"{self.text} " + self._canvas.drawTabMenuButton( + pos=(0,0),text=text, + size=self.size(), color=textColor, borderColor=borderColor, - shortcutColor=scColor ) + sideBorder = self._sideBorder) ''' _curentIndex = 2 @@ -75,6 +88,7 @@ class _TTkTabs(TTkWidget): '_offset', '_currentIndex','_lastIndex', '_leftScroller', '_rightScroller', '_tabMovable', '_tabClosable', + '_sideBorder', #Signals 'currentChanged') @@ -88,6 +102,7 @@ class _TTkTabs(TTkWidget): self._tabClosable = False self._leftScroller = False self._rightScroller = False + self._sideBorder = TTkK.LEFT | TTkK.RIGHT self._tabColor = TTkCfg.theme.tabColor self._tabBorderColor = TTkCfg.theme.tabBorderColor self._tabSelectColor = TTkCfg.theme.tabSelectColor @@ -109,7 +124,14 @@ class _TTkTabs(TTkWidget): def insertTab(self, index, label): self._labels.insert(index, label) self._updateTabs() - + + def setSideBorder(self, border): + self._sideBorder |= border + + def unsetSideBorder(self, border): + self._sideBorder &= ~border + + def setBorderColor(self, color): self._tabBorderColor = color self._tabBorderColorFocus = color @@ -217,7 +239,8 @@ class _TTkTabs(TTkWidget): labels=self._labels, labelsPos=self._labelsPos, selected=self._currentIndex, offset=self._offset, leftScroller=self._leftScroller, rightScroller=self._rightScroller, - color=tabColor, borderColor=tabBorderColor, selectColor=tabSelectColor, offsetColor=tabOffsetColor) + color=tabColor, borderColor=tabBorderColor, selectColor=tabSelectColor, + offsetColor=tabOffsetColor, sideBorder = self._sideBorder) ''' ┌────────────────────────────┐ @@ -284,7 +307,7 @@ class TTkTabWidget(TTkFrame): widget.show() else: widget.hide() - + @pyTTkSlot(bool) def _focusChanged(self, focus): if focus: @@ -295,21 +318,25 @@ class TTkTabWidget(TTkFrame): for widget in self._tabBarTopLayout.iterWidgets(): widget.setBorderColor(tabBorderColor) widget.update() - def addMenu(self, text, position=TTkK.LEFT): - button = _TTkTabMenuButton(text=text, borderColor=self._tabBorderColor, menuOffset=(-1,1)) + button = _TTkTabMenuButton(text=text, borderColor=self._tabBorderColor, menuOffset=(-1,1), tabPosition=position) button.focusChanged.connect(self._focusChanged) if position==TTkK.LEFT: if not self._topLeftLayout: self._topLeftLayout = TTkHBoxLayout() self._tabBarTopLayout.addItem(self._topLeftLayout,0,0) + button.setSideBorder(TTkK.LEFT) layout = self._topLeftLayout else: if not self._topRightLayout: self._topRightLayout = TTkHBoxLayout() self._tabBarTopLayout.addItem(self._topRightLayout,0,2) layout = self._topRightLayout + button.setSideBorder(TTkK.RIGHT) + for b in self._topRightLayout.iterWidgets(onlyVisible=False): + b.unsetSideBorder(TTkK.RIGHT) + self._tabBar.unsetSideBorder(position) layout.addWidget(button) return button diff --git a/demo/showcase/tab.py b/demo/showcase/tab.py index 3f663191..63e6c960 100755 --- a/demo/showcase/tab.py +++ b/demo/showcase/tab.py @@ -40,12 +40,18 @@ def demoTab(root=None, border=True): #tabWidget1.addTab(ttk.TTkTestWidget( border=True, title="Frame1.9"), "Label Test 1.9") #tabWidget1.addTab(ttk.TTkTestWidgetSizes(border=True, title="Frame1.10"), "Label 1.10") - fileMenu = tabWidget1.addMenu("XX") - fileMenu.addMenu("Open") - fileMenu.addMenu("Close") - fileMenu.addMenu("Exit") + fileMenu1 = tabWidget1.addMenu("XX") + fileMenu1.addMenu("Open") + fileMenu1.addMenu("Close") + fileMenu1.addMenu("Exit") - tabWidget1.addMenu("RIGHT", ttk.TTkK.RIGHT) + fileMenu2 = tabWidget1.addMenu("YY") + fileMenu2.addMenu("Open") + fileMenu2.addMenu("Close") + fileMenu2.addMenu("Exit") + + tabWidget1.addMenu("ZZ", ttk.TTkK.RIGHT) + tabWidget1.addMenu("KK", ttk.TTkK.RIGHT) return tabWidget1