Compare commits

...

11 Commits

21 changed files with 900 additions and 389 deletions

BIN
MPENNconfigs/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

16
MPENNconfigs/program.json Normal file
View File

@ -0,0 +1,16 @@
{
"window_width": 800,
"window_height": 1000,
"window_state": "zoomed",
"btn_img_size": [
75,
75
],
"skipable_frames": 30,
"img_format": ".jpg",
"used_threads": 4,
"thread_detection_method": "manual",
"data_mode": "Resize",
"color": "#5f00c7",
"thickness": 4
}

359
MPENNconfigs/theme.json Normal file
View File

@ -0,0 +1,359 @@
{
"CTk": {
"fg_color": [
"#ebebeb",
"#1d1d1d"
]
},
"CTkToplevel": {
"fg_color": [
"gray92",
"#1d1d1d"
]
},
"CTkFrame": {
"corner_radius": 6,
"border_width": 0,
"fg_color": [
"gray86",
"#292929"
],
"top_fg_color": [
"gray81",
"gray20"
],
"border_color": [
"gray65",
"gray28"
]
},
"CTkButton": {
"corner_radius": 6,
"border_width": 0,
"fg_color": [
"#5f00c7",
"#5f00c7"
],
"hover_color": [
"#7d03ff",
"#7d03ff"
],
"border_color": [
"#3E454A",
"#949A9F"
],
"text_color": [
"#f7f7f7",
"#f7f7f7"
],
"text_color_disabled": [
"gray74",
"gray60"
]
},
"CTkLabel": {
"corner_radius": 0,
"fg_color": "transparent",
"text_color": [
"#313131",
"#f7f7f7"
]
},
"CTkEntry": {
"corner_radius": 6,
"border_width": 2,
"fg_color": [
"#cfcfcf",
"#323232"
],
"border_color": [
"#cfcfcf",
"#323232"
],
"text_color": [
"#2a2a2a",
"#f7f7f7"
],
"placeholder_text_color": [
"gray52",
"gray62"
]
},
"CTkCheckBox": {
"corner_radius": 6,
"border_width": 3,
"fg_color": [
"#5f00c7",
"#5f00c7"
],
"border_color": [
"#313131",
"#949A9F"
],
"hover_color": [
"#7d03ff",
"#7d03ff"
],
"checkmark_color": [
"#DCE4EE",
"gray90"
],
"text_color": [
"gray10",
"#DCE4EE"
],
"text_color_disabled": [
"gray60",
"gray45"
]
},
"CTkSwitch": {
"corner_radius": 1000,
"border_width": 3,
"button_length": 0,
"fg_color": [
"#939BA2",
"#4A4D50"
],
"progress_color": [
"#ab5cff",
"#35006f"
],
"button_color": [
"#5f00c7",
"#5f00c7"
],
"button_hover_color": [
"#7d03ff",
"#7d03ff"
],
"text_color": [
"gray10",
"#DCE4EE"
],
"text_color_disabled": [
"gray60",
"gray45"
]
},
"CTkRadioButton": {
"corner_radius": 1000,
"border_width_checked": 6,
"border_width_unchecked": 3,
"fg_color": [
"#5f00c7",
"#5f00c7"
],
"border_color": [
"#313131",
"#3f3f3f"
],
"hover_color": [
"#7d03ff",
"#7d03ff"
],
"text_color": [
"gray10",
"#DCE4EE"
],
"text_color_disabled": [
"gray60",
"gray45"
]
},
"CTkProgressBar": {
"corner_radius": 1000,
"border_width": 0,
"fg_color": [
"#ab5cff",
"#35006f"
],
"progress_color": [
"#5f00c7",
"#5f00c7"
],
"border_color": [
"gray",
"gray"
]
},
"CTkSlider": {
"corner_radius": 1000,
"button_corner_radius": 1000,
"border_width": 6,
"button_length": 0,
"fg_color": [
"#ab5cff",
"#35006f"
],
"progress_color": [
"#5f00c7",
"#5f00c7"
],
"button_color": [
"#5f00c7",
"#5f00c7"
],
"button_hover_color": [
"#7d03ff",
"#7d03ff"
]
},
"CTkOptionMenu": {
"corner_radius": 6,
"fg_color": [
"#ab5cff",
"#35006f"
],
"button_color": [
"#5f00c7",
"#5f00c7"
],
"button_hover_color": [
"#7d03ff",
"#7d03ff"
],
"text_color": [
"#DCE4EE",
"#DCE4EE"
],
"text_color_disabled": [
"gray74",
"gray60"
]
},
"CTkComboBox": {
"corner_radius": 6,
"border_width": 2,
"fg_color": [
"#ab5cff",
"#35006f"
],
"border_color": [
"#5f00c7",
"#5f00c7"
],
"button_color": [
"#5f00c7",
"#5f00c7"
],
"button_hover_color": [
"#7d03ff",
"#7d03ff"
],
"text_color": [
"#f7f7f7",
"#DCE4EE"
],
"text_color_disabled": [
"gray50",
"gray45"
]
},
"CTkScrollbar": {
"corner_radius": 1000,
"border_spacing": 4,
"fg_color": "transparent",
"button_color": [
"#cecece",
"#636363"
],
"button_hover_color": [
"gray40",
"gray53"
]
},
"CTkSegmentedButton": {
"corner_radius": 6,
"border_width": 2,
"fg_color": [
"#ab5cff",
"#35006f"
],
"selected_color": [
"#5f00c7",
"#5f00c7"
],
"selected_hover_color": [
"#7d03ff",
"#7d03ff"
],
"unselected_color": [
"#ab5cff",
"#35006f"
],
"unselected_hover_color": [
"#7d03ff",
"#7d03ff"
],
"text_color": [
"#DCE4EE",
"#DCE4EE"
],
"text_color_disabled": [
"gray74",
"gray60"
]
},
"CTkTextbox": {
"corner_radius": 6,
"border_width": 0,
"fg_color": [
"#dbdbdb",
"#2a2a2a"
],
"border_color": [
"#979DA2",
"#565B5E"
],
"text_color": [
"gray10",
"#DCE4EE"
],
"scrollbar_button_color": [
"gray55",
"gray41"
],
"scrollbar_button_hover_color": [
"gray40",
"gray53"
]
},
"CTkScrollableFrame": {
"label_fg_color": [
"gray78",
"gray23"
]
},
"DropdownMenu": {
"fg_color": [
"gray90",
"gray20"
],
"hover_color": [
"gray75",
"gray28"
],
"text_color": [
"gray10",
"gray90"
]
},
"CTksystem_code.FONT": {
"macOS": {
"family": "SF Display",
"size": 13,
"weight": "normal"
},
"Windows": {
"family": "Roboto",
"size": 13,
"weight": "normal"
},
"Linux": {
"family": "Roboto",
"size": 13,
"weight": "normal"
}
}
}

View File

@ -2,6 +2,11 @@
MPENN is a simple software solution designed to transform the way we process and edit large volumes of images, particularly in applications involving neural networks. This versatile tool combines video-to-picture conversion capabilities with an advanced image editor, enabling users to manage and manipulate images efficiently at scale. Whether you are working on machine learning datasets, enhancing digital media assets, or require a robust tool for bulk image editing, MPENN is the ideal solution for your needs.
## --Support--
Currently only working on Windows!
Linux Support is WIP!
## Features
MPENN provides a comprehensive set of features designed to streamline the process of converting, editing, and managing large sets of images. Here's what you can expect:
@ -20,13 +25,19 @@ With these features, MPENN significantly simplifies the workflow for users who n
Welcome to MPENN, a comprehensive tool designed to streamline massive picture editing tasks for neural networks. Follow these steps to get started with MPENN and begin transforming your videos and images into machine learning-ready datasets.
## 1. Download MPENN
## 1. Downloading and Using MPENN
To start using MPENN, first obtain the software by downloading it from its [Gitea repository](https://gitea.example.com/mpenn/mpenn). Click on the latest release suitable for your operating system to begin the download process.
To begin using MPENN, download the software from its [Gitea repository](https://gitea.fabelous.app/Fabelous/mpenn). You can choose between two options for download:
## 2. Setting Up Your Environment
1. **Source code:** Download the source code and build the application yourself. This option is recommended if you have experience with programming and want to modify or extend MPENN's functionality.
After downloading MPENN, it's recommended to set up a virtual environment (venv) for running the software. This ensures that your Python environment remains clean and organized. Open your terminal or command prompt and navigate to the MPENN directory. Then, run the following commands:
2. **Precompiled binary (.exe):** Download the precompiled binary for your operating system. This will allow you to quickly start using MPENN without needing to build it from source. Please note that, upon executing the .exe, a folder will be created in the directory of the .exe containing some configuration files.
**No environment setup is necessary when using the binary.** You can run the .exe directly after downloading and it will function as intended.
## 2. Dependencies (Applicable for source code only)
If you have chosen to download the source code, we recommend setting up a virtual environment (venv) for running the software. This ensures that your Python environment remains clean and organized. Open your terminal or command prompt and navigate to the MPENN directory. Then, run the following commands:
```bash
# Create a virtual environment named 'mpenn-env'
@ -40,11 +51,12 @@ source mpenn-env/bin/activate
# Install MPENN dependencies
pip install -r requirements.txt
# run main.py to run mpenn
python main.py
```
With these steps, your environment will be prepared for running MPENN using the source code.
## Running MPENN
With your environment set up, you're ready to launch MPENN. Run the `main.py` File to get started:
### 1. Converting Video to Picture Sequence

View File

@ -1,275 +0,0 @@
"""Fabelous CTK Color Picker for customtkinter
----------------------------------------
Based on the original work by Akash Bora (Akascape)
Contributions from Victor Vimbert-Guerlais (helloHackYnow)
Original: https://github.com/Akascape/CTkColorPicker/tree/main
"""
import customtkinter as Ctk
from PIL import Image, ImageTk
import os
import math
class AskColor(Ctk.CTkToplevel):
def __init__(self,
master,
font = None,
width: int = 250,
title: str = "Choose Color",
initial_color: str = None,
text: str = "apply",
corner_radius: int = 16,
slider_border: int = 1,
**button_kwargs):
super().__init__(master, **button_kwargs)
self.selected_color = None
self.title(title)
WIDTH = width if width >= 250 else 250
HEIGHT = WIDTH + 110
self.font = font if font is not None else Ctk.CTkFont(family="kDefaultFont", size=16)
self.image_dimension = self._apply_window_scaling(WIDTH - 100)
self.target_dimension = self._apply_window_scaling(20)
self.initial_color = initial_color
self.maxsize(WIDTH, HEIGHT)
self.minsize(WIDTH, HEIGHT)
self.resizable(width=False, height=False)
self.transient(self.master)
self.lift()
self.after(10)
self.protocol("WM_DELETE_WINDOW", self._on_closing)
self.default_hex_color = "#ffffff"
self.default_rgb = [255, 255, 255]
self.rgb_color = self.default_rgb[:]
self.button_text = text
self.corner_radius = corner_radius
self.slider_border = 10 if slider_border >= 10 else slider_border
self.frame = Ctk.CTkFrame(master=self)
self.frame.grid(sticky="nswe", padx=5, pady=5)
self.fg_color = self.fg_color = self._apply_appearance_mode(Ctk.ThemeManager.theme["CTkFrame"]["fg_color"])
self.canvas = Ctk.CTkCanvas(self.frame, height=self.image_dimension, width=self.image_dimension, highlightthickness=0, bg=self.fg_color)
self.canvas.grid(row=0, column=0, columnspan=2, pady=20)
self.canvas.bind("<B1-Motion>", self.on_mouse_drag)
self.img1 = Image.open('icons/color_wheel.png').resize((self.image_dimension, self.image_dimension), Image.Resampling.LANCZOS)
self.img2 = Image.open('icons/target.png').resize((self.target_dimension, self.target_dimension), Image.Resampling.LANCZOS)
self.wheel = ImageTk.PhotoImage(self.img1)
self.target = ImageTk.PhotoImage(self.img2)
self.canvas.create_image(self.image_dimension/2, self.image_dimension/2, image=self.wheel)
self.set_initial_color(initial_color)
self.brightness_slider_value = Ctk.IntVar()
self.brightness_slider_value.set(255)
self.slider = Ctk.CTkSlider(master=self.frame, height=20, border_width=self.slider_border,
button_length=15, progress_color=self.default_hex_color, from_=0, to=255,
variable=self.brightness_slider_value, number_of_steps=256,
button_corner_radius=self.corner_radius, corner_radius=self.corner_radius,
command=lambda x:self.update_colors())
self.slider.grid(row=1, column=0, columnspan=2, pady=(0, 15), padx=20-self.slider_border)
self.label = Ctk.CTkLabel(master=self.frame, text_color="#000000", height=50, width=75, fg_color=self.default_hex_color,
corner_radius=self.corner_radius, text="")
self.color_entry = Ctk.CTkEntry(master=self.frame, height=50, corner_radius=self.corner_radius, font=self.font, width=100)
self.color_entry.configure(placeholder_text=self.default_hex_color) # Insert the new text
self.button = Ctk.CTkButton(master=self.frame, text=self.button_text, height=50, corner_radius=self.corner_radius,width = 200,
command=self._ok_event, **button_kwargs)
self.label.grid(row=2, column=0, padx=(5, 20), pady=10, sticky="e")
self.color_entry.grid(row=2, column=1, padx=(5, 5), pady=10, sticky="w")
self.button.grid(row=3, column=0, columnspan=3, padx=5, pady=10)
self.after(150, lambda: self.label.focus())
self.grab_set()
def get(self):
# Use the stored selected_color instead of accessing the widget
return self.selected_color
def _ok_event(self, event=None):
input_string = self.color_entry.get()
self.selected_color = self.check_rgb_hex_color(input_string) # Store the selected color
self.grab_release()
self.destroy()
del self.img1
del self.img2
del self.wheel
del self.target
def check_rgb_hex_color(self, input_string):
if not input_string:
return self.default_hex_color
if not input_string.startswith("#"):
input_string = "#" + input_string
hex_color = input_string.lstrip("#")
if len(hex_color) != 6:
return None
try:
int(hex_color, 16)
return input_string
except ValueError:
return None
def _on_closing(self):
self._color = None
self.grab_release()
self.destroy()
del self.img1
del self.img2
del self.wheel
del self.target
def on_mouse_drag(self, event):
x = event.x
y = event.y
self.canvas.delete("all")
self.canvas.create_image(self.image_dimension/2, self.image_dimension/2, image=self.wheel)
d_from_center = math.sqrt(((self.image_dimension/2)-x)**2 + ((self.image_dimension/2)-y)**2)
if d_from_center < self.image_dimension/2:
self.target_x, self.target_y = x, y
else:
self.target_x, self.target_y = self.projection_on_circle(x, y, self.image_dimension/2, self.image_dimension/2, self.image_dimension/2 -1)
self.canvas.create_image(self.target_x, self.target_y, image=self.target)
self.get_target_color()
self.update_colors()
def get_target_color(self):
try:
self.rgb_color = self.img1.getpixel((self.target_x, self.target_y))
r = self.rgb_color[0]
g = self.rgb_color[1]
b = self.rgb_color[2]
self.rgb_color = [r, g, b]
except AttributeError:
self.rgb_color = self.default_rgb
def update_colors(self):
brightness = self.brightness_slider_value.get()
self.get_target_color()
r = int(self.rgb_color[0] * (brightness/255))
g = int(self.rgb_color[1] * (brightness/255))
b = int(self.rgb_color[2] * (brightness/255))
self.rgb_color = [r, g, b]
self.default_hex_color = "#{:02x}{:02x}{:02x}".format(*self.rgb_color)
self.slider.configure(progress_color=self.default_hex_color)
self.label.configure(fg_color=self.default_hex_color)
self.color_entry.delete(0, Ctk.END) # Delete any existing text in the color_entry widget
self.color_entry.configure(placeholder_text=self.default_hex_color) # Insert the new text
def projection_on_circle(self, point_x, point_y, circle_x, circle_y, radius):
angle = math.atan2(point_y - circle_y, point_x - circle_x)
projection_x = circle_x + radius * math.cos(angle)
projection_y = circle_y + radius * math.sin(angle)
return projection_x, projection_y
def set_initial_color(self, initial_color):
"""
Sets the initial color of the target if it matches the specified `initial_color`.
Falls back to the center of the image if no matching color is found or `initial_color` is invalid.
Parameters:
- initial_color (str): The hexadecimal color value (e.g., '#RRGGBB') to match in the image.
Note: This method is in beta stage and may not accurately handle all colors.
"""
if not initial_color or not initial_color.startswith("#"):
self._place_image_at_center()
return
r, g, b = self._hex_to_rgb(initial_color)
for i in range(self.image_dimension):
for j in range(self.image_dimension):
if self._pixel_matches_color(i, j, (r, g, b)):
self._place_image_at(i, j)
return
self._place_image_at_center()
def _hex_to_rgb(self, hex_color):
"""
Converts a hexadecimal color to an RGB tuple.
Parameters:
- hex_color (str): The hexadecimal color string (e.g., '#RRGGBB').
Returns:
(tuple): A tuple containing the RGB values (r, g, b).
"""
try:
return tuple(int(hex_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))
except ValueError:
return None
def _pixel_matches_color(self, x, y, color):
"""
Checks if the pixel at (x, y) matches the specified `color`.
Parameters:
- x (int): The x-coordinate of the pixel.
- y (int): The y-coordinate of the pixel.
- color (tuple): The RGB tuple to match.
Returns:
(bool): True if the pixel matches the `color`; False otherwise.
"""
try:
return self.img1.getpixel((x, y))[:3] == color
except IndexError:
# Outside the image bounds
return False
def _place_image_at(self, x, y):
"""
Places the image at the specified (x, y) coordinates.
Parameters:
- x (int): The x-coordinate where the image should be placed.
- y (int): The y-coordinate where the image should be placed.
"""
self.default_hex_color = self.initial_color
self.canvas.create_image(x, y, image=self.target)
self.target_x = x
self.target_y = y
def _place_image_at_center(self):
"""
Places the image at the center of the canvas.
"""
center = self.image_dimension // 2
self.canvas.create_image(center, center, image=self.target)
if __name__ == "__main__":
app = AskColor(master=None, font=None)
app.wait_window(app) # This waits until the window is closed
color = app.get() # Access the color stored before the window was destroyed
print("Selected color:", color)

View File

@ -339,7 +339,7 @@
"gray90"
]
},
"CTkFont": {
"CTksystem_code.FONT": {
"macOS": {
"family": "SF Display",
"size": 13,

BIN
data/mpenn_font.TTF Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

26
main.py
View File

@ -1,4 +1,5 @@
import customtkinter as Ctk
import platform
from icons.icons import Icons
import scripts.get_sys_info as system_code
@ -12,22 +13,21 @@ from scripts.folder_mangement.OpenFolder import OpenFolder
from scripts.folder_mangement.CreateFolder import CreateFolder
from scripts.folder_mangement.SwitchFolder import SwitchFolder
SELECTION_TEXT = "Select your Directory and your Export Directory"
class App(Ctk.CTk):
def __init__(self):
super().__init__()
self.icons = Icons()
system_code.load_json_file()
Ctk.FontManager.load_font("/mpenn_font.TTF")
self.icons = Icons(path=system_code.data_path)
system_code.set_theme()
self.my_font = Ctk.CTkFont(family="Berlin Sans FB", size=22)
self.font_entry = Ctk.CTkFont(family="Berlin Sans FB", size=18)
self.minsize(1000, 750)
self.geometry(f"{system_code.window_width}x{system_code.window_height}")
icon_path = self.icons.get_icon_path()
self.iconbitmap(icon_path)
self.after(1, self.wm_state, system_code.window_state)
if platform.system() == "Windows":
icon_path = self.icons.get_icon_path()
self.iconbitmap(icon_path)
self.after(1, self.wm_state, system_code.window_state)
self.back_btn_image = self.icons.get_image("BackButton")
self.title("MPENN")
self.protocol('WM_DELETE_WINDOW', self.close_attempt)
@ -45,10 +45,10 @@ class App(Ctk.CTk):
self.window_informaton_save = ()
# Top Menu
# Widgets
self.settings_btn = Ctk.CTkButton(self, text="Settings", width=100, command=self.open_settings, font=self.my_font)
image = Ctk.CTkImage(self.back_btn_image, size=(50, 50))
self.back_btn = Ctk.CTkButton(self, text="", image=image,width=50, command=self.go_back, font=self.my_font)
self.window_information = Ctk.CTkLabel(self, text="Choose if you want to convert or label DATA", width=100, font=self.my_font)
self.settings_btn = Ctk.CTkButton(self, text="Settings", width=100, command=self.open_settings, font=(system_code.MPENN_FONT, 22))
image = Ctk.CTkImage(self.back_btn_image, size=(40, 40))
self.back_btn = Ctk.CTkButton(self, text="", font=(system_code.MPENN_FONT, 22), image=image,width=50, command=self.go_back)
self.window_information = Ctk.CTkLabel(self, text="Choose if you want to convert or label DATA", width=100, font=(system_code.MPENN_FONT, 26))
# Alignment
self.place_top_menu()
@ -61,8 +61,8 @@ class App(Ctk.CTk):
self.buttons_frame = Ctk.CTkFrame(self)
self.active_frame = self.buttons_frame
# Main Menu
self.convert_btn = Ctk.CTkButton(self.buttons_frame, text="Convert Videos\ninto IMG-Sequences", command=self.open_converter, width=64, font=self.my_font)
self.label_btn = Ctk.CTkButton(self.buttons_frame, text="Label and\n manage Images", command=self.open_current_labeling_ui, width=64,font=self.my_font)
self.convert_btn = Ctk.CTkButton(self.buttons_frame, text="Convert Videos\ninto IMG-Sequences", command=self.open_converter, width=64, font=(system_code.MPENN_FONT, 22))
self.label_btn = Ctk.CTkButton(self.buttons_frame, text="Label and\n manage Images", command=self.open_current_labeling_ui, width=64,font=(system_code.MPENN_FONT, 22))
# Main Menu
self.active_frame.place(
relx=0.5, rely=0.52,relwidth=0.95, relheight=0.85, anchor="center"

6
requirements.txt Normal file
View File

@ -0,0 +1,6 @@
python3-pil.imagetk
opencv-python
python3-tk
customtkinter
CTkMenubar
pillow

View File

@ -1,22 +1,26 @@
import customtkinter as Ctk
import scripts.get_sys_info as system_code
import platform
from icons.icons import Icons
class ClosePopup(Ctk.CTkToplevel):
def __init__(self,master, callback, **kwargs, ):
super().__init__(master, **kwargs)
self.icons = Icons()
self.my_font = Ctk.CTkFont(family="Berlin Sans FB", size=22)
system_code.load_json_file()
self.icons = Icons(path=system_code.data_path)
self.geometry("400x300")
self.resizable(False, False)
icon_path = self.icons.get_icon_path()
self.iconbitmap(icon_path)
self.after(201, lambda: self.iconbitmap(icon_path))
if platform.system() == "Windows":
icon_path = self.icons.get_icon_path()
self.iconbitmap(icon_path)
self.after(201, lambda: self.iconbitmap(icon_path))
self.callback = callback
self.label = Ctk.CTkLabel(self, text="Do you want to leave?\n You might lose some Data", font=self.my_font)
self.label = Ctk.CTkLabel(self, text="Do you want to leave?\n You might lose some Data", font=(system_code.MPENN_FONT, 22))
# Add exit button
self.exit_button = Ctk.CTkButton(self, text="Exit",fg_color="#bd202d",hover_color="#f24150", command=self.confirm_exit, font=self.my_font)
self.exit_button = Ctk.CTkButton(self, text="Exit",fg_color="#bd202d",hover_color="#f24150", command=self.confirm_exit, font=(system_code.MPENN_FONT, 22))
# Add leave button
self.leave_button = Ctk.CTkButton(self, text="Stay", command=self.destroy, font=self.my_font)
self.leave_button = Ctk.CTkButton(self, text="Stay", command=self.destroy, font=(system_code.MPENN_FONT, 22))
self.grab_set()
#aligning
self.align()

View File

@ -9,6 +9,7 @@ Original: https://github.com/Akascape/CTkColorPicker/tree/main
import customtkinter as Ctk
from PIL import Image, ImageTk
from icons.icons import Icons
import scripts.get_sys_info as system_code
import math
@ -25,7 +26,8 @@ class AskColor(Ctk.CTkToplevel):
slider_border: int = 1,
**button_kwargs):
super().__init__(master, **button_kwargs)
self.icons = Icons()
system_code.load_json_file()
self.icons = Icons(path=system_code.data_path)
self.selected_color = None
self.title(title)
WIDTH = width if width >= 250 else 250

View File

@ -72,8 +72,6 @@ class Converter(Ctk.CTkFrame):
#system_code.load_json_file()
self.thread_count = system_code.used_threads
self.continue_offset = 0
self.my_font = Ctk.CTkFont(family="Berlin Sans FB", size=22)
self.font_entry = Ctk.CTkFont(family="Berlin Sans FB", size=18)
stop_btn_txt = ("Stop Convert", "Continue")
self.test_var = 0
self.input_path = None
@ -83,19 +81,19 @@ class Converter(Ctk.CTkFrame):
self.step_size = None
# the layout
# input layout
self.input_entry = Ctk.CTkEntry(self, placeholder_text="input path", width=350, font=self.my_font)
self.input_btn = Ctk.CTkButton(self, text="Browse Input", width=100, command=self.get_video_path, font=self.my_font)
self.input_entry = Ctk.CTkEntry(self, placeholder_text="input path", width=350, font=(system_code.MPENN_FONT, 22))
self.input_btn = Ctk.CTkButton(self, text="Browse Input", width=100, command=self.get_video_path, font=(system_code.MPENN_FONT, 22))
# output layout
self.output_entry = Ctk.CTkEntry(self, placeholder_text="output path", width=350, font=self.my_font)
self.output_btn = Ctk.CTkButton(self, text="Browse Output", width=100, command=self.get_folder_path, font=self.my_font)
self.output_entry = Ctk.CTkEntry(self, placeholder_text="output path", width=350, font=(system_code.MPENN_FONT, 22))
self.output_btn = Ctk.CTkButton(self, text="Browse Output", width=100, command=self.get_folder_path, font=(system_code.MPENN_FONT, 22))
# button row + img name selection
self.img_naming = Ctk.CTkEntry(self, placeholder_text="Img_seq", width=150, font=self.my_font)
self.img_naming = Ctk.CTkEntry(self, placeholder_text="Img_seq", width=150, font=(system_code.MPENN_FONT, 22))
# start Button
self.start_btn = Ctk.CTkButton(self, text="Start Convert", width=100, command=self.start_threads, font=self.my_font)
self.start_btn = Ctk.CTkButton(self, text="Start Convert", width=100, command=self.start_threads, font=(system_code.MPENN_FONT, 22))
# stop Button
self.stop_btn = Ctk.CTkButton(self, text=stop_btn_txt[0], width=50, command=self.stop_continue_threads, font=self.my_font)
self.stop_btn = Ctk.CTkButton(self, text=stop_btn_txt[0], width=50, command=self.stop_continue_threads, font=(system_code.MPENN_FONT, 22))
self.stop_btn.configure(text='Stop', state=Ctk.DISABLED)
self.show_progress()
self.progress_bar.set(0)
@ -153,7 +151,7 @@ class Converter(Ctk.CTkFrame):
# progressbar
self.progress_bar = Ctk.CTkProgressBar(self,orientation="horizontal", width=500, height=30)
# progressinfo
self.progress_info = Ctk.CTkLabel(self, text="", width=1, font=self.my_font)
self.progress_info = Ctk.CTkLabel(self, text="", width=1, font=(system_code.MPENN_FONT, 22))
# button row
self.progress_bar.place(
relx=0.5,

View File

@ -10,10 +10,9 @@ import scripts.get_sys_info as system_code
class Labeling(Ctk.CTkFrame):
def __init__(self,master,img_paths, output_path, callback, window_information, **kwargs):
super().__init__(master, **kwargs)
self.icons = Icons()
system_code.load_json_file()
self.icons = Icons(path=system_code.data_path)
self.data_saver = SaveData()
self.my_font = Ctk.CTkFont(family="Berlin Sans FB", size=22)
self.image_btn_size = system_code.btn_img_size
#callback
self.callback = callback
@ -56,7 +55,6 @@ class Labeling(Ctk.CTkFrame):
s: Switch Folder
Return: Save Image
"""
print("gettriggered")
self.master.bind("<r>", self.delete_current_rectangle, add="+")
self.master.bind("<j>", self.skip_time, add="+")
self.master.bind("<l>", self.set_data_mode_binding, add="+")
@ -134,18 +132,18 @@ class Labeling(Ctk.CTkFrame):
def create_labeling(self):
"""adapt button size to window_size"""
self.big_canvas = Ctk.CTkCanvas(self,background="#5f00c7", bd=0, highlightthickness=0)
self.reset_btn = Ctk.CTkButton(self, text="reset Image", width=100, command=self.reset_image, font=self.my_font)
self.create_folder_btn = Ctk.CTkButton(self,image=self.create_folder_image, text="", width=100, command=self.create_new_folder, font=self.my_font)
self.open_folder_btn = Ctk.CTkButton(self, image=self.open_folder_image,text="", width=100, command=self.open_new_folder, font=self.my_font)
self.save_img_btn = Ctk.CTkButton(self, text="Save Image", width=100, command=self.save_and_load, font=self.my_font)
self.delete_img_btn = Ctk.CTkButton(self, text="Delete Image", width=100, command=self.delete_img, font=self.my_font)
self.skip_time_btn = Ctk.CTkButton(self, text="Jump", width=100, command=self.skip_time, font=self.my_font)
self.new_source_btn = Ctk.CTkButton(self,image=self.source_folder_image, text="", width=100, command=self.source_folder_dialog, font=self.my_font)
self.reset_btn = Ctk.CTkButton(self, text="reset Image", width=100, command=self.reset_image, font=(system_code.MPENN_FONT, 22))
self.create_folder_btn = Ctk.CTkButton(self,image=self.create_folder_image, text="", width=100, command=self.create_new_folder, font=(system_code.MPENN_FONT, 22))
self.open_folder_btn = Ctk.CTkButton(self, image=self.open_folder_image,text="", width=100, command=self.open_new_folder, font=(system_code.MPENN_FONT, 22))
self.save_img_btn = Ctk.CTkButton(self, text="Save Image", width=100, command=self.save_and_load, font=(system_code.MPENN_FONT, 22))
self.delete_img_btn = Ctk.CTkButton(self, text="Delete Image", width=100, command=self.delete_img, font=(system_code.MPENN_FONT, 22))
self.skip_time_btn = Ctk.CTkButton(self, text="Jump", width=100, command=self.skip_time, font=(system_code.MPENN_FONT, 22))
self.new_source_btn = Ctk.CTkButton(self,image=self.source_folder_image, text="", width=100, command=self.source_folder_dialog, font=(system_code.MPENN_FONT, 22))
self.preview_canvas = Ctk.CTkCanvas(self,background="#5f00c7", bd=0, highlightthickness=0)
self.start_mode = Ctk.StringVar(value=system_code.data_mode)
self.choose_mode = Ctk.CTkSegmentedButton(self, values= system_code.data_modes,
variable=self.start_mode,
command=self.set_data_mode,width=64,font=self.my_font)
command=self.set_data_mode,width=64,font=(system_code.MPENN_FONT, 22))
# big_canvas
self.big_canvas.bind("<ButtonPress-1>", self.on_press)
@ -169,7 +167,6 @@ class Labeling(Ctk.CTkFrame):
self.data_mode_index = 1 - self.data_mode_index
system_code.data_mode = system_code.data_modes[self.data_mode_index]
self.choose_mode.set(system_code.data_mode)
print("also triggered")
def reset_image(self):
self.reset_canvas()

View File

@ -3,14 +3,13 @@ import os
import scripts.get_sys_info as system_code
from ..SaveData import SaveData
FONT = "Berlin Sans FB"
FONT = system_code.MPENN_FONT
class CreateFolder(Ctk.CTkFrame):
def __init__(self,master, output_path,callback, **kwargs):
super().__init__(master, **kwargs)
system_code.load_json_file()
self.data_saver = SaveData()
self.my_font = Ctk.CTkFont(family=FONT, size=22)
self.output_path = output_path
self.callback = callback
self.error_txt = ""
@ -29,10 +28,10 @@ class CreateFolder(Ctk.CTkFrame):
self.create_new_data_folder()
def create_folder(self):
self.create_folder_label = Ctk.CTkLabel(self, text="Type name for new Object:", width=100, font=self.my_font)
self.create_folder_entry = Ctk.CTkEntry(self, placeholder_text="New Data Object", width=100, font=self.my_font)
self.create_folder_name_btn = Ctk.CTkButton(self, text="Create", width=100, command=self.create_new_data_folder, font=self.my_font)
self.create_folder_error = Ctk.CTkLabel(self, text=self.error_txt, width=100, font=self.my_font)
self.create_folder_label = Ctk.CTkLabel(self, text="Type name for new Object:", width=100, font=(system_code.MPENN_FONT, 22))
self.create_folder_entry = Ctk.CTkEntry(self, placeholder_text="New Data Object", width=100, font=(system_code.MPENN_FONT, 22))
self.create_folder_name_btn = Ctk.CTkButton(self, text="Create", width=100, command=self.create_new_data_folder, font=(system_code.MPENN_FONT, 22))
self.create_folder_error = Ctk.CTkLabel(self, text=self.error_txt, width=100, font=(system_code.MPENN_FONT, 22))
self.place_create_folder()
def create_new_data_folder(self):

View File

@ -5,21 +5,18 @@ from ..SaveData import SaveData
import scripts.get_sys_info as system_code
FONT = "Berlin Sans FB"
class OpenFolder(Ctk.CTkScrollableFrame):
def __init__(self,master,output_path, callback, **kwargs, ):
super().__init__(master, **kwargs)
self.icons = Icons()
self.my_font = Ctk.CTkFont(family=FONT, size=16)
self.warning_font = Ctk.CTkFont(family=FONT, size=20)
# the variables needed to get from the upper class
system_code.load_json_file()
self.icons = Icons(path=system_code.data_path)
self.data_saver = SaveData()
self.button_image = Ctk.CTkImage(self.icons.get_image("Folder"), size=(63, 63))
self.output_path = output_path
self.callback = callback # Store the callback function
system_code.load_json_file()
self.data_saver = SaveData()
self.folders = self.get_all_folders()
self.button_size = (50, 50) # Size width and height
self.padding = 10 # Padding around each button
@ -91,7 +88,7 @@ class OpenFolder(Ctk.CTkScrollableFrame):
image=self.button_image, # Corrected: Use self.button_image for the image parameter
compound="top", # Position text below the image
command=lambda val=value: self.new_folder_chosen(val),
font=self.my_font
font=(system_code.MPENN_FONT, 22)
)
folder_btn.grid_remove()
self.buttons.append(folder_btn)

View File

@ -5,14 +5,13 @@ from ..SaveData import SaveData
from tkinter import filedialog
FONT = "Berlin Sans FB"
class SwitchFolder(Ctk.CTkFrame):
def __init__(self,master, callback, **kwargs):
super().__init__(master, **kwargs)
system_code.load_json_file()
self.data_saver = SaveData()
self.my_font = Ctk.CTkFont(family=FONT, size=22)
self.callback = callback
self.error_txt = ""
self.input_path = None
@ -31,14 +30,14 @@ class SwitchFolder(Ctk.CTkFrame):
# the selection part
def create_selection(self):
# input
self.input_entry = Ctk.CTkEntry(self, placeholder_text="Input folder path", width=100, font=self.my_font)
self.input_btn = Ctk.CTkButton(self, text="Browse", width=100, command=self.get_folder_path, font=self.my_font)
self.input_entry = Ctk.CTkEntry(self, placeholder_text="Input folder path", width=100, font=(system_code.MPENN_FONT, 22))
self.input_btn = Ctk.CTkButton(self, text="Browse", width=100, command=self.get_folder_path, font=(system_code.MPENN_FONT, 22))
# output
self.output_entry = Ctk.CTkEntry(self, placeholder_text="Output folder path", width=100, font=self.my_font)
self.output_btn = Ctk.CTkButton(self, text="Browse", width=100, command=self.get_project_path, font=self.my_font)
self.output_entry = Ctk.CTkEntry(self, placeholder_text="Output folder path", width=100, font=(system_code.MPENN_FONT, 22))
self.output_btn = Ctk.CTkButton(self, text="Browse", width=100, command=self.get_project_path, font=(system_code.MPENN_FONT, 22))
# start
self.start_btn = Ctk.CTkButton(self, text="Start", width=100, command=self.open_labeling, font=self.my_font)
self.error_label = Ctk.CTkLabel(self, text=self.error_txt, width=100, font=self.my_font)
self.start_btn = Ctk.CTkButton(self, text="Start", width=100, command=self.open_labeling, font=(system_code.MPENN_FONT, 22))
self.error_label = Ctk.CTkLabel(self, text=self.error_txt, width=100, font=(system_code.MPENN_FONT, 22))
self.place_label_selection()
def open_labeling(self, value = None):

View File

@ -2,24 +2,30 @@ import os
import re
import customtkinter
import json
from scripts.theme import Theme
json_file_path = "./data/program.json"
window_width = None
window_height = None
window_state = None
btn_img_size = None
skipable_frames = None
img_format = None
img_format_options = (".gif", ".jpg", ".png", ".tif")
data_modes = ("Resize", "Labeling")
thread_switcher = ("automatic", "manual")
used_threads = None
thread_detection_mode = None
thread_options = []
data = {}
data_mode = None
color = None
thickness = None
def create_folder(folder_name):
"""
Creates a folder in the current directory with the specified folder name.
Parameters:
folder_name (str): The name of the folder to create.
Returns:
None
"""
try:
# Construct the path where to create the new folder
new_folder_path = os.path.join(os.getcwd(), folder_name)
# Create the folder
os.makedirs(new_folder_path, exist_ok=True)
except Exception as e:
print(f"An error occurred while creating the folder: {e}")
return new_folder_path
def load_json_file():
global data, window_width, window_height, window_state, skipable_frames ,img_format, used_threads, thread_detection_mode, thread_options, btn_img_size, data_mode, color, thickness
@ -143,8 +149,30 @@ def save_img_btn_size(btn_size):
def set_theme():
# Get the current working directory
current_dir = os.getcwd()
# Create the path to the Json file
theme_path = os.path.join(current_dir, 'data', 'MPENN_theme.json')
customtkinter.set_appearance_mode("System") # Modes: system (default), light, dark
customtkinter.set_default_color_theme(theme_path)
customtkinter.set_default_color_theme(theme.get_theme())
MPENN_FONT = "Berlin Sans FB"
data_path = create_folder("MPENNconfigs")
json_file_path = data_path + "/program.json"
theme = Theme(path=data_path)
window_width = None
window_height = None
window_state = None
btn_img_size = None
skipable_frames = None
img_format = None
img_format_options = (".gif", ".jpg", ".png", ".tif")
data_modes = ("Resize", "Labeling")
thread_switcher = ("automatic", "manual")
used_threads = None
thread_detection_mode = None
thread_options = []
data = {}
data_mode = None
color = None
thickness = None

View File

@ -6,41 +6,40 @@ class Settings(Ctk.CTkFrame):
def __init__(self,master, **kwargs):
super().__init__(master, **kwargs)
system_code.load_json_file()
self.my_font = Ctk.CTkFont(family="Berlin Sans FB", size=22)
self.color_information = Ctk.CTkLabel(self, text="Bounding Box Color: ", width=100, font=self.my_font)
self.color_btn = Ctk.CTkButton(self, text="Set Color",fg_color=system_code.color, width=100, command=self.ask_color, font=self.my_font)
self.color_information = Ctk.CTkLabel(self, text="Bounding Box Color: ", width=100, font=(system_code.MPENN_FONT, 22))
self.color_btn = Ctk.CTkButton(self, text="Set Color",fg_color=system_code.color, width=100, command=self.ask_color, font=(system_code.MPENN_FONT, 22))
# set the time for skiping frames
self.thickness_label = Ctk.CTkLabel(self, text="Bounding Box Thickness:", width=100, font=self.my_font)
self.thickness_label = Ctk.CTkLabel(self, text="Bounding Box Thickness:", width=100, font=(system_code.MPENN_FONT, 22))
self.thickness_slider = Ctk.CTkSlider(self, from_=1, to=100, command=self.change_thickness)
self.thickness_slider_value = Ctk.CTkLabel(self, text=system_code.thickness, width=100, font=self.my_font)
self.thickness_slider_value = Ctk.CTkLabel(self, text=system_code.thickness, width=100, font=(system_code.MPENN_FONT, 22))
self.thickness_slider.set(system_code.thickness)
# set the time for skiping frames
self.skip_label = Ctk.CTkLabel(self, text="Skipable Frames:", width=100, font=self.my_font)
self.skip_label = Ctk.CTkLabel(self, text="Skipable Frames:", width=100, font=(system_code.MPENN_FONT, 22))
self.skip_slider = Ctk.CTkSlider(self, from_=2, to=100, command=self.change_skipped_frame)
self.skip_slider_value = Ctk.CTkLabel(self, text=system_code.skipable_frames, width=100, font=self.my_font)
self.skip_slider_value = Ctk.CTkLabel(self, text=system_code.skipable_frames, width=100, font=(system_code.MPENN_FONT, 22))
self.skip_slider.set(system_code.skipable_frames)
# set the outputs
self.label_output_formats = Ctk.CTkLabel(self, text="Output formats:", width=256, font=self.my_font)
self.label_output_formats = Ctk.CTkLabel(self, text="Output formats:", width=256, font=(system_code.MPENN_FONT, 22))
self.change_output_format = Ctk.StringVar(value=system_code.img_format)
self.output_formats = Ctk.CTkSegmentedButton(self, values= system_code.img_format_options,
command=self.set_img_format,
variable=self.change_output_format,width=64,font=self.my_font)
variable=self.change_output_format,width=64,font=(system_code.MPENN_FONT, 22))
# set the threads
self.label_threads = Ctk.CTkLabel(self, text="Threads: ", width=196, font=self.my_font)
self.label_threads = Ctk.CTkLabel(self, text="Threads: ", width=196, font=(system_code.MPENN_FONT, 22))
self.thread_switcher = Ctk.StringVar(value=system_code.thread_detection_mode)
self.thread_switch = Ctk.CTkSegmentedButton(self, values=system_code.thread_switcher,
command=self.change_thread_type,
variable=self.thread_switcher,
width=64,font=self.my_font)
width=64,font=(system_code.MPENN_FONT, 22))
self.used_threads = Ctk.StringVar(value=system_code.used_threads)
self.thread_count_switch = Ctk.CTkSegmentedButton(self, values=system_code.thread_options,
command=self.change_manual_threads,
width=256,font=self.my_font)
width=256,font=(system_code.MPENN_FONT, 22))
if system_code.thread_detection_mode == "manual":
self.show_thread_selection()
@ -69,7 +68,7 @@ class Settings(Ctk.CTkFrame):
self.thickness_slider_value.configure(text=value)
def ask_color(self):
self.pick_color = AskColor(master=self.master, font=self.my_font)
self.pick_color = AskColor(master=self.master, font=(system_code.MPENN_FONT, 22))
self.wait_window(self.pick_color)
self.color = self.pick_color.get() # get the color string

369
scripts/theme.py Normal file
View File

@ -0,0 +1,369 @@
import json
class Theme:
def __init__(self, path) -> None:
self.path = path
self.theme_json = {
"CTk": {
"fg_color": [
"#ebebeb",
"#1d1d1d"
]
},
"CTkToplevel": {
"fg_color": [
"gray92",
"#1d1d1d"
]
},
"CTkFrame": {
"corner_radius": 6,
"border_width": 0,
"fg_color": [
"gray86",
"#292929"
],
"top_fg_color": [
"gray81",
"gray20"
],
"border_color": [
"gray65",
"gray28"
]
},
"CTkButton": {
"corner_radius": 6,
"border_width": 0,
"fg_color": [
"#5f00c7",
"#5f00c7"
],
"hover_color": [
"#7d03ff",
"#7d03ff"
],
"border_color": [
"#3E454A",
"#949A9F"
],
"text_color": [
"#f7f7f7",
"#f7f7f7"
],
"text_color_disabled": [
"gray74",
"gray60"
]
},
"CTkLabel": {
"corner_radius": 0,
"fg_color": "transparent",
"text_color": [
"#313131",
"#f7f7f7"
]
},
"CTkEntry": {
"corner_radius": 6,
"border_width": 2,
"fg_color": [
"#cfcfcf",
"#323232"
],
"border_color": [
"#cfcfcf",
"#323232"
],
"text_color": [
"#2a2a2a",
"#f7f7f7"
],
"placeholder_text_color": [
"gray52",
"gray62"
]
},
"CTkCheckBox": {
"corner_radius": 6,
"border_width": 3,
"fg_color": [
"#5f00c7",
"#5f00c7"
],
"border_color": [
"#313131",
"#949A9F"
],
"hover_color": [
"#7d03ff",
"#7d03ff"
],
"checkmark_color": [
"#DCE4EE",
"gray90"
],
"text_color": [
"gray10",
"#DCE4EE"
],
"text_color_disabled": [
"gray60",
"gray45"
]
},
"CTkSwitch": {
"corner_radius": 1000,
"border_width": 3,
"button_length": 0,
"fg_color": [
"#939BA2",
"#4A4D50"
],
"progress_color": [
"#ab5cff",
"#35006f"
],
"button_color": [
"#5f00c7",
"#5f00c7"
],
"button_hover_color": [
"#7d03ff",
"#7d03ff"
],
"text_color": [
"gray10",
"#DCE4EE"
],
"text_color_disabled": [
"gray60",
"gray45"
]
},
"CTkRadioButton": {
"corner_radius": 1000,
"border_width_checked": 6,
"border_width_unchecked": 3,
"fg_color": [
"#5f00c7",
"#5f00c7"
],
"border_color": [
"#313131",
"#3f3f3f"
],
"hover_color": [
"#7d03ff",
"#7d03ff"
],
"text_color": [
"gray10",
"#DCE4EE"
],
"text_color_disabled": [
"gray60",
"gray45"
]
},
"CTkProgressBar": {
"corner_radius": 1000,
"border_width": 0,
"fg_color": [
"#ab5cff",
"#35006f"
],
"progress_color": [
"#5f00c7",
"#5f00c7"
],
"border_color": [
"gray",
"gray"
]
},
"CTkSlider": {
"corner_radius": 1000,
"button_corner_radius": 1000,
"border_width": 6,
"button_length": 0,
"fg_color": [
"#ab5cff",
"#35006f"
],
"progress_color": [
"#5f00c7",
"#5f00c7"
],
"button_color": [
"#5f00c7",
"#5f00c7"
],
"button_hover_color": [
"#7d03ff",
"#7d03ff"
]
},
"CTkOptionMenu": {
"corner_radius": 6,
"fg_color": [
"#ab5cff",
"#35006f"
],
"button_color": [
"#5f00c7",
"#5f00c7"
],
"button_hover_color": [
"#7d03ff",
"#7d03ff"
],
"text_color": [
"#DCE4EE",
"#DCE4EE"
],
"text_color_disabled": [
"gray74",
"gray60"
]
},
"CTkComboBox": {
"corner_radius": 6,
"border_width": 2,
"fg_color": [
"#ab5cff",
"#35006f"
],
"border_color": [
"#5f00c7",
"#5f00c7"
],
"button_color": [
"#5f00c7",
"#5f00c7"
],
"button_hover_color": [
"#7d03ff",
"#7d03ff"
],
"text_color": [
"#f7f7f7",
"#DCE4EE"
],
"text_color_disabled": [
"gray50",
"gray45"
]
},
"CTkScrollbar": {
"corner_radius": 1000,
"border_spacing": 4,
"fg_color": "transparent",
"button_color": [
"#cecece",
"#636363"
],
"button_hover_color": [
"gray40",
"gray53"
]
},
"CTkSegmentedButton": {
"corner_radius": 6,
"border_width": 2,
"fg_color": [
"#ab5cff",
"#35006f"
],
"selected_color": [
"#5f00c7",
"#5f00c7"
],
"selected_hover_color": [
"#7d03ff",
"#7d03ff"
],
"unselected_color": [
"#ab5cff",
"#35006f"
],
"unselected_hover_color": [
"#7d03ff",
"#7d03ff"
],
"text_color": [
"#DCE4EE",
"#DCE4EE"
],
"text_color_disabled": [
"gray74",
"gray60"
]
},
"CTkTextbox": {
"corner_radius": 6,
"border_width": 0,
"fg_color": [
"#dbdbdb",
"#2a2a2a"
],
"border_color": [
"#979DA2",
"#565B5E"
],
"text_color": [
"gray10",
"#DCE4EE"
],
"scrollbar_button_color": [
"gray55",
"gray41"
],
"scrollbar_button_hover_color": [
"gray40",
"gray53"
]
},
"CTkScrollableFrame": {
"label_fg_color": [
"gray78",
"gray23"
]
},
"DropdownMenu": {
"fg_color": [
"gray90",
"gray20"
],
"hover_color": [
"gray75",
"gray28"
],
"text_color": [
"gray10",
"gray90"
]
},
"CTksystem_code.FONT": {
"macOS": {
"family": "SF Display",
"size": 13,
"weight": "normal"
},
"Windows": {
"family": "Roboto",
"size": 13,
"weight": "normal"
},
"Linux": {
"family": "Roboto",
"size": 13,
"weight": "normal"
}
}
}
def get_theme(self):
with open(self.path + "/theme.json", "w") as file:
json.dump(self.theme_json, file, indent=4)
return self.path + "/theme.json"

1
tempCodeRunnerFile.py Normal file
View File

@ -0,0 +1 @@
BackButton