-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
UI: improve tab options displaying used environment variables and usi…
…ng collapsible frames (#330)
- Loading branch information
Showing
5 changed files
with
374 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
#! python3 # noqa: E265 | ||
|
||
|
||
""" | ||
Name: Custom collapsible frame | ||
Purpose: Allow toggle a frame in pure Python Tkinter. | ||
Author: Julien Moura (@geojulien) | ||
Sources: | ||
- ttkwidgets (GPL 3) | ||
- Onlyjus (https://stackoverflow.com/a/13169685/2556577) | ||
""" | ||
|
||
# ############################################################################## | ||
# ########## Libraries ############# | ||
# ################################## | ||
|
||
# Standard library | ||
import logging | ||
from tkinter import BooleanVar | ||
from tkinter.ttk import Button, Frame, Label, Widget | ||
|
||
# ############################################################################## | ||
# ############ Globals ############ | ||
# ################################# | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
# ############################################################################## | ||
# ########## Classes ############### | ||
# ################################## | ||
|
||
|
||
class ToggledFrame(Frame): | ||
"""A frame that can be toggled to open and close.""" | ||
|
||
def __init__( | ||
self, | ||
parent: Widget = None, | ||
in_text: str = "", | ||
toggle_width: int = 2, | ||
start_opened: bool = True, | ||
**kwargs, | ||
): | ||
"""Initializes UI tab for end-user options. | ||
Args: | ||
parent: tkinter parent object | ||
in_text: text to display next to the toggle arrow. Defaults to empty string. | ||
toggle_width: width of the tgogle button(in characters). Defaults to 2. | ||
kwargs: keyword arguments passed on to the :class:`ttk.Frame` initializer | ||
""" | ||
super().__init__(parent, **kwargs) | ||
|
||
# variables | ||
self.is_open_var = BooleanVar(value=start_opened) | ||
|
||
# frame containing tool button and label | ||
self.title_frame = Frame(self) | ||
self.lbl_frame = Label(self.title_frame, text=in_text) | ||
self.btn_toggle = Button( | ||
self.title_frame, | ||
command=self.toggle, | ||
style="Toolbutton", | ||
text="-" if start_opened is True else "+", | ||
width=toggle_width, | ||
) | ||
|
||
self.sub_frame = Frame(self) | ||
|
||
self._grid_widgets() | ||
self.toggle() | ||
|
||
def _grid_widgets(self): | ||
"""Grid frame widgets.""" | ||
self.title_frame.grid(sticky="WE") | ||
self.title_frame.grid_columnconfigure(0, weight=1) | ||
self.lbl_frame.grid(row=0, column=0, sticky="W", padx=15) | ||
self.btn_toggle.grid(row=0, column=1, sticky="E") | ||
|
||
def toggle(self): | ||
"""Toggle opened or closed.""" | ||
if self.is_open_var.get(): | ||
self._open = False | ||
self.sub_frame.grid(row=1, sticky="nswe") | ||
self.btn_toggle.configure(text="-") | ||
else: | ||
self._open = True | ||
self.sub_frame.grid_forget() | ||
|
||
self.btn_toggle.configure(text="+") | ||
|
||
self.is_open_var.set(not self.is_open_var.get()) | ||
|
||
|
||
if __name__ == "__main__": | ||
from tkinter import Tk | ||
from tkinter.ttk import Button | ||
|
||
root = Tk() | ||
|
||
collapsible_frame = ToggledFrame( | ||
parent=root, | ||
in_text="Rotate", | ||
start_opened=True, | ||
borderwidth=2, | ||
relief="raised", | ||
) | ||
collapsible_frame.pack() | ||
button = Button( | ||
collapsible_frame.sub_frame, text="Close window", command=root.destroy | ||
) | ||
button.grid() | ||
collapsible_frame.toggle() | ||
root.mainloop() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
from tkinter import Event | ||
from tkinter.ttk import Frame, Scrollbar, Treeview, Widget | ||
|
||
from dicogis.utils.texts import TextsManager | ||
|
||
|
||
class ScrollableTable(Frame): | ||
""" | ||
A scrollable table with two columns in read-only mode. | ||
Attributes: | ||
tree (ttk.Treeview): The Treeview widget for displaying the table. | ||
vsb (ttk.Scrollbar): The vertical scrollbar for the Treeview. | ||
""" | ||
|
||
def __init__( | ||
self, | ||
parent: Widget, | ||
localized_strings: dict | None = None, | ||
init_widgets: bool = True, | ||
): | ||
"""Initialize the ScrollableTable frame. | ||
Args: | ||
parent (tk.Widget): The parent widget. | ||
init_widgets: option to create widgets during init or not. Defaults to True. | ||
""" | ||
super().__init__(parent) | ||
|
||
# handle empty localized strings | ||
self.localized_strings = localized_strings | ||
if self.localized_strings is None: | ||
self.localized_strings = TextsManager().load_texts() | ||
|
||
if init_widgets: | ||
self.create_widgets() | ||
|
||
def create_widgets(self) -> None: | ||
"""Create and layout the widgets for the frame.""" | ||
# Create Treeview with 2 columns | ||
self.tree = Treeview( | ||
self, | ||
columns=("column1", "column2"), | ||
show="headings", | ||
height=3, | ||
selectmode="browse", | ||
) | ||
self.tree.heading("column1", text=self.localized_strings.get("key", "Key")) | ||
self.tree.heading("column2", text=self.localized_strings.get("value", "Value")) | ||
|
||
# Make the columns read-only | ||
# self.tree.bind("<1>", self.disable_event) | ||
|
||
# Add a vertical scrollbar | ||
self.vsb = Scrollbar( | ||
self, | ||
orient="vertical", | ||
name="env_var_table_vert_scroll", | ||
command=self.tree.yview, | ||
) | ||
self.tree.configure(yscrollcommand=self.vsb.set) | ||
|
||
# Layout the Treeview and Scrollbar | ||
self.tree.grid(row=0, column=0, sticky="NSEW") | ||
self.vsb.grid(row=0, column=1, sticky="NS") | ||
|
||
# Make the frame expandable | ||
self.grid_rowconfigure(0, weight=1) | ||
self.grid_columnconfigure(0, weight=1) | ||
|
||
def disable_event(self, event: Event) -> str: | ||
""" | ||
Disable the event to make the Treeview read-only. | ||
Args: | ||
event (Event): The event object. | ||
Returns: | ||
str: "break" to indicate that the event should be ignored. | ||
""" | ||
return "break" |
Oops, something went wrong.