Unknown  option readonlybackground here is code I want updated to fix this  import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import os
import subprocess
import threading
import concurrent.futures
import queue
import sys

def select_input_folders():
    while True:
        folder = filedialog.askdirectory(title="Select Input Folder (Cancel to finish)")
        if folder:
            if folder not in input_folders:
                input_folders.append(folder)
                input_folders_listbox.insert(tk.END, folder)
            else:
                messagebox.showwarning("Duplicate Folder", f"The folder '{folder}' is already selected.")
        else:
            break

def remove_selected_folders():
    selected_indices = list(input_folders_listbox.curselection())
    selected_indices.reverse()  # Remove from the end to avoid index shifting
    for index in selected_indices:
        folder = input_folders_listbox.get(index)
        input_folders.remove(folder)
        input_folders_listbox.delete(index)

def select_input_videos():
    videos = filedialog.askopenfilenames(title="Select Video Files",
                                        filetypes=[("Video Files", "*.mp4 *.avi *.mov *.mkv *.flv *.wmv")])
    if videos:
        for video in videos:
            if video not in input_videos:
                input_videos.append(video)
                input_videos_listbox.insert(tk.END, video)
            else:
                messagebox.showwarning("Duplicate Video", f"The video '{video}' is already selected.")

def remove_selected_videos():
    selected_indices = list(input_videos_listbox.curselection())
    selected_indices.reverse()  # Remove from the end to avoid index shifting
    for index in selected_indices:
        video = input_videos_listbox.get(index)
        input_videos.remove(video)
        input_videos_listbox.delete(index)

def select_output_folder():
    folder = filedialog.askdirectory(title="Select Output Folder")
    if folder:
        output_folder_var.set(folder)
        output_entry.config(state='normal')
        output_entry.delete(0, tk.END)
        output_entry.insert(0, folder)
        output_entry.config(state='readonly')

def sanitize_name(name):
    """Sanitize the folder or file name to remove or replace problematic characters."""
    return "".join(c if c.isalnum() or c in (' ', '_', '-') else "_" for c in name).replace(" ", "_")

def process_videos_thread():
    """Run the video processing in a separate thread."""
    threading.Thread(target=process_videos, daemon=True).start()

def process_videos():
    output_folder = output_folder_var.get()

    if not input_folders and not input_videos:
        messagebox.showerror("Error", "Please select at least one input folder or video.")
        return
    if not output_folder:
        messagebox.showerror("Error", "Please select an output folder.")
        return

    # Get selected format
    selected_format = format_var.get().lower()
    if selected_format not in ['jpg', 'png']:
        messagebox.showerror("Error", "Please select a valid format (JPG or PNG).")
        return

    # Ensure the output directory exists
    os.makedirs(output_folder, exist_ok=True)

    # Disable the process button and input selection buttons to prevent multiple clicks
    set_buttons_state(tk.DISABLED)

    # Initialize progress bars
    total_tasks = len(input_folders) + len(input_videos)
    total_folders = len(input_folders)
    total_videos = len(input_videos)
    if total_tasks == 0:
        messagebox.showerror("Error", "No tasks to process.")
        set_buttons_state(tk.NORMAL)
        return

    progress_bar.config(maximum=total_tasks)
    progress_bar['value'] = 0
    status_label.config(text="Starting processing...")

    # Queues to receive progress updates
    progress_queue = queue.Queue()

    # Lists to collect errors
    errors = []

    # Define worker functions
    def worker_folder(folder):
        base_name = os.path.basename(os.path.normpath(folder))
        sanitized_base = sanitize_name(base_name)
        unique_output_dir = os.path.join(output_folder, f"{sanitized_base}_{base_name}")
        os.makedirs(unique_output_dir, exist_ok=True)
        try:
            # Run the video2image command with the unique output directory and selected format
            subprocess.run(
                ['video2image', '-i', folder, '-o', unique_output_dir, '-f', selected_format],
                check=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            progress_queue.put(("success", f"Folder: {folder}"))
        except subprocess.CalledProcessError as e:
            error_msg = f"Failed to process folder: {folder}\nError: {e.stderr.decode().strip()}"
            progress_queue.put(("error", error_msg))
        except Exception as ex:
            error_msg = f"An unexpected error occurred while processing folder: {folder}\nError: {ex}"
            progress_queue.put(("error", error_msg))

    def worker_video(video):
        base_name = os.path.basename(video)
        name_without_ext = os.path.splitext(base_name)[0]
        sanitized_name = sanitize_name(name_without_ext)
        unique_output_dir = os.path.join(output_folder, f"{sanitized_name}_{name_without_ext}")
        os.makedirs(unique_output_dir, exist_ok=True)
        try:
            # Run the video2image command with the unique output directory and selected format
            subprocess.run(
                ['video2image', '-i', video, '-o', unique_output_dir, '-f', selected_format],
                check=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            progress_queue.put(("success", f"Video: {video}"))
        except subprocess.CalledProcessError as e:
            error_msg = f"Failed to process video: {video}\nError: {e.stderr.decode().strip()}"
            progress_queue.put(("error", error_msg))
        except Exception as ex:
            error_msg = f"An unexpected error occurred while processing video: {video}\nError: {ex}"
            progress_queue.put(("error", error_msg))

    # Create separate executors for folders and videos
    folder_executor = concurrent.futures.ThreadPoolExecutor(max_workers=4)
    video_executor = concurrent.futures.ThreadPoolExecutor(max_workers=4)

    # Submit folder tasks
    folder_futures = [folder_executor.submit(worker_folder, folder) for folder in input_folders]

    # Submit video tasks
    video_futures = [video_executor.submit(worker_video, video) for video in input_videos]

    total_processed = 0

    # Function to periodically check the queue
    def check_queue():
        nonlocal total_processed
        try:
            while True:
                status, info = progress_queue.get_nowait()
                if status == "success":
                    progress_bar['value'] += 1
                    total_processed += 1
                    status_label.config(text=f"Processed: {info}")
                elif status == "error":
                    errors.append(info)
                    progress_bar['value'] += 1
                    total_processed += 1
                    status_label.config(text=f"Error: {info}")

                if total_processed >= total_tasks:
                    folder_executor.shutdown(wait=False)
                    video_executor.shutdown(wait=False)
                    finalize_processing()
        except queue.Empty:
            pass
        if total_processed < total_tasks:
            root.after(100, check_queue)

    # Start checking the queue
    root.after(100, check_queue)

    def finalize_processing():
        set_buttons_state(tk.NORMAL)
        if errors:
            error_message = "\n\n".join(errors)
            messagebox.showerror("Processing Completed with Errors", error_message)
        else:
            messagebox.showinfo("Success", "All videos and folders have been successfully processed.")
        progress_bar['value'] = 0
        status_label.config(text="Processing completed.")

def set_buttons_state(state):
    process_button.config(state=state)
    select_input_folders_button.config(state=state)
    select_input_videos_button.config(state=state)
    select_output_button.config(state=state)
    remove_folders_button.config(state=state if input_folders else tk.DISABLED)
    remove_videos_button.config(state=state if input_videos else tk.DISABLED)

# Initialize the main window
root = tk.Tk()
root.title("Video to Image Converter")
root.geometry("1000x700")
root.resizable(True, True)  # Allow resizing for better usability

# Egyptian Space Ascension Theme Colors
BACKGROUND_COLOR = "#0b0c10"  # Dark background
FRAME_COLOR = "#1f2833"
BUTTON_COLOR = "#c5c6c7"
TEXT_COLOR = "#66fcf1"
PROGRESS_COLOR = "#45a29e"

root.configure(bg=BACKGROUND_COLOR)

# Initialize the lists to store input folders and videos
input_folders = []
input_videos = []

# Variables to store output folder path and format selection
output_folder_var = tk.StringVar()
format_var = tk.StringVar(value="JPG")  # Default to JPG

# Style configuration
style = ttk.Style(root)
style.theme_use('clam')  # Use 'clam' for better customization

# Customize styles
style.configure("TButton",
                foreground=BACKGROUND_COLOR,
                background=BUTTON_COLOR,
                font=("Helvetica", 10, "bold"),
                borderwidth=1)
style.map("TButton",
          background=[('active', '#45a29e')])

style.configure("TLabel",
                foreground=TEXT_COLOR,
                background=BACKGROUND_COLOR,
                font=("Helvetica", 10))

style.configure("TLabelFrame",
                foreground=TEXT_COLOR,
                background=FRAME_COLOR,
                font=("Helvetica", 12, "bold"),
                labelbackground=FRAME_COLOR)

style.configure("Horizontal.TProgressbar",
                troughcolor=FRAME_COLOR,
                background=PROGRESS_COLOR)

# Frame for Input Folders
input_folders_frame = ttk.LabelFrame(root, text="Input Folders")
input_folders_frame.pack(fill="both", expand=True, padx=20, pady=10)

# Listbox to display selected input folders
input_folders_listbox = tk.Listbox(input_folders_frame, selectmode=tk.MULTIPLE, height=10, 
                                   bg=FRAME_COLOR, fg=TEXT_COLOR, selectbackground=PROGRESS_COLOR, selectforeground=BACKGROUND_COLOR)
input_folders_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0,5), pady=5)

# Scrollbar for the folders listbox
folders_scroll = ttk.Scrollbar(input_folders_frame, orient=tk.VERTICAL, command=input_folders_listbox.yview)
folders_scroll.pack(side=tk.RIGHT, fill=tk.Y)
input_folders_listbox.config(yscrollcommand=folders_scroll.set)

# Frame for Input Folders Buttons
input_folders_button_frame = ttk.Frame(root)
input_folders_button_frame.pack(fill='x', padx=20, pady=(0,10))

# Button to select input folders
select_input_folders_button = ttk.Button(input_folders_button_frame, text="Select Input Folders", command=select_input_folders)
select_input_folders_button.pack(side=tk.LEFT, padx=5, pady=5)

# Button to remove selected input folders
remove_folders_button = ttk.Button(input_folders_button_frame, text="Remove Selected Folders", command=remove_selected_folders, state=tk.DISABLED)
remove_folders_button.pack(side=tk.LEFT, padx=5, pady=5)

# Frame for Input Videos
input_videos_frame = ttk.LabelFrame(root, text="Input Videos")
input_videos_frame.pack(fill="both", expand=True, padx=20, pady=10)

# Listbox to display selected input videos
input_videos_listbox = tk.Listbox(input_videos_frame, selectmode=tk.MULTIPLE, height=10, 
                                  bg=FRAME_COLOR, fg=TEXT_COLOR, selectbackground=PROGRESS_COLOR, selectforeground=BACKGROUND_COLOR)
input_videos_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0,5), pady=5)

# Scrollbar for the videos listbox
videos_scroll = ttk.Scrollbar(input_videos_frame, orient=tk.VERTICAL, command=input_videos_listbox.yview)
videos_scroll.pack(side=tk.RIGHT, fill=tk.Y)
input_videos_listbox.config(yscrollcommand=videos_scroll.set)

# Frame for Input Videos Buttons
input_videos_button_frame = ttk.Frame(root)
input_videos_button_frame.pack(fill='x', padx=20, pady=(0,10))

# Button to select input videos
select_input_videos_button = ttk.Button(input_videos_button_frame, text="Select Input Videos", command=select_input_videos)
select_input_videos_button.pack(side=tk.LEFT, padx=5, pady=5)

# Button to remove selected input videos
remove_videos_button = ttk.Button(input_videos_button_frame, text="Remove Selected Videos", command=remove_selected_videos, state=tk.DISABLED)
remove_videos_button.pack(side=tk.LEFT, padx=5, pady=5)

# Frame for Output Folder
output_frame = ttk.LabelFrame(root, text="Output Folder")
output_frame.pack(fill="both", expand=True, padx=20, pady=10)

# Entry widget to display selected output folder
output_entry = ttk.Entry(output_frame, textvariable=output_folder_var, width=80, state='readonly', 
                         background=FRAME_COLOR, foreground=TEXT_COLOR, readonlybackground=FRAME_COLOR)
output_entry.pack(side=tk.LEFT, padx=(0, 5), expand=True, fill=tk.X)

# Button to select output folder
select_output_button = ttk.Button(output_frame, text="Select Output Folder", command=select_output_folder)
select_output_button.pack(side=tk.LEFT, padx=5, pady=5)

# Frame for Format Selection
format_frame = ttk.LabelFrame(root, text="Select Format")
format_frame.pack(fill="both", expand=True, padx=20, pady=10)

# Dropdown menu for format selection
format_dropdown = ttk.Combobox(format_frame, textvariable=format_var, state="readonly",
                               values=["JPG", "PNG"], width=10, font=("Helvetica", 10))
format_dropdown.pack(padx=10, pady=10)
format_dropdown.current(0)  # Set default to JPG

# Progress Frame
progress_frame = ttk.Frame(root)
progress_frame.pack(fill='x', padx=20, pady=10)

progress_label = ttk.Label(progress_frame, text="Processing Progress:")
progress_label.pack(anchor='w')

progress_bar = ttk.Progressbar(progress_frame, orient='horizontal', length=960,
                               mode='determinate', style="Horizontal.TProgressbar")
progress_bar.pack(pady=5, fill='x')

# Status Label
status_label = ttk.Label(root, text="Ready.", relief='sunken', anchor='w')
status_label.pack(fill='x', padx=20, pady=(0,10), ipady=2)

# Process Button
process_button = ttk.Button(root, text="Process", command=process_videos_thread)
process_button.pack(pady=10, ipadx=10, ipady=5)

def on_input_folders_change(*args):
    """Enable or disable the remove folders button based on folder selection."""
    if input_folders:
        remove_folders_button.config(state=tk.NORMAL)
    else:
        remove_folders_button.config(state=tk.DISABLED)

def on_input_videos_change(*args):
    """Enable or disable the remove videos button based on video selection."""
    if input_videos:
        remove_videos_button.config(state=tk.NORMAL)
    else:
        remove_videos_button.config(state=tk.DISABLED)

# Monitor changes in the input_folders and input_videos lists to update the remove buttons state
def monitor_input_lists():
    """Periodically check if input lists are empty to enable/disable the remove buttons."""
    on_input_folders_change()
    on_input_videos_change()
    root.after(500, monitor_input_lists)

monitor_input_lists()

# Function to apply custom styling for Egyptian Space Ascension Theme
def apply_custom_theme():
    # Set a custom font for all widgets
    default_font = ("Segoe UI", 10)
    root.option_add("*Font", default_font)

    # Configure other style options as needed
    # For more advanced theming, consider using images or additional styling packages
    pass

apply_custom_theme()

# Run the GUI loop
root.mainloop()