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/__init__.py +4 -2
- spacr/annotate_app.py +258 -99
- spacr/annotate_app_v2.py +163 -4
- spacr/classify_app.py +201 -0
- spacr/gui.py +19 -13
- spacr/gui_2.py +106 -36
- spacr/gui_annotate.py +145 -0
- spacr/gui_classify_app.py +22 -8
- spacr/gui_make_masks_app.py +927 -0
- spacr/gui_make_masks_app_v2.py +688 -0
- spacr/gui_mask_app.py +42 -15
- spacr/gui_measure_app.py +46 -21
- spacr/gui_utils.py +161 -30
- spacr/make_masks_app.py +927 -0
- spacr/make_masks_app_v2.py +688 -0
- spacr/mask_app.py +239 -915
- spacr/measure_app.py +246 -0
- spacr/sim_app.py +0 -0
- {spacr-0.1.0.dist-info → spacr-0.1.11.dist-info}/METADATA +5 -1
- {spacr-0.1.0.dist-info → spacr-0.1.11.dist-info}/RECORD +24 -16
- {spacr-0.1.0.dist-info → spacr-0.1.11.dist-info}/entry_points.txt +3 -3
- {spacr-0.1.0.dist-info → spacr-0.1.11.dist-info}/LICENSE +0 -0
- {spacr-0.1.0.dist-info → spacr-0.1.11.dist-info}/WHEEL +0 -0
- {spacr-0.1.0.dist-info → spacr-0.1.11.dist-info}/top_level.txt +0 -0
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
|
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="
|
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")
|
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)
|
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')
|
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)
|
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.
|
216
|
-
root.
|
217
|
-
|
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
|
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="
|
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
|
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.
|
215
|
-
root.
|
216
|
-
|
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
|
-
#
|
46
|
-
root
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
#
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
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 .
|
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:
|
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
|
-
#
|
97
|
-
self.font_style = tkFont.Font(family="
|
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="
|
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 = "
|
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="
|
261
|
-
tkFont.nametofont("TkTextFont").configure(family="
|
262
|
-
tkFont.nametofont("TkHeadingFont").configure(family="
|
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
|
374
|
+
def style_text_boxes_v1(style):
|
269
375
|
check_and_download_font()
|
270
|
-
font_style = tkFont.Font(family="
|
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
|
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=("
|
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
|