Source code for kalmus.tkinter_windows.GenerateBarcodeWindow

""" GenerateBarcodeWindow Class """

import cv2
import tkinter
import tkinter.filedialog
from tkinter.messagebox import showerror, showwarning, showinfo
import copy
import os
import threading

from kalmus.tkinter_windows.meta_info_windows.SpecifyMetaDataWindow import SpecifyMetaDataWindow
from kalmus.tkinter_windows.gui_utils import resource_path


[docs]class GenerateBarcodeWindow(): """ GenerateBarcodeWindow Class GUI window for user to generate the barcode from a video file """ def __init__(self, barcode_generator, barcode_stack): """ Initialize :param barcode_generator: The barcode generator :param barcode_stack: The dictionary that stores all the barcode on the memory """ self.barcode_generator = barcode_generator self.barcode_stack = barcode_stack # Initialize the window self.window = tkinter.Tk() self.window.wm_title("Barcode Generator") self.window.iconbitmap(resource_path("kalmus_icon.ico")) # A temporary meta data dictionary that will hold the meta information given by the user self.meta_data_dict = {} # video object capture by cv2 self.video = None # Label prompt for the generated barcode's barcode type barcode_type_label = tkinter.Label(self.window, text="Barcode Type: ") barcode_type_label.grid(row=0, column=0) # Label prompt for the frame sampling type frame_type_label = tkinter.Label(self.window, text="Frame Type: ") frame_type_label.grid(row=1, column=0) # Label prompt for the color/brightness metric color_metric_label = tkinter.Label(self.window, text="Color Metric: ") color_metric_label.grid(row=2, column=0) # Variable that stores the user's choice of generated barcode type self.barcode_type_var = tkinter.StringVar(self.window) self.barcode_type_var.set("Color") # Dropdown menu for the barcode type selection dropdown_bar_type = tkinter.OptionMenu(self.window, self.barcode_type_var, "Color", "Brightness") dropdown_bar_type.grid(row=0, column=1) # Variable that stores the user's choice of frame sampling type self.frame_type_var = tkinter.StringVar(self.window) self.frame_type_var.set("Whole_frame") # Dropdown menu for the frame sampling type selection dropdown_frame_type = tkinter.OptionMenu(self.window, self.frame_type_var, "Whole_frame", "Low_contrast_region", "High_contrast_region", "Foreground", "Background") dropdown_frame_type.grid(row=1, column=1) # Variable that stores the user's choice of color metric self.color_metric_var = tkinter.StringVar(self.window) self.color_metric_var.set("Average") # Dropdown menu for the color metric selection dropdown_color_metric = tkinter.OptionMenu(self.window, self.color_metric_var, "Average", "Median", "Mode", "Top-dominant", "Weighted-dominant", "Bright", "Brightest") dropdown_color_metric.grid(row=2, column=1) # Label prompt for the skip over specification self.skip_over_label = tkinter.Label(self.window, text="Start at (frames): ") self.skip_over_label.grid(row=0, column=2) # Label prompt for the sample rate specification self.sampled_rate_label = tkinter.Label(self.window, text="Sample every (frames): ") self.sampled_rate_label.grid(row=1, column=2) # Label prompt for the total frame included specification self.total_frames_label = tkinter.Label(self.window, text="Total frames: ") self.total_frames_label.grid(row=2, column=2) # Acquisition unit specification (in frames or in time) self.acquisition_label = tkinter.Label(self.window, text="Acquistion unit") self.acquisition_label.grid(row=0, column=5) # Variable that stores the user's choice of acquisition unit self.acquisition_option = tkinter.StringVar(self.window) self.acquisition_option.set("Frame") # Radio button for the Acquisition unit (Frame/Time) selection self.radio_frame = tkinter.Radiobutton(self.window, text="Frame", variable=self.acquisition_option, value="Frame", anchor='w', command=self.frame_unit) self.radio_frame.grid(row=1, column=5, sticky=tkinter.W) self.radio_frame.select() self.radio_time = tkinter.Radiobutton(self.window, text="Time", variable=self.acquisition_option, value="Time", anchor='w', command=self.time_unit) self.radio_time.grid(row=2, column=5, sticky=tkinter.W) # Text entry for the skip over specification self.skip_over_entry = tkinter.Entry(self.window, textvariable="0", width=12) self.skip_over_entry.grid(row=0, column=3, columnspan=2) # Text entry for the sampling rate specification self.sampled_rate_entry = tkinter.Entry(self.window, textvariable="1", width=12) self.sampled_rate_entry.grid(row=1, column=3, columnspan=2) # Text entry for the total frames specification self.total_frames_entry = tkinter.Entry(self.window, textvariable="1000", width=12) self.total_frames_entry.grid(row=2, column=3, columnspan=2) # Label prompt for the video file name input video_filename_label = tkinter.Label(self.window, text="Media file path: ") video_filename_label.grid(row=3, column=0, columnspan=1) # Text entry for the video file name specification self.video_filename_entry = tkinter.Entry(self.window, textvariable="", width=55) self.video_filename_entry.grid(row=3, column=1, columnspan=3) # Button to browse the folder self.browse_folder_button = tkinter.Button(self.window, text='Browse', command=self.browse_folder) self.browse_folder_button.grid(row=3, column=4) # Variable that stores 0 for not saving JSON file 1 for saving generated barcode to JSON self.var_save_json = tkinter.IntVar(self.window) # Checkbox for the user to choose whether use the multi-thread or not for barcode generation self.checkbox_save_json = tkinter.Checkbutton(self.window, text="Save Output:", variable=self.var_save_json, onvalue=1, offvalue=0, command=self.update_json_filename) self.checkbox_save_json.grid(row=4, column=0) # Text entry for the output JSON file name specification self.json_filename_entry = tkinter.Entry(self.window, textvariable="", width=55) self.json_filename_entry.grid(row=4, column=1, columnspan=3) self.json_filename_entry.config(state="disabled") # Variable that stores the letter box option (automatic/user defined) self.letterbox_option = tkinter.StringVar(self.window) self.letterbox_option.set("Auto") # initialize # Label prompt for the letter box remove option letterbox_label = tkinter.Label(self.window, text="Remove Letterbox: ") letterbox_label.grid(row=5, column=0, columnspan=1) # Radio button for the letter box remove option self.radio_auto = tkinter.Radiobutton(self.window, text="Auto", variable=self.letterbox_option, value="Auto", anchor='w', command=self.disable_setup) self.radio_auto.grid(row=6, column=0, sticky=tkinter.W) self.radio_auto.select() self.radio_manual = tkinter.Radiobutton(self.window, text="Manual", variable=self.letterbox_option, value="Manual", anchor='w', command=self.enable_setup) self.radio_manual.grid(row=7, column=0, sticky=tkinter.W) # User defined letter box label prompt high_ver_label = tkinter.Label(self.window, text="Upper vertical: ") high_ver_label.grid(row=6, column=1, columnspan=1) low_ver_label = tkinter.Label(self.window, text="Lower vertical: ") low_ver_label.grid(row=7, column=1, columnspan=1) # User defined letter box text entry self.high_ver_entry = tkinter.Entry(self.window, textvariable="-1", width=4, state="disabled") self.high_ver_entry.grid(row=6, column=2, columnspan=1, sticky=tkinter.W) self.low_ver_entry = tkinter.Entry(self.window, textvariable="-2", width=4, state="disabled") self.low_ver_entry.grid(row=7, column=2, columnspan=1, sticky=tkinter.W) left_hor_label = tkinter.Label(self.window, text="Left horizontal: ") left_hor_label.grid(row=6, column=3, columnspan=1) right_hor_label = tkinter.Label(self.window, text="right horizontal: ") right_hor_label.grid(row=7, column=3, columnspan=1) self.left_hor_entry = tkinter.Entry(self.window, textvariable="-3", width=4, state="disabled") self.left_hor_entry.grid(row=6, column=4, columnspan=1) self.right_hor_entry = tkinter.Entry(self.window, textvariable="-4", width=4, state="disabled") self.right_hor_entry.grid(row=7, column=4, columnspan=1) # Variable that stores 0 for not saving frames during the generation 1 for saving frames during the generation self.var_saved_frame = tkinter.IntVar(self.window) # Checkbox for the user to choose whether save the frames or not during barcode generation self.checkbox_saved_frame = tkinter.Checkbutton(self.window, text="Save Frames ", variable=self.var_saved_frame, onvalue=1, offvalue=0, command=self.update_save_frame_entry) self.checkbox_saved_frame.grid(row=8, column=0) # Label prompt for saving frame save_frame_label = tkinter.Label(master=self.window, text="Save every (secs):") save_frame_label.grid(row=8, column=1, sticky=tkinter.E) # Text entry for the saved frames rate specification self.save_frame_entry = tkinter.Entry(self.window, textvariable="-8", width=4, state="normal") self.save_frame_entry.grid(row=8, column=2, sticky=tkinter.W) self.save_frame_entry.delete(0, tkinter.END) self.save_frame_entry.insert(0, "4") self.save_frame_entry.config(state="disabled") # Variable that stores 0 for not saving frames during the generation 1 for rescaling frame # during the generation self.var_rescale_frame = tkinter.IntVar(self.window) # Checkbox for the user to choose whether to rescale the frames or not during the barcode generation self.checkbox_rescale_frame = tkinter.Checkbutton(self.window, text="Rescale Frames", width=12, variable=self.var_rescale_frame, onvalue=1, offvalue=0, command=self.update_rescale_entry) self.checkbox_rescale_frame.grid(row=8, column=3, sticky=tkinter.E) # Text entry for the rescale factor specification self.rescale_factor_entry = tkinter.Entry(self.window, textvariable="-7", width=4, state="normal") self.rescale_factor_entry.grid(row=8, column=4) self.rescale_factor_entry.delete(0, tkinter.END) self.rescale_factor_entry.insert(0, "0.5") self.rescale_factor_entry.config(state="disabled") # Variable that stores 0 for single thread generation 1 for multi-thread generation self.var_multi_thread = tkinter.IntVar(self.window) # Checkbox for the user to choose whether use the multi-thread or not for barcode generation self.checkbox_multi_thread = tkinter.Checkbutton(self.window, text="Multi-Thread:", variable=self.var_multi_thread, onvalue=1, offvalue=0, command=self.update_thread_entry) self.checkbox_multi_thread.grid(row=9, column=0) # Text entry for the thread specification self.thread_entry = tkinter.Entry(self.window, textvariable="-6", width=4, state="normal") self.thread_entry.grid(row=9, column=1, sticky=tkinter.W) self.thread_entry.delete(0, tkinter.END) self.thread_entry.insert(0, "4") self.thread_entry.config(state="disabled") # Button to generate the barcode self.generate_button = tkinter.Button(master=self.window, text="Generate Barcode", command=self.generate_barcode_thread) self.generate_button.grid(row=9, column=2, sticky=tkinter.W, rowspan=1, pady=5) # Button to specify the meta data of the generated barcode self.specify_data_button = tkinter.Button(master=self.window, text="Specify Meta Data", command=self.specify_data) self.specify_data_button.grid(row=9, column=3, sticky=tkinter.W, rowspan=1, pady=5) self.use_default_setting_button = tkinter.Button(master=self.window, text="Default Setting", command=self.fill_default_setting) self.use_default_setting_button.grid(row=9, column=4, sticky=tkinter.E, rowspan=1, columnspan=2, pady=5, padx=15) self.window.protocol("WM_DELETE_WINDOW", self.quit) # Start the window self.window.mainloop()
[docs] def quit(self): """ Quit the main window """ self.window.quit() self.window.destroy()
[docs] def specify_data(self): """ Instantiate the SpecifyMetaDataWindow """ SpecifyMetaDataWindow(self.meta_data_dict)
[docs] def update_json_filename(self): if self.var_save_json.get() == 0: self.checkbox_save_json["text"] = "Save Output:" self.json_filename_entry.config(state="disabled") elif self.var_save_json.get() == 1: self.checkbox_save_json["text"] = "JSON file path:" self.json_filename_entry.config(state="normal")
[docs] def fill_default_setting(self): self.barcode_type_var.set("Color") self.frame_type_var.set("Whole_frame") self.color_metric_var.set("Average") self.acquisition_option.set("Frame") self.radio_frame.select() self.radio_time.deselect() self.radio_frame.invoke() self.skip_over_entry.delete(0, tkinter.END) self.skip_over_entry.insert(0, "start") self.sampled_rate_entry.delete(0, tkinter.END) self.sampled_rate_entry.insert(0, "2") self.total_frames_entry.delete(0, tkinter.END) self.total_frames_entry.insert(0, "end") self.letterbox_option.set("Auto") self.radio_auto.select() self.radio_manual.deselect() self.radio_auto.invoke() self.checkbox_saved_frame.deselect() self.checkbox_saved_frame.invoke() self.save_frame_entry.delete(0, tkinter.END) self.save_frame_entry.insert(0, "4") self.checkbox_rescale_frame.select() self.checkbox_rescale_frame.invoke() self.checkbox_save_json.deselect() self.checkbox_save_json.invoke() if len(self.json_filename_entry.get()) <= 0: default_json_save_path = "saved_{:s}_barcode_{:s}_{:s}.json"\ .format(self.barcode_type_var.get(), self.frame_type_var.get(), self.color_metric_var.get()) self.json_filename_entry.delete(0, tkinter.END) self.json_filename_entry.insert(0, os.path.abspath(default_json_save_path))
[docs] def update_thread_entry(self): """ Enable or disable and change the label prompt when user check/uncheck the multi-thread checkbox """ if self.var_multi_thread.get() == 0: self.checkbox_multi_thread["text"] = "Multi-Thread:" self.thread_entry.config(state="disabled") elif self.var_multi_thread.get() == 1: self.checkbox_multi_thread["text"] = "# of Threads:" self.thread_entry.config(state="normal")
[docs] def update_rescale_entry(self): """ Enable or disable and change the label prompt when user check/uncheck the rescale frames checkbox """ if self.var_rescale_frame.get() == 0: self.checkbox_rescale_frame["text"] = "Rescale Frames" self.rescale_factor_entry.config(state="disabled") elif self.var_rescale_frame.get() == 1: self.checkbox_rescale_frame["text"] = "By a factor of: " self.rescale_factor_entry.config(state="normal")
[docs] def update_save_frame_entry(self): """ Enable or disable the text entry when user check/uncheck the save frames checkbox """ if self.var_saved_frame.get() == 0: self.save_frame_entry.config(state="disabled") elif self.var_saved_frame.get() == 1: self.save_frame_entry.config(state="normal")
[docs] def time_unit(self): """ Change the acquisition unit to Time when user switch to the time radio button """ self.skip_over_label['text'] = "Start at (mins:secs): " self.sampled_rate_label['text'] = "Sample every (secs): " self.total_frames_label['text'] = "End at (mins:secs): "
[docs] def frame_unit(self): """ Change the acquisition unit to Frame when user switch to the frame radio button """ self.skip_over_label['text'] = "Start at (frames): " self.sampled_rate_label['text'] = "Sample every (frames): " self.total_frames_label['text'] = "Total frames: "
[docs] def browse_folder(self): """ Browse the folder """ # Get the file name from the user specification filename = tkinter.filedialog.askopenfilename(initialdir="", title="Select Media file", filetypes=(("mp4 files", "*.mp4"), ("avi files", "*.avi"), ("m4v files", "*.m4v"), ("All files", "*.*"))) # Update the file name to the text entry self.video_filename_entry.delete(0, tkinter.END) self.video_filename_entry.insert(0, filename)
[docs] def generate_barcode_thread(self): """ Generate the barcode in a another thread to avoid the frozen tkinter window issue :return: """ threading.Thread(target=self.generate_barcode).start()
[docs] def acquire_generation_param(self): """ Acquire the barcode generation parameters """ # Get barcode type, frame sampling type, and color/brightness metric barcode_type = self.barcode_type_var.get() frame_type = self.frame_type_var.get() color_metric = self.color_metric_var.get() # Get the acquisition unit unit_type = self.acquisition_option.get() # Get the file name/path of the input video video_filename = str(self.video_filename_entry.get()) if not os.path.exists(video_filename): showerror("Video File Not Exists", "Video file not found!\nPlease check the file path.") raise FileNotFoundError() # Get the correct acquisition parameters based on the acqusition unit if unit_type == "Frame": skip_over_str = self.skip_over_entry.get() if len(skip_over_str) == 0 or skip_over_str.lower() == "start": skip_over = 0 else: skip_over = int(self.skip_over_entry.get()) total_frames_str = self.total_frames_entry.get() if len(total_frames_str) == 0 or total_frames_str.lower() == "end": total_frames = int(1e8) else: total_frames = int(self.total_frames_entry.get()) sampled_frame_rate_str = self.sampled_rate_entry.get() if len(sampled_frame_rate_str) == 0: showwarning("Sample Frame not Specified", "Sample frame rate is not given.\n" "Default sample rate 1 frame every input frame is used.") sampled_frame_rate = 1 else: sampled_frame_rate = int(sampled_frame_rate_str) elif unit_type == "Time": self.video = cv2.VideoCapture(video_filename) fps = self.video.get(cv2.CAP_PROP_FPS) skip_over_str = str(self.skip_over_entry.get()) if len(skip_over_str) == 0 or skip_over_str.lower() == "start": skip_over = 0 else: split_pos = skip_over_str.find(":") skip_over = int((int(skip_over_str[:split_pos]) * 60 + int(skip_over_str[split_pos + 1:])) * fps) sampled_frame_rate_str = str(self.sampled_rate_entry.get()) if len(sampled_frame_rate_str) == 0: showwarning("Sample Frame not Specified", "Sample frame rate is not given.\n" "Default sample rate 1 frame every input frame is used.") sampled_frame_rate = 1 else: sampled_frame_rate = int(round(float(sampled_frame_rate_str) * fps)) total_frames_str = str(self.total_frames_entry.get()) if len(total_frames_str) == 0 or total_frames_str.lower() == "end": total_frames = int(1e8) else: split_pos = total_frames_str.find(":") total_frames = (int(total_frames_str[:split_pos]) * 60 + int(total_frames_str[split_pos + 1:])) * fps total_frames -= skip_over total_frames = int(total_frames) total_frames //= sampled_frame_rate # Make sure the sampled frame rate >= 1 and the skip over >= 0 and total frame >= 0 if sampled_frame_rate < 1: showwarning("Frame Sample Rate too Small", "The frame sample rate is too small.\n" "It has been adjusted to the Minimum valid sample rate,\n" "Sample 1 frame every frame (==use all frames)") sampled_frame_rate = 1 if skip_over < 0: showwarning("Invalid Start time", "Invalid start time for the barcode generation.\n" "Start frames/time has been set to 0/00:00 (== start of film)") skip_over = 0 if total_frames < 0: showwarning("Invalid Total Frames", "Invalid total frames\n" "or Barcode starts after it ends.\n" "Total frames has been adjusted to 0.") total_frames = 0 return barcode_type, frame_type, color_metric, sampled_frame_rate, skip_over, total_frames, video_filename
[docs] def generate_barcode(self): """ Generate the barcode using the given parameters """ self.disable_generate_button() try: barcode_type, frame_type, color_metric, sampled_frame_rate, skip_over, total_frames, video_filename = \ self.acquire_generation_param() except FileNotFoundError: self.enable_generate_button() return except: showerror("Acquisition Parameters", "An unknown Error occurred when reading\n" "the acquisition parameters.\n\n" "Please make sure all parameters are positive\n" "Frames units must all be integers\n" "In Time unit, mins:secs in Start and End at must be integers\n" "Sample every (secs) can be decimals but not fraction.") self.enable_generate_button() return # Update all the parameters to the barcode generator self.barcode_generator.barcode_type = barcode_type self.barcode_generator.frame_type = frame_type self.barcode_generator.color_metric = color_metric self.barcode_generator.sampled_frame_rate = sampled_frame_rate self.barcode_generator.skip_over = skip_over self.barcode_generator.total_frames = total_frames if self.var_save_json.get() == 1: json_filename = self.json_filename_entry.get() if len(json_filename) == 0: showwarning("Default Saved JSON Path is Used", "Path to the saved JSON file is not specified.\n" "Default save path is used.\n" "File will be saved in the current working directory.\n" "It is recommended to specify the file path.") json_filename = None if json_filename and (not json_filename.endswith(".json")): json_filename += ".json" # Check if user choose the multi-thread or not if self.var_multi_thread.get() == 0: multi_thread = None elif self.var_multi_thread.get() == 1: # If user choose to use the multi-thread, then get the number of threads that will be used try: multi_thread = int(self.thread_entry.get()) if multi_thread < 1: showwarning("Non Positive Thread Number", "Number of threads has been adjusted to 1.\n" "Degenerated to single thread generation.") multi_thread = 1 except: showerror("Invalid Thread Number", "Invalid number of threads.\n" "Number of threads must be an integer") self.enable_generate_button() return # Check if user choose to save the frames or not if self.var_saved_frame.get() == 1: save_frames = True try: save_frames_rate = int(self.save_frame_entry.get()) except: showerror("Invalid Save Frame Rate", "Invalid Save frame rate.\n" "Save frame rate must be a positive Integer.") self.enable_generate_button() else: save_frames_rate = -1 save_frames = False # Check if user choose to rescale the frames or not if self.var_rescale_frame.get() == 1: try: rescale_factor = float(self.rescale_factor_entry.get()) except: showerror("Invalid Rescale Factor", "Invalid frame rescale factor.\n" "Must be a positive number.\n" "It can be a decimal number but not fractions") self.enable_generate_button() return else: rescale_factor = -1 # Check if user choose to define the letter box region manually if self.letterbox_option.get() == "Manual": try: # Update the letter box parameters, if user choose Manual high_ver = int(self.high_ver_entry.get()) low_ver = int(self.low_ver_entry.get()) left_hor = int(self.left_hor_entry.get()) right_hor = int(self.right_hor_entry.get()) # Start the generation self.barcode_generator.generate_barcode(video_filename, user_defined_letterbox=True, low_ver=low_ver, high_ver=high_ver, left_hor=left_hor, right_hor=right_hor, num_thread=multi_thread, save_frames=save_frames, rescale_frames_factor=rescale_factor, save_frames_rate=save_frames_rate) except: showwarning("Error Occurred in Barcode Generation", "An unknown Error occurred in the barcode " "generation.\nPlease check the letterbox set up" " and the other parameters' specification.") self.enable_generate_button() return elif self.letterbox_option.get() == "Auto": # try: # If not, start the generation. # The letter box will be automatically found during the generation process self.barcode_generator.generate_barcode(video_filename, num_thread=multi_thread, save_frames=save_frames, rescale_frames_factor=rescale_factor, save_frames_rate=save_frames_rate) # except: # showwarning("Error Occurred in Barcode Generation", "An unknown Error occurred in the barcode " # "generation.\nPlease check the parameters' " # "specification.") # self.enable_generate_button() # return # Correct the total frames total_frames = self.barcode_generator.get_barcode().total_frames # Get the key of the barcode, which will be later stored in the memory stack (dictionary) start_pos = video_filename.rfind("/") + 1 if start_pos < 0: start_pos = 0 end_pos = video_filename.rfind(".") videoname = video_filename[start_pos:end_pos] + "_" + barcode_type + "_" + frame_type + "_" + color_metric \ + "_" + str(skip_over) + "_" + str(sampled_frame_rate) + "_" + str(total_frames) # Get the barcode from the barcode generator barcode = self.barcode_generator.get_barcode() if self.var_save_json.get() == 1: try: barcode.save_as_json(json_filename) if json_filename is None: json_filename = "saved_{:s}_barcode_{:s}_{:s}.json" \ .format(barcode.barcode_type, barcode.frame_type, barcode.color_metric) json_filename = os.path.abspath(json_filename) json_saved_success_message = "\nand is saved as a JSON object at path: {:20s}" \ .format(json_filename) except: showwarning("Error Occurred in Saving Barcode", "An unknown Error occurred in saving barcode to " "JSON object.\nPlease verify the file path and " "make sure you have the permission to save file " "at that directory.") json_saved_success_message = "" else: json_saved_success_message = "" # Clear the cv2 captured video object barcode.video = None # Update the user pre-defined meta data to the computed barcode barcode.meta_data = copy.deepcopy(self.meta_data_dict) # Add the generated barcode to the memory stack (dictionary) self.barcode_stack[videoname] = copy.deepcopy(barcode) # Enable the generate button for the next barcode generation request self.enable_generate_button() # Reset the meta data to the initial state self.meta_data_dict = {} # Show barcode generation success message showinfo("Finished Successfully", "{:s} {:s} {:s} Barcode of the input video:\n" "{:20s}\n" "has been successfully generated!\n\n" "Barcode is saved in the memory with name: {:20s}".format(color_metric, frame_type, barcode_type, video_filename, videoname) + json_saved_success_message)
[docs] def disable_generate_button(self): """ Disable the generate button and Specify Meta Data button once generation starts """ # Update the generate button text to the processing self.generate_button["text"] = " Processing... " self.generate_button.config(state="disabled") self.specify_data_button.config(state="disabled")
[docs] def enable_generate_button(self): """ Enable the generate button and Specify Meta Data button in case of failed generation """ # Change the button text back to Generate Barcode self.generate_button["text"] = "Generate Barcode" self.generate_button.config(state="normal") self.specify_data_button.config(state="normal")
[docs] def disable_setup(self): """ Disable the letter box setup entry if user choose the Auto radio button """ self.high_ver_entry.config(state="disabled") self.low_ver_entry.config(state="disabled") self.left_hor_entry.config(state="disabled") self.right_hor_entry.config(state="disabled")
[docs] def enable_setup(self): """ Enable the letter box setup entry if user choose the Manual radio button """ self.high_ver_entry.config(state="normal") self.low_ver_entry.config(state="normal") self.left_hor_entry.config(state="normal") self.right_hor_entry.config(state="normal")