Skip to content

Tkinter standardised approach#203

Open
Felix-Mallinder wants to merge 29 commits intodevelopfrom
Python_Toolkit-#202-Tkiner-UI-BHoM-Standardisation
Open

Tkinter standardised approach#203
Felix-Mallinder wants to merge 29 commits intodevelopfrom
Python_Toolkit-#202-Tkiner-UI-BHoM-Standardisation

Conversation

@Felix-Mallinder
Copy link
Contributor

@Felix-Mallinder Felix-Mallinder commented Feb 24, 2026

NOTE: Depends on

Issues addressed by this PR

Closes #202

Set up of BHoM standard approach for tkinter UIs

Test files

Can test by running any of the windows or widget objects - each has an example usage method in the file

Test script added to the test folder

Changelog

  • Set of scripts / methods developed in python_toolkit.bhom_tkinter for a modular approach to tkinter usage in dependant bhom toolkits.
  • BHoMBaseWindow has been established as a base object for all tkinter UI tools to inherit from, this handles base attributes such as styling.
  • bhom_tkinter.windows contains a series of pre-produced window objects, for direct use, including loading windows, warning windows etc.
  • bhom_tkinter.widgets includes a series of widgets to be used when building up a UI. these widgets inherit from BHoMBaseWidget for handling of get, set, packing & build protocols
  • .tcl sheets have been set for bhom styling, in dark and light mode. widgets use bhom logos and icons

Additional comments

@Felix-Mallinder Felix-Mallinder self-assigned this Feb 24, 2026
@Felix-Mallinder Felix-Mallinder added the type:feature New capability or enhancement label Feb 24, 2026
@Felix-Mallinder Felix-Mallinder linked an issue Feb 24, 2026 that may be closed by this pull request
@Felix-Mallinder Felix-Mallinder added the status:WIP PR in progress and still in draft, not ready for formal review label Feb 25, 2026
Copy link
Contributor

@Tom-Kingstone Tom-Kingstone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good code wise on first cursory pass except a few comments, Will test when changes stop coming through.

Comment on lines +38 to +46
def _on_click(self):
"""Internal click handler increments counter and calls user callback."""
self._click_count += 1
if self._user_command:
try:
self._user_command()
except Exception:
# Keep widget robust; do not propagate callback errors
pass
Copy link
Contributor

@Tom-Kingstone Tom-Kingstone Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might not be ideal to just catch exceptions and ignore them with no output, I would be more comfortable if it were to catch and write the stack trace to a logging method for instance.

Suggested change
def _on_click(self):
"""Internal click handler increments counter and calls user callback."""
self._click_count += 1
if self._user_command:
try:
self._user_command()
except Exception:
# Keep widget robust; do not propagate callback errors
pass
def _on_click(self):
"""Internal click handler increments counter and calls user callback."""
self._click_count += 1
if self._user_command:
try:
self._user_command()
except Exception:
CONSOLE_LOGGER.error("Unhandled exception when trying to perform button widget `on_click` command.", exc_info=1)
# Keep widget robust; do not propagate callback errors
pass

(exc_info just adds the stack trace to the error message as if it was an exception readout)
You can add as much info as desired to the error log, for instance the component ID, the name of the command etc.

Another option would be to show an error box to the user, but that might be best left to the called method to handle, as far as I can tell this is just an extra fallback in case something drastic happens.

tmp_doc_audit.py Outdated
Copy link
Contributor

@Tom-Kingstone Tom-Kingstone Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove temporary files

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Comment on lines +260 to +278
def build(
self,
build_type: Literal['pack', 'grid', 'place'] = 'pack',
**kwargs
):
"""Place the widget in its parent container.

Args:
build_type: Geometry manager strategy (`pack`, `grid`, or `place`).
**kwargs: Additional geometry manager options.
"""
if build_type == 'pack':
self.pack(**self.packing_options.to_dict())

elif build_type == 'grid':
raise NotImplementedError("Grid packing is not yet implemented for BHoMBaseWidget.")

elif build_type == 'place':
raise NotImplementedError("Place packing is not yet implemented for BHoMBaseWidget.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with this as is (I assume that the caller can still call .pack with grid or place anyway, just doesn't get the benefit of using packing_options), but it would be good to have an issue for grid at least as it's (in my opinion) the more useful of the not implemented methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grid is on the todo list, will implement before removing WIP from this PR

@Tom-Kingstone
Copy link
Contributor

@BHoMBot check installer -force

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status:WIP PR in progress and still in draft, not ready for formal review type:feature New capability or enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tkinter UI BHoM standardisation

2 participants