def set_stage2(self): # Update image title self.ref_object_var.set("Selected Reference Object") # Update instructions self.instructions_var.set( "Now please tell us how long is the dimension given by the pink line in the image.\n" "Provide the most decimals for more accurate results!") # Hide stage 1 for (widget, grid_command) in self.stage1_widgets: widget.grid_forget() # Show stage 2 for (widget, grid_command) in self.stage2_widgets: grid_command() # Update responsive image if self.responsive_image is not None: self.responsive_image.grid(row=1, column=0, rowspan=8, columnspan=3, sticky=NSEW, pady=20) # Update responsive reset_both_responsive(self) make_columns_responsive(self, ignored=[0, 1]) make_rows_responsive(self, ignored=[0, 2, 3, 4, 5, 6, 7])
def set_stage1(self): current = self.current_contour_var.get() # Update image title self.ref_object_var.set("Object #" + str(current + 1)) # Update instructions self.instructions_var.set( "Choose an object for which you know its width or height.\n" "This will allow to calculate the real dimensions of the bamboo slice." ) # Hide stage 2 for (widget, grid_command) in self.stage2_widgets: widget.grid_forget() # Hide invalid message self.invalid_dimension.grid_forget() # Show stage 1 for (widget, grid_command) in self.stage1_widgets: grid_command() # Update responsive image if self.responsive_image is not None: self.responsive_image.grid(row=1, column=0, rowspan=2, columnspan=3, sticky=NSEW, pady=20) # Update responsive reset_both_responsive(self) make_columns_responsive(self, ignored=[1, 2]) make_rows_responsive(self, ignored=[0])
def initialize_widgets(self): # Watchers # Update captured count self.count_str = StringVar() self.count_number = IntVar() self.count_number.trace("w", self.update_count_label) # Status message self.status_var = StringVar() self.status_message = Label(self, textvariable=self.status_var, font=self.controller.header_font, relief=GROOVE, padx=10, pady=10) self.status_message.grid(row=0, column=0, sticky=EW, padx=40, pady=20) # Table headers top_headers = ["Sensor #", "Current\nreading", "Last\ncaptured\nvalue", "Last\ndeviation"] self.table_headers = VerticalTable(self, rows=1, columns=len(top_headers)) self.table_headers.update_cells(top_headers) self.table_headers.grid(row=1, column=0, sticky=S) # column indexes self.live_column = 0 self.captured_column = 1 self.deviation_column = 2 # Sensor Data: current readings, last captured, and deviation info sensor_headers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "Sensor Z"] self.table = HorizontalTable(self, rows=len(sensor_headers), columns=3, header_values=sensor_headers) self.table.grid(row=2, column=0, rowspan=2, sticky=N) # calibrate button self.calibrate_button = GreenButton(self, text="Calibrate Sensors", command=self.calibrate) self.calibrate_button.grid(row=0, column=1, pady=20) # captured count self.captured_count = Label(self, textvariable=self.count_str, font=self.controller.bold_font) self.captured_count.grid(row=2, column=1, sticky=S, pady=10) # capture button self.capture_button = YellowButton(self, text="Capture Measurements", command=self.capture) self.capture_button.grid(row=3, column=1, sticky=N) # view results button self.results_button = GreenButton(self, text="View Results", command=self.view_results, image=self.controller.arrow_right, compound=RIGHT) self.results_button.grid(row=4, column=1, sticky=SE, padx=20, pady=20) make_rows_responsive(self) make_columns_responsive(self)
def initialize_widgets(self): # Watchers # on image path change self.image_path = StringVar() self.image_path.trace("w", self.on_image_path_change) # responsive image container self.placeholder_image = Image.open("assets/placeholder_image.png") self.responsive_image = ResponsiveImage(self, self.placeholder_image) self.responsive_image.grid(row=0, column=0, rowspan=4) # choose image button self.choose_button = GreenButton(self, text="Choose an image", command=self.load_image) self.choose_button.grid(row=0, column=1, sticky=S) # selected image path self.path_entry = Entry(self, textvariable=self.image_path, state="readonly") self.path_entry.grid(row=1, column=1, sticky=EW, padx=20) # status message in row 2 self.message_var = StringVar() self.message = Label(self, textvariable=self.message_var, font=self.controller.header_font) # begin button self.begin_button = YellowButton(self, text="BEGIN", command=self.begin, image=self.controller.arrow_right, compound=RIGHT) self.begin_button.grid(row=3, column=1, sticky=SE, padx=20, pady=20) # Update widgets self.on_image_path_change() # visited flag self.visit_counter = 0 make_rows_responsive(self) make_columns_responsive(self)
def initialize_widgets(self): # Result image row=0, col=0, columnspan=2 # Save button self.save_button = YellowButton(self, text="Save coordinates", command=self.save, image=self.controller.save_icon, compound=LEFT) self.save_button.grid(row=2, column=0, sticky=E, padx=10, pady=20) # Discard button self.discard_button = RedButton(self, text="DISCARD", command=self.discard) self.discard_button.grid(row=2, column=1, sticky=W, padx=10, pady=20) # min size of buttons row self.grid_rowconfigure(2, minsize=80) make_rows_responsive(self, ignored=[0]) make_columns_responsive(self)
def __init__(self, parent, controller): Frame.__init__(self, parent) self.controller = controller self.bind("<<ShowFrame>>", self.on_show_frame) # Bamboo Scanner logo logo_image = ImageTk.PhotoImage(Image.open("assets/logo.png")) self.logo = Label(self, image=logo_image) self.logo.image = logo_image self.logo.grid(row=0, columnspan=2, sticky=S) # Buttons font buttons_font = font.Font(family="Segoe UI Emoji", size=26) # BPC self.bpc_button = GreenButton(self, text="Pole", command=self.open_bpc, font=buttons_font) self.bpc_button.grid(row=1, column=0, sticky=S) self.bpc_description = Label( self, fg="#333333", text="Measure the external surface\n of a bamboo pole") self.bpc_description.grid(row=2, column=0, rowspan=2, sticky=N) # BSC self.bsc_button = GreenButton(self, text="Slice", command=self.open_bsc, font=buttons_font) self.bsc_button.grid(row=1, column=1, sticky=S) self.bsc_description = Label( self, fg="#333333", text= "Measure the inner and outer\n circumferences of a\n bamboo cross section" ) self.bsc_description.grid(row=2, column=1, rowspan=3, sticky=N) make_rows_responsive(self) make_columns_responsive(self)
def __init__(self, parent, controller): Frame.__init__(self, parent) self.controller = controller self.bind("<<ShowFrame>>", self.on_show_frame) # Bamboo Scanner logo logo_image = ImageTk.PhotoImage(Image.open("assets/logo.png")) self.logo = Label(self, image=logo_image) self.logo.image = logo_image self.logo.grid(row=0, columnspan=2, sticky=S) # select a tool label self.select_label = Label(self, text="Select a tool:", font=self.controller.important_font, fg="grey") self.select_label.grid(row=1, column=0, columnspan=2, sticky=S) # Buttons font buttons_font = font.Font(family="Segoe UI Emoji", size=26) # BPC self.bpc_button = GreenButton(self, text="Pole", command=self.open_bpc, font=buttons_font) self.bpc_button.grid(row=2, column=0, sticky=S) self.bpc_description = Label(self, fg="#333333", text="Measure the external surface\n of a bamboo pole") self.bpc_description.grid(row=3, column=0, rowspan=2, sticky=N) # BSC self.bsc_button = GreenButton(self, text="Slice", command=self.open_bsc, font=buttons_font) self.bsc_button.grid(row=2, column=1, sticky=S) self.bsc_description = Label(self, fg="#333333", text="Measure the inner and outer\n circumferences of a\n bamboo cross section") self.bsc_description.grid(row=3, column=1, rowspan=3, sticky=N) # guide link self.guide_button = Button(self, text="First time? Open tutorial", relief=FLAT, command=self.open_guide, fg="blue", font=self.controller.underlined_font) self.guide_button.grid(row=4, columnspan=2) make_rows_responsive(self) make_columns_responsive(self)
def initialize_widgets(self): # Empty message self.empty_message = Label( self, text="Nothing to see here. Go capture some measurements!", font=self.controller.header_font) # Save button self.save_button = YellowButton(self, text="Save coordinates", command=self.save, image=self.controller.save_icon, compound=LEFT) self.save_button.grid(row=1, column=0, sticky=SE, padx=10, pady=20) # Discard button self.discard_button = RedButton(self, text="DISCARD", command=self.discard) self.discard_button.grid(row=1, column=1, sticky=SW, padx=10, pady=20) make_rows_responsive(self) make_columns_responsive(self)
def initialize_widgets(self): # a canvas with scrollbars; the results table goes in it h_scrollbar = AutoScrollbar(self, orient=HORIZONTAL) h_scrollbar.grid(row=1, column=0, columnspan=2, sticky=EW) v_scrollbar = AutoScrollbar(self) v_scrollbar.grid(row=0, column=2, sticky=NS) self.canvas = Canvas(self, xscrollcommand=h_scrollbar.set, yscrollcommand=v_scrollbar.set) h_scrollbar.config(command=self.canvas.xview) v_scrollbar.config(command=self.canvas.yview) # Empty message self.empty_message = Label( self, text="Nothing to see here. Go capture some measurements!", font=self.controller.header_font) # Save button self.save_button = YellowButton(self, text="Save coordinates", command=self.save, image=self.controller.save_icon, compound=LEFT) self.save_button.grid(row=2, column=0, sticky=S, pady=20) # Discard button self.discard_button = RedButton(self, text="DISCARD", command=self.discard) self.discard_button.grid(row=2, column=1, sticky=S, pady=20) # responsive except the scrollbars and the buttons make_rows_responsive(self, ignored=[1, 2]) make_columns_responsive(self, ignored=[2])
def initialize_widgets(self): # Watchers # Update state of navigation buttons self.current_circumference_var = IntVar() self.current_circumference_var.trace("w", self.update_navigation) # Update count label self.selected_count_var = IntVar() self.selected_count_var.trace("w", self.update_count_text) # Update buttons self.selected_count_text = StringVar() self.selected_count_text.trace("w", self.update_buttons) # title of circumference image self.circumference_title_var = StringVar() self.circumference_title = Label( self, textvariable=self.circumference_title_var, font=self.controller.header_font) self.circumference_title.grid(row=0, column=0, sticky=W, padx=20, pady=20) # Controls to navigate contours self.prev_button = GreenButton( self, text="Previous", image=self.controller.arrow_left, compound=LEFT, command=lambda: self.show_circumference( self.current_circumference_var.get() - 1)) self.prev_button.grid(row=0, column=1, sticky=SE, padx=5, pady=20) self.next_button = GreenButton( self, text="Next", image=self.controller.arrow_right, compound=RIGHT, command=lambda: self.show_circumference( self.current_circumference_var.get() + 1)) self.next_button.grid(row=0, column=2, sticky=SW, pady=20) # image in row=1, col=0, colspan=3, rowspan=4 # instructions instructions_text = "More than 2 circumferences were found.\n" instructions_text += "Select the inner and outer circumference of the bamboo slice." self.instructions = Label(self, text=instructions_text, relief=GROOVE, padx=10, pady=10) self.instructions.grid(row=1, column=3, padx=40) # remove button self.remove_button = RedButton(self, text="Deselect circumference", command=self.deselect) self.remove_button.grid(row=2, column=3) # select button self.select_button = YellowButton(self, text="Use this circumference", command=self.select) self.select_button.grid(row=2, column=3) # Selection count self.selected_count = Label(self, textvariable=self.selected_count_text, font=self.controller.important_font) self.selected_count.grid(row=3, column=3, sticky=N) # confirm button self.confirm_button = YellowButton(self, text="CONFIRM", command=self.confirm, state=DISABLED, cursor="arrow") self.confirm_button.grid(row=4, column=3, sticky=SE, padx=20, pady=20) make_columns_responsive(self, ignored=[1, 2]) make_rows_responsive(self, ignored=[0])
def initialize_widgets(self): # CALIBRATION # Ring diameter entry value self.ring_diameter_var = StringVar() self.ring_diameter_var.trace("w", self.update_begin_button) # Calibration object value self.calibration_object_var = StringVar() self.calibration_object_var.trace("w", self.update_begin_button) # Distance to end of rail value self.distance_z_var = StringVar() self.distance_z_var.trace("w", self.update_begin_button) # %d = Type of action (1=insert, 0=delete, -1 for others) # %P = value of the entry if the edit is allowed # %S = the text string being inserted or deleted, if any validate_cmd = (self.register(self.validate_dimension), '%d', '%P', '%S') # Calibration settings group self.calibration_settings = LabelFrame( self, text="Calibration Settings", fg="grey", padx=20, pady=20, font=self.controller.header_font) self.calibration_settings.grid(row=0, column=0, sticky=NS + W, padx=20, pady=20) # Ring diameter self.ring_diameter_label = Label(self.calibration_settings, text="Ring structure diameter", anchor=SW, font=self.controller.bold_font) self.ring_diameter_label.grid(row=0, column=0, sticky=SW, padx=20) self.ring_diameter_entry = EntryWithPlaceholder( self.calibration_settings, text_var=self.ring_diameter_var, placeholder_text="0.00", validatecommand=validate_cmd, validate="key", textvariable=self.ring_diameter_var) self.ring_diameter_entry.grid(row=1, column=0, sticky=NW, padx=20, pady=20) # Calibration object self.calibration_object_label = Label(self.calibration_settings, text="Calibration object radius", font=self.controller.bold_font, anchor=SW) self.calibration_object_label.grid(row=0, column=1, sticky=SW, padx=20) self.calibration_object_entry = EntryWithPlaceholder( self.calibration_settings, text_var=self.calibration_object_var, placeholder_text="0.00", validatecommand=validate_cmd, textvariable=self.calibration_object_var, validate="key") self.calibration_object_entry.grid(row=1, column=1, sticky=NW, padx=20, pady=20) # Distance to flat surface at end of rail self.distance_z_label = Label(self.calibration_settings, text="Distance to the end of the rail", anchor=SW, font=self.controller.bold_font) self.distance_z_label.grid(row=2, column=0, sticky=SW, padx=20) self.distance_z_entry = EntryWithPlaceholder( self.calibration_settings, text_var=self.distance_z_var, placeholder_text="0.00", validate="key", validatecommand=validate_cmd, textvariable=self.distance_z_var) self.distance_z_entry.grid(row=3, column=0, sticky=NW, padx=20, pady=20) # Invalid dimension message self.invalid_dimension = Label( self.calibration_settings, text="Dimension must be between 1 and 28 centimeters", fg="red", anchor=W) # make calibration section responsive make_columns_responsive(self.calibration_settings) make_rows_responsive(self.calibration_settings) # description label self.description_label = Label( self, text="Information about the sample (optional)", font=self.controller.bold_font) self.description_label.grid(row=1, column=0, sticky=SW, padx=20, pady=20) # Description text area self.text_area = ScrollableTextArea(self) self.text_area.grid(row=2, column=0, sticky=NW, padx=20) # begin button self.begin_button = YellowButton(self, text="BEGIN", command=self.begin, image=self.controller.arrow_right, compound=RIGHT) self.begin_button.grid(row=3, column=0, sticky=SE, padx=20, pady=20) # set placeholders self.ring_diameter_entry.set_placeholder() self.calibration_object_entry.set_placeholder() self.distance_z_entry.set_placeholder() make_rows_responsive(self) make_columns_responsive(self)
def __init__(self): Tk.__init__(self) # START SHARED # Global fonts self.global_font_family = font.Font(family="Segoe UI Emoji") self.common_font = font.Font(family="Segoe UI Emoji", size=14) self.bold_font = font.Font(family="Segoe UI Emoji", size=13, weight="bold") self.header_font = font.Font(family="Segoe UI Emoji", size=16, weight="bold") self.title_font = font.Font(family="Segoe UI Emoji", size=28, weight="bold") self.important_font = font.Font(family="Segoe UI Emoji", size=28, weight="bold", underline=True) # update widget fonts self.option_add("*Font", self.global_font_family) self.option_add("*Button.Font", self.bold_font) self.option_add("*Label.Font", self.common_font) # Common images self.arrow_left = ImageTk.PhotoImage( Image.open("assets/arrow_left.png")) self.arrow_right = ImageTk.PhotoImage( Image.open("assets/arrow_right.png")) self.save_icon = ImageTk.PhotoImage(Image.open("assets/save.png")) # END SHARED # Main page layout: hosts page content and global widgets self.container = Frame(self) # Container fills the entire window self.container.pack(side=TOP, fill=BOTH, expand=True) # Navigation bar self.navbar = Frame(self.container, bg="#35AD35") self.navbar.grid(row=0, columnspan=2, sticky=NSEW) # Home button home_image = Image.open("assets/home.png") # resize home button image home_image = resize_keep_aspect(home_image, max_w=100, max_h=37) home_image = ImageTk.PhotoImage(home_image) self.home_button = Label(self.navbar, image=home_image, cursor="hand2", text="Home") self.home_button.image = home_image self.home_button.grid(row=0, column=0, sticky=NSEW) # bind to click event self.home_button.bind("<Button-1>", self.go_home) self.home_button.bind("<Enter>", self.on_enter_home_btn) self.home_button.bind("<Leave>", self.on_leave_home_btn) # Back button self.back_button = Button(self.navbar, image=self.arrow_left, cursor="hand2", text="Go back", compound=LEFT, command=self.go_back, bg="#35AD35", fg="#FFFFFF", relief=GROOVE, padx=10) self.back_button.grid(row=0, column=1, sticky=NSEW) # Page title self.title_var = StringVar() self.page_title = Label(self.navbar, textvariable=self.title_var, bg="#35AD35", fg="#FFFFFF", font=self.title_font) self.page_title.grid(row=0, column=2, sticky=W + E, padx=10) # Step indicator self.step = StringVar() self.page_step = Label(self.navbar, textvariable=self.step, bg="#35AD35", fg="#FFFFFF") self.page_step.grid(row=0, column=3, sticky=E, padx=10) # only the page title is responsive make_columns_responsive(self.navbar, ignored=[0, 1, 3]) # Bamboo decor on left side of screen bamboo_image = Image.open("assets/bamboo.png") self.bamboo = ResponsiveImage(self.container, bamboo_image, tag="bamboo", anchor=NW) self.bamboo.grid(row=1, column=0, sticky=NSEW) # The class names for both BSC and BPC self.bsc_pages = (ConfigBSC, PickCircumferencesBSC, RefObjectBSC, ResultsBSC) self.bpc_pages = (ConfigBPC, MeasureBPC, ResultsBPC) # Initialize all pages and keep their references accessible self.frames = {} for F in (() + (Home, ) + self.bsc_pages + self.bpc_pages): page_name = F.__name__ frame = F(parent=self.container, controller=self) self.frames[page_name] = frame # Add all frames to the container, on top of each other frame.grid(row=1, column=1, sticky=NSEW) # make the window responsive, except the navbar row make_rows_responsive(self.container, ignored=[0]) make_columns_responsive(self.container) # Start on the home page self.active_frame = None self.show_frame("Home")
def initialize_widgets(self): # CALIBRATION # Ring diameter entry value self.ring_diameter_var = StringVar() self.ring_diameter_var.trace("w", self.update_begin_button) # Calibration object value self.calibration_object_var = StringVar() self.calibration_object_var.trace("w", self.update_begin_button) # Distance to end of rail value self.distance_z_var = StringVar() self.distance_z_var.trace("w", self.update_begin_button) # %d = Type of action (1=insert, 0=delete, -1 for others) # %P = value of the entry if the edit is allowed # %S = the text string being inserted or deleted, if any # %W = the name of the widget validate_cmd = (self.register(self.validate_calibration_settings), '%d', '%P', '%S', '%W') # Calibration settings group self.calibration_settings = LabelFrame(self, text="Calibration Settings (all measures in centimeters)", fg="grey", padx=20, pady=20, font=self.controller.header_font) self.calibration_settings.grid(row=0, column=0, sticky=NSEW, padx=20, pady=20) # Ring diameter self.ring_diameter_label = Label(self.calibration_settings, text="Ring structure diameter", anchor=SW, font=self.controller.bold_font) self.ring_diameter_label.grid(row=0, column=0, sticky=SW, padx=20) # ring diameter range self.range_ring_diameter = Label(self.calibration_settings, text="[Valid range: 10 - 30]", fg="grey", anchor=SW, font=self.controller.small_font) self.range_ring_diameter.grid(row=1, column=0, sticky=NW, padx=20) self.ring_diameter_entry = EntryWithPlaceholder(self.calibration_settings, text_var=self.ring_diameter_var, placeholder_text="0.00", validatecommand=validate_cmd, validate="key", textvariable=self.ring_diameter_var, name="ring") self.ring_diameter_entry.grid(row=2, column=0, sticky=NW, padx=20, pady=20) # Calibration object self.calibration_object_label = Label(self.calibration_settings, text="Calibration object diameter", font=self.controller.bold_font, anchor=SW) self.calibration_object_label.grid(row=0, column=1, sticky=SW, padx=20) # calibration object diameter range self.range_calibration_obj_diameter = Label(self.calibration_settings, text="[Valid range: 2 - 26]", fg="grey", anchor=NW, font=self.controller.small_font) self.range_calibration_obj_diameter.grid(row=1, column=1, sticky=NW, padx=20) self.calibration_object_entry = EntryWithPlaceholder(self.calibration_settings, text_var=self.calibration_object_var, placeholder_text="0.00", validatecommand=validate_cmd, textvariable=self.calibration_object_var, validate="key", name="calibration_obj") self.calibration_object_entry.grid(row=2, column=1, sticky=NW, padx=20, pady=20) # Distance to flat surface at end of rail self.distance_z_label = Label(self.calibration_settings, text="Distance to the end of the rail", anchor=SW, font = self.controller.bold_font) self.distance_z_label.grid(row=3, column=0, sticky=SW, padx=20) # z distance range self.range_z_distance = Label(self.calibration_settings, text="[Valid range: 15.24 - 645]", fg="grey", anchor=NW, font=self.controller.small_font) self.range_z_distance.grid(row=4, column=0, sticky=NW, padx=20) self.distance_z_entry = EntryWithPlaceholder(self.calibration_settings, text_var=self.distance_z_var, placeholder_text="0.00", validate="key", name="z_distance", validatecommand=validate_cmd, textvariable=self.distance_z_var) self.distance_z_entry.grid(row=5, column=0, sticky=NW, padx=20, pady=20) # calibration object diameter greater than ring diameter self.calibration_obj_greater_ring = Label(self.calibration_settings, text="The calibration object's diameter\ncan't be greater than the ring diameter", fg="red", anchor=NW) # make calibration section responsive make_columns_responsive(self.calibration_settings) make_rows_responsive(self.calibration_settings) # description label self.description_label = Label(self, text="Information about the bamboo sample (optional)", font=self.controller.bold_font) self.description_label.grid(row=1, column=0, sticky=SW, padx=20, pady=20) # Description text area self.text_area = ScrollableTextArea(self) self.text_area.grid(row=2, column=0, sticky=NW, padx=20) # begin button self.begin_button = YellowButton(self, text="BEGIN", command=self.begin, image=self.controller.arrow_right, compound=RIGHT) self.begin_button.grid(row=3, column=0, sticky=SE, padx=20, pady=20) # set placeholders self.ring_diameter_entry.set_placeholder() self.calibration_object_entry.set_placeholder() self.distance_z_entry.set_placeholder() make_rows_responsive(self) make_columns_responsive(self) # min size of buttons row self.grid_rowconfigure(3, minsize=80)