Adding top bar options for draw methods

Each of the 16 toolbar buttons can have its own option. Just like we called the functions related to the toolbar buttons dynamically, we will again call methods to display options for the top bar dynamically.

So we decide that the method for handling the top bar options would be named by appending the string _options to the existing method.

Suppose we want to display the options for the draw_line method, it would be defined in the method called draw_line_options. Similarly, we have to define methods such as draw_arc_options, draw_star_options, and others.

We achieve this dynamic call in the display_options_in_the_top_bar method as follows (see code 6.06.py):

def display_options_in_the_top_bar(self):
self.show_selected_tool_icon_in_top_bar(self.selected_tool_bar_function)
options_function_name =
"{}_options".format(self.selected_tool_bar_function)
func = getattr(self, options_function_name, self.function_not_defined)
func()

Now, with that code in place, every time a toolbar button is clicked the program will look for a method named by appending the _options string to the current method related to the button. If it finds one, it will be executed. If not found, the fallback function function_not_defined will be called, which is an empty method to silently ignore the absence of a method.

The Canvas widget lets you specify the fill color, outline color, and border width for most shapes as their configurable options.

In addition to these, the Canvas widget also has several other configurable options for many of these basic shapes. For instance, for a line, you can specify whether it will have an arrowhead shape at the end or it will be dashed.

We need to display the following top options for the first six buttons:

As can be seen, we need to create Combobox widgets for fill, outline, width, arrow, and dash. We first import the ttk module into our namespace and then create the Combobox widget as shown in the following code (see code 6.06.py):

def create_fill_options_combobox(self):
Label(self.top_bar, text='Fill:').pack(side="left")
self.fill_combobox = ttk.Combobox(self.top_bar, state='readonly',
width=5)
self.fill_combobox.pack(side="left")
self.fill_combobox['values'] = ('none', 'fg', 'bg', 'black', 'white')
self.fill_combobox.bind('<<ComboboxSelected>>', self.set_fill)
self.fill_combobox.set(self.fill)

The ttk Combobox widget binds to another method called set_fill, which is defined as follows (6.06.py): 

def set_fill(self, event=None):
fill_color = self.fill_combobox.get()
if fill_color == 'none':
self.fill = '' # transparent
elif fill_color == 'fg':
self.fill = self.foreground
elif fill_color == 'bg':
self.fill = self.background
else:
self.fill = fill_color

We define a similar combobox for the width, outline, arrow, and dash properties. We also define a combobox to allow the user to change the number of spokes in the star. 

Since the code for all these methods is pretty similar to the code we have just discussed, we do not explore it here (6.06.py).
Finally, we add the required comboboxes to each of the six options methods as follows:

def draw_line_options(self):
self.create_fill_options_combobox()
self.create_width_options_combobox()
self.create_arrow_options_combobox()
self.create_dash_options_combobox()

There's similar code for all the other five toolbar buttons (see code 6.06.py).

Now, if you run code 6.06.py, it should display options for the first six buttons.

When you change the options, the change is reflected in all subsequent drawings on the canvas.

However, there is a small bug in our code. What if someone has chosen the fill color as the foreground color? And then they change the foreground color from the color palette. Although this changes the value of the foreground attribute, it does not change the value of the fill attribute. Our program will keep using the old foreground value for fill.

In order to fix this bug, we modify the code for set_background_color and set_foreground_color to call two new methods:

def try_to_set_fill_after_palette_change(self):
try:
self.set_fill()
except:
pass

def try_to_set_outline_after_palette_change(self):
try:
self.set_outline()
except:
pass

The two methods are kept in a try…except block because not every toolbar button will have a fill and outline options combobox. Even if a toolbar button has the fill or outline combobox, it may not be selected to use the foreground or background color.

Lastly, since we want the draw_line options to populate the top bar immediately when the program starts, we add the following two lines to the create_gui method (see the 6.06.py code):

self.show_selected_tool_icon_in_top_bar("draw_line")
self.draw_line_options()

This concludes this iteration. We will add functionality to a few other toolbar buttons in the next iteration.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.120.187