spacr 0.1.0__py3-none-any.whl → 0.1.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
spacr/gui_mask_app.py CHANGED
@@ -97,19 +97,23 @@ def import_settings(scrollable_frame):
97
97
  vars_dict = generate_fields(new_settings, scrollable_frame)
98
98
 
99
99
  #@log_function_call
100
- def initiate_mask_root(parent_frame, width, height):
100
+ def initiate_mask_root(parent_frame):
101
101
  global vars_dict, q, canvas, fig_queue, canvas_widget, thread_control, advanced_var, scrollable_frame
102
102
 
103
103
  style = ttk.Style(parent_frame)
104
104
  set_dark_style(style)
105
105
  style_text_boxes(style)
106
- set_default_font(parent_frame, font_name="Arial", size=8)
106
+ set_default_font(parent_frame, font_name="Helvetica", size=8)
107
107
  parent_frame.configure(bg='black')
108
108
  parent_frame.grid_rowconfigure(0, weight=1)
109
109
  parent_frame.grid_columnconfigure(0, weight=1)
110
110
 
111
111
  fig_queue = Queue()
112
112
 
113
+ # Initialize after_tasks if not already done
114
+ if not hasattr(parent_frame, 'after_tasks'):
115
+ parent_frame.after_tasks = []
116
+
113
117
  def _process_fig_queue():
114
118
  global canvas
115
119
  try:
@@ -130,14 +134,20 @@ def initiate_mask_root(parent_frame, width, height):
130
134
  except Exception as e:
131
135
  traceback.print_exc()
132
136
  finally:
133
- canvas_widget.after(100, _process_fig_queue)
137
+ after_id = canvas_widget.after(100, _process_fig_queue)
138
+ parent_frame.after_tasks.append(after_id)
134
139
 
135
140
  def _process_console_queue():
136
141
  while not q.empty():
137
142
  message = q.get_nowait()
138
143
  console_output.insert(tk.END, message)
139
144
  console_output.see(tk.END)
140
- console_output.after(100, _process_console_queue)
145
+ after_id = console_output.after(100, _process_console_queue)
146
+ parent_frame.after_tasks.append(after_id)
147
+
148
+ # Clear previous content if any
149
+ for widget in parent_frame.winfo_children():
150
+ widget.destroy()
141
151
 
142
152
  vertical_container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL)
143
153
  vertical_container.grid(row=0, column=0, sticky=tk.NSEW)
@@ -164,25 +174,27 @@ def initiate_mask_root(parent_frame, width, height):
164
174
  vars_dict['Test mode'] = (None, None, tk.BooleanVar(value=False))
165
175
 
166
176
  # Button section
167
- test_mode_button = CustomButton(scrollable_frame.scrollable_frame, text="Test Mode", command=toggle_test_mode)
177
+ test_mode_button = CustomButton(scrollable_frame.scrollable_frame, text="Test Mode", command=toggle_test_mode, font=('Helvetica', 10))
178
+ #CustomButton(buttons_frame, text=app_name, command=lambda app_name=app_name: self.load_app(app_name, app_func), font=('Helvetica', 12))
179
+
168
180
  test_mode_button.grid(row=47, column=1, pady=10, padx=10)
169
- import_btn = CustomButton(scrollable_frame.scrollable_frame, text="Import", command=lambda: import_settings(scrollable_frame))
181
+ import_btn = CustomButton(scrollable_frame.scrollable_frame, text="Import", command=lambda: import_settings(scrollable_frame), font=('Helvetica', 10))
170
182
  import_btn.grid(row=47, column=0, pady=10, padx=10)
171
183
  run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue))
172
184
  run_button.grid(row=45, column=0, pady=10, padx=10)
173
- abort_button = CustomButton(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort)
185
+ abort_button = CustomButton(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort, font=('Helvetica', 10))
174
186
  abort_button.grid(row=45, column=1, pady=10, padx=10)
175
- progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Processing: 0%", background="black", foreground="white") # Create progress field
187
+ progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Processing: 0%", background="black", foreground="white")
176
188
  progress_label.grid(row=50, column=0, columnspan=2, sticky="ew", pady=(5, 0), padx=10)
177
189
 
178
190
  # Plot Canvas Section
179
- plot_frame = tk.PanedWindow(vertical_container, orient=tk.VERTICAL) # Horizontal container for Matplotlib figure and the vertical pane (for settings and console)
191
+ plot_frame = tk.PanedWindow(vertical_container, orient=tk.VERTICAL)
180
192
  vertical_container.add(plot_frame, stretch="always")
181
- figure = Figure(figsize=(30, 4), dpi=100, facecolor='black') # Matplotlib figure setup
193
+ figure = Figure(figsize=(30, 4), dpi=100, facecolor='black')
182
194
  plot = figure.add_subplot(111)
183
195
  plot.plot([], []) # This creates an empty plot.
184
196
  plot.axis('off')
185
- canvas = FigureCanvasTkAgg(figure, master=plot_frame) # Embedd Matplotlib figure in Tkinter window
197
+ canvas = FigureCanvasTkAgg(figure, master=plot_frame)
186
198
  canvas.get_tk_widget().configure(cursor='arrow', background='black', highlightthickness=0)
187
199
  canvas_widget = canvas.get_tk_widget()
188
200
  plot_frame.add(canvas_widget, stretch="always")
@@ -206,15 +218,30 @@ def initiate_mask_root(parent_frame, width, height):
206
218
  _process_console_queue()
207
219
  _process_fig_queue()
208
220
 
209
- parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
221
+ after_id = parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
222
+ parent_frame.after_tasks.append(after_id)
210
223
 
211
224
  return parent_frame, vars_dict
212
225
 
213
226
  def gui_mask():
214
227
  root = tk.Tk()
215
- root.geometry("1000x800")
216
- root.title("SpaCer: generate masks")
217
- initiate_mask_root(root, 1000, 800)
228
+ width = root.winfo_screenwidth()
229
+ height = root.winfo_screenheight()
230
+ root.geometry(f"{width}x{height}")
231
+ root.title("SpaCr: generate masks")
232
+
233
+ # Clear previous content if any
234
+ if hasattr(root, 'content_frame'):
235
+ for widget in root.content_frame.winfo_children():
236
+ widget.destroy()
237
+ root.content_frame.grid_forget()
238
+ else:
239
+ root.content_frame = tk.Frame(root)
240
+ root.content_frame.grid(row=1, column=0, sticky="nsew")
241
+ root.grid_rowconfigure(1, weight=1)
242
+ root.grid_columnconfigure(0, weight=1)
243
+
244
+ initiate_mask_root(root.content_frame)
218
245
  create_menu_bar(root)
219
246
  root.mainloop()
220
247
 
spacr/gui_measure_app.py CHANGED
@@ -19,6 +19,15 @@ from .gui_utils import measure_variables, measure_crop_wrapper, clear_canvas, ch
19
19
 
20
20
  thread_control = {"run_thread": None, "stop_requested": False}
21
21
 
22
+ def import_settings(scrollable_frame):
23
+ global vars_dict
24
+
25
+ csv_file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
26
+ csv_settings = read_settings_from_csv(csv_file_path)
27
+ variables = measure_variables()
28
+ new_settings = update_settings_from_csv(variables, csv_settings)
29
+ vars_dict = generate_fields(new_settings, scrollable_frame)
30
+
22
31
  def toggle_test_mode():
23
32
  global vars_dict
24
33
  current_state = vars_dict['test_mode'][2].get()
@@ -86,29 +95,24 @@ def initiate_abort():
86
95
  thread_control["run_thread"] = None
87
96
 
88
97
  #@log_function_call
89
- def import_settings(scrollable_frame):
90
- global vars_dict
91
-
92
- csv_file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
93
- csv_settings = read_settings_from_csv(csv_file_path)
94
- variables = measure_variables()
95
- new_settings = update_settings_from_csv(variables, csv_settings)
96
- vars_dict = generate_fields(new_settings, scrollable_frame)
97
-
98
- #@log_function_call
99
- def initiate_measure_root(parent_frame):#, width, height):
98
+ def initiate_measure_root(parent_frame):
100
99
  global vars_dict, q, canvas, fig_queue, canvas_widget, thread_control, variables, advanced_var, scrollable_frame
101
100
 
102
101
  style = ttk.Style(parent_frame)
103
102
  set_dark_style(style)
104
103
  style_text_boxes(style)
105
- set_default_font(parent_frame, font_name="Arial", size=8)
104
+ set_default_font(parent_frame, font_name="Helvetica", size=8)
106
105
 
107
106
  parent_frame.configure(bg='black')
108
107
  parent_frame.grid_rowconfigure(0, weight=1)
109
108
  parent_frame.grid_columnconfigure(0, weight=1)
109
+
110
110
  fig_queue = Queue()
111
111
 
112
+ # Initialize after_tasks if not already done
113
+ if not hasattr(parent_frame, 'after_tasks'):
114
+ parent_frame.after_tasks = []
115
+
112
116
  def _process_fig_queue():
113
117
  global canvas
114
118
  try:
@@ -129,14 +133,20 @@ def initiate_measure_root(parent_frame):#, width, height):
129
133
  except Exception as e:
130
134
  traceback.print_exc()
131
135
  finally:
132
- canvas_widget.after(100, _process_fig_queue)
136
+ after_id = canvas_widget.after(100, _process_fig_queue)
137
+ parent_frame.after_tasks.append(after_id)
133
138
 
134
139
  def _process_console_queue():
135
140
  while not q.empty():
136
141
  message = q.get_nowait()
137
142
  console_output.insert(tk.END, message)
138
143
  console_output.see(tk.END)
139
- console_output.after(100, _process_console_queue)
144
+ after_id = console_output.after(100, _process_console_queue)
145
+ parent_frame.after_tasks.append(after_id)
146
+
147
+ # Clear previous content if any
148
+ for widget in parent_frame.winfo_children():
149
+ widget.destroy()
140
150
 
141
151
  vertical_container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL)
142
152
  vertical_container.grid(row=0, column=0, sticky=tk.NSEW)
@@ -165,11 +175,11 @@ def initiate_measure_root(parent_frame):#, width, height):
165
175
  # Button section
166
176
  test_mode_button = CustomButton(scrollable_frame.scrollable_frame, text="Test Mode", command=toggle_test_mode)
167
177
  test_mode_button.grid(row=47, column=1, pady=10, padx=10)
168
- import_btn = CustomButton(scrollable_frame.scrollable_frame, text="Import Settings", command=lambda: import_settings(scrollable_frame))
178
+ import_btn = CustomButton(scrollable_frame.scrollable_frame, text="Import", command=lambda: import_settings(scrollable_frame), font=('Helvetica', 10))
169
179
  import_btn.grid(row=47, column=0, pady=20, padx=20)
170
- run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue))
180
+ run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue), font=('Helvetica', 10))
171
181
  run_button.grid(row=45, column=0, pady=20, padx=20)
172
- abort_button = CustomButton(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort)
182
+ abort_button = CustomButton(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort, font=('Helvetica', 10))
173
183
  abort_button.grid(row=45, column=1, pady=20, padx=20)
174
184
  progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Processing: 0%", background="black", foreground="white") # Create progress field
175
185
  progress_label.grid(row=50, column=0, columnspan=2, sticky="ew", pady=(5, 0), padx=10)
@@ -205,15 +215,30 @@ def initiate_measure_root(parent_frame):#, width, height):
205
215
  _process_console_queue()
206
216
  _process_fig_queue()
207
217
 
208
- parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
218
+ after_id = parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
219
+ parent_frame.after_tasks.append(after_id)
209
220
 
210
221
  return parent_frame, vars_dict
211
222
 
212
223
  def gui_measure():
213
224
  root = tk.Tk()
214
- root.geometry("1000x800")
215
- root.title("SpaCer: generate masks")
216
- initiate_measure_root(root, 1000, 800)
225
+ width = root.winfo_screenwidth()
226
+ height = root.winfo_screenheight()
227
+ root.geometry(f"{width}x{height}")
228
+ root.title("SpaCr: measure objects")
229
+
230
+ # Clear previous content if any
231
+ if hasattr(root, 'content_frame'):
232
+ for widget in root.content_frame.winfo_children():
233
+ widget.destroy()
234
+ root.content_frame.grid_forget()
235
+ else:
236
+ root.content_frame = tk.Frame(root)
237
+ root.content_frame.grid(row=1, column=0, sticky="nsew")
238
+ root.grid_rowconfigure(1, weight=1)
239
+ root.grid_columnconfigure(0, weight=1)
240
+
241
+ initiate_measure_root(root.content_frame)
217
242
  create_menu_bar(root)
218
243
  root.mainloop()
219
244
 
spacr/gui_utils.py CHANGED
@@ -40,25 +40,35 @@ class ToolTip:
40
40
  self.tooltip_window.destroy()
41
41
  self.tooltip_window = None
42
42
 
43
-
44
43
  def load_app(root, app_name, app_func):
45
- # Destroy the current window
46
- root.destroy()
47
- # Create a new window for the app
48
- app_window = tk.Tk()
49
- app_window.title(f"SpaCr - {app_name}")
50
- app_window.geometry("1200x800")
51
- #app_window.attributes('-fullscreen', True)
52
- app_window.configure(bg="black")
53
- create_menu_bar(app_window) # Add menu to the new window
54
- app_func(app_window, app_window.winfo_width(), app_window.winfo_height())
44
+ # Cancel all scheduled after tasks
45
+ if hasattr(root, 'after_tasks'):
46
+ for task in root.after_tasks:
47
+ root.after_cancel(task)
48
+ root.after_tasks = []
49
+
50
+ # Exit functionality only for the annotation app
51
+ if app_name == "Annotate" and hasattr(root, 'current_app_exit_func'):
52
+ root.current_app_exit_func()
53
+
54
+ # Clear the current content frame
55
+ if hasattr(root, 'content_frame'):
56
+ for widget in root.content_frame.winfo_children():
57
+ widget.destroy()
58
+ else:
59
+ root.content_frame = tk.Frame(root)
60
+ root.content_frame.grid(row=1, column=0, sticky="nsew")
61
+ root.grid_rowconfigure(1, weight=1)
62
+ root.grid_columnconfigure(0, weight=1)
55
63
 
56
- def create_menu_bar(root):
64
+ # Initialize the new app in the content frame
65
+ app_func(root.content_frame)
57
66
 
67
+ def create_menu_bar(root):
58
68
  from .gui_mask_app import initiate_mask_root
59
69
  from .gui_measure_app import initiate_measure_root
60
70
  from .annotate_app import initiate_annotation_app_root
61
- from .mask_app import initiate_mask_app_root
71
+ from .gui_make_masks_app import initiate_mask_app_root
62
72
  from .gui_classify_app import initiate_classify_root
63
73
 
64
74
  gui_apps = {
@@ -68,6 +78,10 @@ def create_menu_bar(root):
68
78
  "Make Masks": initiate_mask_app_root,
69
79
  "Classify": initiate_classify_root
70
80
  }
81
+
82
+ def load_app_wrapper(app_name, app_func):
83
+ load_app(root, app_name, app_func)
84
+
71
85
  # Create the menu bar
72
86
  menu_bar = tk.Menu(root, bg="#008080", fg="white")
73
87
  # Create a "SpaCr Applications" menu
@@ -75,15 +89,75 @@ def create_menu_bar(root):
75
89
  menu_bar.add_cascade(label="SpaCr Applications", menu=app_menu)
76
90
  # Add options to the "SpaCr Applications" menu
77
91
  for app_name, app_func in gui_apps.items():
78
- app_menu.add_command(label=app_name, command=lambda app_name=app_name, app_func=app_func: load_app(root, app_name, app_func))
92
+ app_menu.add_command(label=app_name, command=lambda app_name=app_name, app_func=app_func: load_app_wrapper(app_name, app_func))
79
93
  # Add a separator and an exit option
80
94
  app_menu.add_separator()
81
95
  app_menu.add_command(label="Exit", command=root.quit)
82
96
  # Configure the menu for the root window
83
97
  root.config(menu=menu_bar)
84
98
 
99
+ def load_app(root, app_name, app_func):
100
+ # Cancel all scheduled after tasks
101
+ if hasattr(root, 'after_tasks'):
102
+ for task in root.after_tasks:
103
+ root.after_cancel(task)
104
+ root.after_tasks = []
105
+
106
+ def proceed_with_app():
107
+ # Clear the current content frame
108
+ if hasattr(root, 'content_frame'):
109
+ for widget in root.content_frame.winfo_children():
110
+ widget.destroy()
111
+ else:
112
+ root.content_frame = tk.Frame(root)
113
+ root.content_frame.grid(row=1, column=0, sticky="nsew")
114
+ root.grid_rowconfigure(1, weight=1)
115
+ root.grid_columnconfigure(0, weight=1)
116
+
117
+ # Initialize the new app in the content frame
118
+ app_func(root.content_frame)
119
+
120
+ # Exit functionality only for the annotation app
121
+ if app_name != "Annotate" and hasattr(root, 'current_app_exit_func'):
122
+ root.next_app_func = proceed_with_app
123
+ root.current_app_exit_func()
124
+ else:
125
+ proceed_with_app()
126
+
127
+ def create_menu_bar(root):
128
+ from .gui_mask_app import initiate_mask_root
129
+ from .gui_measure_app import initiate_measure_root
130
+ from .annotate_app import initiate_annotation_app_root
131
+ from .gui_make_masks_app import initiate_mask_app_root
132
+ from .gui_classify_app import initiate_classify_root
133
+
134
+ gui_apps = {
135
+ "Mask": initiate_mask_root,
136
+ "Measure": initiate_measure_root,
137
+ "Annotate": initiate_annotation_app_root,
138
+ "Make Masks": initiate_mask_app_root,
139
+ "Classify": initiate_classify_root
140
+ }
141
+
142
+ def load_app_wrapper(app_name, app_func):
143
+ load_app(root, app_name, app_func)
144
+
145
+ # Create the menu bar
146
+ menu_bar = tk.Menu(root, bg="#008080", fg="white")
147
+ # Create a "SpaCr Applications" menu
148
+ app_menu = tk.Menu(menu_bar, tearoff=0, bg="#008080", fg="white")
149
+ menu_bar.add_cascade(label="SpaCr Applications", menu=app_menu)
150
+ # Add options to the "SpaCr Applications" menu
151
+ for app_name, app_func in gui_apps.items():
152
+ app_menu.add_command(label=app_name, command=lambda app_name=app_name, app_func=app_func: load_app_wrapper(app_name, app_func))
153
+ # Add a separator and an exit option
154
+ app_menu.add_separator()
155
+ app_menu.add_command(label="Exit", command=root.destroy) # Use root.destroy instead of root.quit
156
+ # Configure the menu for the root window
157
+ root.config(menu=menu_bar)
158
+
85
159
  class CustomButton(tk.Frame):
86
- def __init__(self, parent, text="", command=None, *args, **kwargs):
160
+ def __init__(self, parent, text="", command=None, font=None, *args, **kwargs):
87
161
  super().__init__(parent, *args, **kwargs)
88
162
  self.text = text
89
163
  self.command = command
@@ -93,8 +167,8 @@ class CustomButton(tk.Frame):
93
167
 
94
168
  self.button_bg = self.create_rounded_rectangle(0, 0, 150, 50, radius=20, fill="#800080")
95
169
 
96
- # Create a Tkinter font object using OpenSans
97
- self.font_style = tkFont.Font(family="Arial", size=12, weight=tkFont.NORMAL)
170
+ # Use the passed font or default to Helvetica if not provided
171
+ self.font_style = font if font else tkFont.Font(family="Helvetica", size=12, weight=tkFont.NORMAL)
98
172
  self.button_text = self.canvas.create_text(75, 25, text=self.text, fill="white", font=self.font_style)
99
173
 
100
174
  self.bind("<Enter>", self.on_enter)
@@ -137,7 +211,7 @@ class CustomButton(tk.Frame):
137
211
  x1, y1]
138
212
 
139
213
  return self.canvas.create_polygon(points, **kwargs, smooth=True)
140
-
214
+
141
215
  class ToggleSwitch(ttk.Frame):
142
216
  def __init__(self, parent, text="", variable=None, command=None, *args, **kwargs):
143
217
  super().__init__(parent, *args, **kwargs)
@@ -226,15 +300,47 @@ class ToggleSwitch(ttk.Frame):
226
300
 
227
301
  return self.canvas.create_polygon(points, **kwargs, smooth=True)
228
302
 
229
- def set_default_font(root, font_name="Arial", size=12):
303
+ def set_default_font(root, font_name="Helvetica", size=12):
230
304
  default_font = (font_name, size)
231
305
  root.option_add("*Font", default_font)
232
306
  root.option_add("*TButton.Font", default_font)
233
307
  root.option_add("*TLabel.Font", default_font)
234
308
  root.option_add("*TEntry.Font", default_font)
235
309
 
310
+ def check_and_download_font_v1():
311
+ font_name = "Helvetica"
312
+ font_dir = "fonts"
313
+ font_path = os.path.join(font_dir, "OpenSans-Regular.ttf")
314
+
315
+ # Check if the font is already available
316
+ available_fonts = list(tkFont.families())
317
+ if font_name not in available_fonts:
318
+ print(f"Font '{font_name}' not found. Downloading...")
319
+ if not os.path.exists(font_dir):
320
+ os.makedirs(font_dir)
321
+
322
+ if not os.path.exists(font_path):
323
+ url = "https://github.com/google/fonts/blob/main/apache/opensans/OpenSans-Regular.ttf?raw=true"
324
+ response = requests.get(url)
325
+ with open(font_path, "wb") as f:
326
+ f.write(response.content)
327
+
328
+ # Load the font
329
+ try:
330
+ tkFont.nametofont("TkDefaultFont").configure(family=font_name, size=10)
331
+ tkFont.nametofont("TkTextFont").configure(family=font_name, size=10)
332
+ tkFont.nametofont("TkHeadingFont").configure(family=font_name, size=12)
333
+ except tk.TclError:
334
+ tkFont.nametofont("TkDefaultFont").configure(family="Helvetica", size=10)
335
+ tkFont.nametofont("TkTextFont").configure(family="Helvetica", size=10)
336
+ tkFont.nametofont("TkHeadingFont").configure(family="Helvetica", size=12)
337
+ else:
338
+ tkFont.nametofont("TkDefaultFont").configure(family=font_name, size=10)
339
+ tkFont.nametofont("TkTextFont").configure(family=font_name, size=10)
340
+ tkFont.nametofont("TkHeadingFont").configure(family=font_name, size=12)
341
+
236
342
  def check_and_download_font():
237
- font_name = "Arial"
343
+ font_name = "Helvetica"
238
344
  font_dir = "fonts"
239
345
  font_path = os.path.join(font_dir, "OpenSans-Regular.ttf")
240
346
 
@@ -257,17 +363,17 @@ def check_and_download_font():
257
363
  tkFont.nametofont("TkTextFont").configure(family=font_name, size=10)
258
364
  tkFont.nametofont("TkHeadingFont").configure(family=font_name, size=12)
259
365
  except tk.TclError:
260
- tkFont.nametofont("TkDefaultFont").configure(family="Arial", size=10)
261
- tkFont.nametofont("TkTextFont").configure(family="Arial", size=10)
262
- tkFont.nametofont("TkHeadingFont").configure(family="Arial", size=12)
366
+ tkFont.nametofont("TkDefaultFont").configure(family="Helvetica", size=10)
367
+ tkFont.nametofont("TkTextFont").configure(family="Helvetica", size=10)
368
+ tkFont.nametofont("TkHeadingFont").configure(family="Helvetica", size=12)
263
369
  else:
264
370
  tkFont.nametofont("TkDefaultFont").configure(family=font_name, size=10)
265
371
  tkFont.nametofont("TkTextFont").configure(family=font_name, size=10)
266
372
  tkFont.nametofont("TkHeadingFont").configure(family=font_name, size=12)
267
373
 
268
- def style_text_boxes(style):
374
+ def style_text_boxes_v1(style):
269
375
  check_and_download_font()
270
- font_style = tkFont.Font(family="Arial", size=10) # Define the Arial font
376
+ font_style = tkFont.Font(family="Helvetica", size=10) # Define the Helvetica font
271
377
  style.configure('TEntry', padding='5 5 5 5', borderwidth=1, relief='solid', fieldbackground='#000000', foreground='#ffffff', font=font_style)
272
378
  style.configure('TCombobox', fieldbackground='#000000', background='#000000', foreground='#ffffff', font=font_style)
273
379
  style.configure('Custom.TButton', padding='10 10 10 10', borderwidth=1, relief='solid', background='#008080', foreground='#ffffff', font=font_style)
@@ -278,6 +384,18 @@ def style_text_boxes(style):
278
384
  style.configure('TCheckbutton', background='#333333', foreground='#ffffff', indicatoron=False, relief='flat', font=font_style)
279
385
  style.map('TCheckbutton', background=[('selected', '#555555'), ('active', '#555555')])
280
386
 
387
+ def style_text_boxes(style):
388
+ font_style = tkFont.Font(family="Helvetica", size=10)
389
+ style.configure('TEntry', padding='5 5 5 5', borderwidth=1, relief='solid', fieldbackground='#333333', foreground='#ffffff', font=font_style)
390
+ style.configure('TCombobox', fieldbackground='#333333', background='#333333', foreground='#ffffff', font=font_style)
391
+ style.configure('Custom.TButton', padding='10 10 10 10', borderwidth=1, relief='solid', background='#008080', foreground='#ffffff', font=font_style)
392
+ style.map('Custom.TButton',
393
+ background=[('active', '#66b2b2'), ('disabled', '#004d4d'), ('!disabled', '#008080')],
394
+ foreground=[('active', '#ffffff'), ('disabled', '#888888')])
395
+ style.configure('Custom.TLabel', padding='5 5 5 5', borderwidth=1, relief='flat', background='#000000', foreground='#ffffff', font=font_style)
396
+ style.configure('TCheckbutton', background='#333333', foreground='#ffffff', indicatoron=False, relief='flat', font=font_style)
397
+ style.map('TCheckbutton', background=[('selected', '#555555'), ('active', '#555555')])
398
+
281
399
 
282
400
 
283
401
  def read_settings_from_csv(csv_file_path):
@@ -337,7 +455,7 @@ class ScrollableFrame(ttk.Frame):
337
455
  canvas.pack(side="left", fill="both", expand=True)
338
456
  scrollbar.pack(side="right", fill="y")
339
457
 
340
- class StdoutRedirector(object):
458
+ class StdoutRedirector_v1(object):
341
459
  def __init__(self, text_widget):
342
460
  self.text_widget = text_widget
343
461
 
@@ -348,6 +466,21 @@ class StdoutRedirector(object):
348
466
  def flush(self):
349
467
  pass
350
468
 
469
+ class StdoutRedirector:
470
+ def __init__(self, text_widget):
471
+ self.text_widget = text_widget
472
+
473
+ def write(self, string):
474
+ try:
475
+ if self.text_widget.winfo_exists():
476
+ self.text_widget.insert(tk.END, string)
477
+ self.text_widget.see(tk.END)
478
+ except tk.TclError:
479
+ pass # Handle or log the error as needed
480
+
481
+ def flush(self):
482
+ pass
483
+
351
484
  def check_mask_gui_settings(vars_dict):
352
485
  settings = {}
353
486
  for key, var in vars_dict.items():
@@ -804,8 +937,6 @@ def generate_fields(variables, scrollable_frame):
804
937
  row += 1
805
938
  return vars_dict
806
939
 
807
-
808
-
809
940
  class TextRedirector(object):
810
941
  def __init__(self, widget, queue):
811
942
  self.widget = widget
@@ -834,7 +965,7 @@ def create_dark_mode(root, style, console_output):
834
965
  style.map('TCombobox', fieldbackground=[('readonly', input_bg)], selectbackground=[('readonly', input_bg)], foreground=[('readonly', dark_text)])
835
966
 
836
967
  if console_output != None:
837
- console_output.config(bg=dark_bg, fg=light_text, insertbackground=light_text) #, font=("Arial", 12)
968
+ console_output.config(bg=dark_bg, fg=light_text, insertbackground=light_text) #, font=("Helvetica", 12)
838
969
  root.configure(bg=dark_bg)
839
970
 
840
971
  def set_dark_style(style):
@@ -1025,4 +1156,4 @@ def run_multiple_simulations_wrapper(settings, q, fig_queue):
1025
1156
  q.put(errorMessage) # Send the error message to the GUI via the queue
1026
1157
  traceback.print_exc()
1027
1158
  finally:
1028
- plt.show = original_show # Restore the original plt.show function
1159
+ plt.show = original_show # Restore the original plt.show function