-
Notifications
You must be signed in to change notification settings - Fork 32
Open
Description
There should be other break condition(s) in _draw_text (other than the if...break below, which is the only break implemented). In my first attempt at running example code, the first create_marker call hangs.
- How much of the timeline is visible is what should stop the loop according to the current implementation of
_draw_text- Even if I use root.after to call my
create_markersfunction (to ensure Tk has finished the initial window layout) the hang still occurs. - There are only 3 markers in my example.
- Even if I use root.after to call my
The following patch to _draw_text in timeline.py reveals the issue is an infinite loop, and the output of my raise is "RuntimeError: Too many (1000) bounding boxes. (7 - -7) >= (15.0 - 5.0) :: 14 >= 10.0":
x1_r, _, x2_r, _ = coords
+ count = 0
+ limit = 999
while True:
+ count += 1
text_id = self._timeline.create_text(
(0, 0), text=text,
fill=foreground if foreground != "default" else self._marker_foreground,
font=font if font != "default" else self._marker_font,
tags=("marker",)
)
x1_t, _, x2_t, _ = self._timeline.bbox(text_id)
if (x2_t - x1_t) < (x2_r - x1_r):
break
+ if count > limit:
+ raise RuntimeError(
+ "Too many ({}) bounding boxes. ({} - {}) >= ({} - {}) :: {} >= {}"
+ .format(count, x2_t, x1_t, x2_r, x1_r, (x2_t - x1_t), (x2_r - x1_r)))
self._timeline.delete(text_id)
text = text[:-4] + "..."
- I am not suggesting this is a solution, or the proper break condition. The limit conditional code merely reveals that the loop should have ended earlier (through some better conditional)
- The patch is also useful during testing to reveal the state of the variables in the infinite loop condition.
- However, adding this (with 9999 or something) could be useful such as if you add a unit test based on my example code below in order to ensure there is not a regression once the root cause can be determined and fixed.
Example code (If there is nonsense in the code, it is because it is ChatGPT...regardless, the library should have some kind of way to exit the loop above better, even if there is some nonsense input):
import tkinter as tk
from ttkwidgets.timeline import TimeLine
from collections import OrderedDict
timeline = None
def create_markers():
print("create marker...")
# Add markers to the timeline using create_marker()
timeline.create_marker(
category="Development",
start=5.0, # Start time for the marker
finish=15.0, # Finish time for the marker
text="Requirement Analysis",
foreground="white",
background="blue",
outline="darkblue",
border=2,
)
print("create marker...")
timeline.create_marker(
category="Testing",
start=20.0, # Start time for the marker
finish=30.0, # Finish time for the marker
text="Unit Testing",
foreground="black",
background="green",
outline="darkgreen",
border=2,
)
print("create marker...")
timeline.create_marker(
category="Deployment",
start=40.0, # Start time for the marker
finish=50.0, # Finish time for the marker
text="Initial Deployment",
foreground="white",
background="red",
outline="darkred",
border=2,
)
def create_timeline():
global timeline
# Create the main window
root = tk.Tk()
root.title("TimeLine Widget Example")
root.geometry("1200x800")
# Define categories with valid ttk.Label options
categories = OrderedDict({
"Development": {
"text": "Development",
"foreground": "white",
"background": "blue",
},
"Testing": {
"text": "Testing",
"foreground": "black",
"background": "green",
},
"Deployment": {
"text": "Deployment",
"foreground": "white",
"background": "red",
},
})
# Create the TimeLine widget
timeline = TimeLine(
root,
width=1000, # Width of the timeline in pixels
height=300, # Height of the timeline in pixels
extend=True, # Allow extending timeline when needed
start=0.0, # Start value for the timeline (float)
finish=100.0, # Finish value for the timeline (float)
resolution=1.0, # Seconds per pixel (float)
tick_resolution=10.0, # Ticks every 10 seconds (float)
unit="s", # Seconds as the unit
zoom_enabled=True, # Enable zooming
categories=categories, # Add categories to the timeline
background="white", # Background color
style="TFrame", # Apply a style to the frame
zoom_factors=(1.0, 2.0, 5.0), # Allowed zoom levels
zoom_default=1.0, # Default zoom level
snap_margin=5, # Snap to ticks within 5 pixels
autohidescrollbars=True # Use AutoHideScrollbars
)
print("pack...")
timeline.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# root.after(500, create_markers) # attempted solve of issue #110, but doesn't solve
create_markers()
print("mainloop...")
# Run the Tkinter main loop
root.mainloop()
if __name__ == "__main__":
create_timeline()Metadata
Metadata
Assignees
Labels
No labels