Outils pour utilisateurs

Outils du site


issue197:python

Ceci est une ancienne révision du document !


Hello again, fellow Beings. I come again to you from the remote land of Central Texas.

As the article title suggests, I’m going to be talking about PAGE again. This time, I will show you how to push the envelope and add Tcl widgets WITHOUT using a Custom widget.

If you are at all familiar with PAGE, you might know that there are a couple of “normal” widgets that PAGE doesn’t include in its toolbox. While that leaves a gap in PAGE and its set of widgets that you can use, there has never been a great request for support for those widgets, which is one reason they haven’t been added before now.

What widgets would I be talking about? The Menubutton and the OptionMenu widgets.

Let’s take a quick look at each of these to see what benefits they give us.

Menubutton

The Menubutton widget is like having a normal menubar-type menu but on a button.

You can use all the “normal” menu items on a Menubutton. This includes cascade, command, separators, checkbuttons, and radiobuttons. In addition, you can include accelerators, images, and create column breaks.

The image above shows a very long menubutton option set that represents all of the books of the King James Bible version, grouped into the Old testament books and New testament books, split with a column break between, and each column has a “header” which is made up of a disabled menu item. Each of the menu items are Radiobutton items, which immediately return an integer value that can be looked up in the list that created the menu that represents the selection the user makes.

OptionMenu

The OptionMenu widget is like a low-tech combobox widget.

When you click on the dash on the side, you get a dropdown with your options.

The Project

I actually created two fairly similar projects for this month, but I’m going to go over only one of them. (Could you hear Ronnie give out a sigh of relief there?) However, I’m going to include them both in the repository for this month. The one we will look at here is a simple project that can be found in the repository under the name of “mb_om_demo.py”. I won’t go too deep into the creation of the project under PAGE, since it will be fairly obvious how I created it.

Basically there are four labels (two static and two dynamic), one button (the Exit button) and two frames. The frames are the empty boxes in between the two sets of labels. I used the “solid” relief for the frames. This way, when you are designing the form, you know exactly where the frames are. I designed the project under PAGE 7.6, so the .tcl file is included.

All of the heavy work is done in the support module, so we don’t risk breaking the project by modifying the GUI module. As I always do, I inserted a line in the main function to call the startup function right before the program is shown on the screen.

As you can see (top right) there are two functions for each of our special widgets. One that sets up the items that the widgets will show, and one that actually creates the widget on the toplevel form for us. There are also two additional functions, which are the callback handlers.

So, we’ll start with the setup_menubutton_items() function (bottom below).

This simple function just creates a list of strings that will be used to populate the Menubutton widget. While this code could easily have been included in the creation function, I decided to break it out into its own function, and to do the same thing for the items for the OptionMenu widget (below).

One thing to notice here. The items for the Menubutton are in a list. The items for the OptionMenu is a tuple. This is important as you will see in a little bit.

Now we will create the Menubutton widget and stick it into the proper Frame(below).

The first thing we do to create the Menubutton widget is to define a couple of global variables, one for the carTypes, which we just defined in the setup_menubutton_items function, and the other named selection, which will be a type of tk.IntVar, since our menu items will all be of the radiobutton type. Then we set the frame relief from solid to flat, to make the frame invisible. Finally, we make the actual assignment of the tk.IntVar. Again, we will do this so the user’s selection will immediately be handled and to cut down on the number of callback functions.

Next, we create the actual widget. Then we will use the Pack geometry manager to “shove” the widget into the frame and force it to completely fill the frame. The name of the MenuButton instance is mnuBtn. We’ll use this every time we need to reference it. Notice that we don’t use the normal _w1. prefix, since we created this not PAGE.

  mnuBtn = ttk.Menubutton(_w1.mbFrame, text="Items")
  mnuBtn.pack(expand=True, side="top", fill="both", anchor="nw")

Now (top right) we have to define the menu object that will be attached to the menu button.

The last thing we do for the Menubutton is to define a counter variable, and walk through the list of carTypes, and then create the radiobutton menu item with the name of the car type, the callback, the value of the counter variable which we set as the value that will be passed back to the callback, and the name of the variable which in our case is selection. Finally, bottom right, we add one to the counter variable.

We start off with the same kind of code we did for the Menubutton widget. Define the globals, set the relief for the frame from solid to flat, and define the tk.StringVar for our return value.

The next line is technically not needed, since it sets the display portion of the OptionMenu to “Options”. If we don’t do that, it just won’t display anything.

  returnval.set("Options")

Finally, we do the creation of the instance of the OptionMenu button and finally pack the widget into its frame, just like we did with the Menubutton widget.

However, notice that in the options for the widget, we use *optionlist as the “list” of options to display. Remember that I said we need to make this a tuple, not a list. The reason for this is that you can provide each item separately as the syntax line below shows…

w = ttk.OptionMenu(parent, variable, choice 1 , choice 2 , …)

If we were to use a straight list, the options will all be placed on the same line instead of a dropdown set of items. There might be a reason for you to want to do this, but I can’t imagine one (next page).

That’s it. Now I have to say that the OptionMenu widget is REALLY a whole lot easier to deal with than the MenuButton. If you’ve ever created a menu by hand in Tkinter, you know it is not a painless process and often not worth all the work. You can see what I mean in the second project. If you run back to the first image in the article, you will see the Menubutton example. I really did this as a proof of concept more than for any real need. I would probably use a popup menu created in the PAGE menu editor before I would hand code a menu for a Menubutton.

The whole purpose in this project was to show you that with a little work (well, a LOT of work in the case of the Menubutton) and digging, you can use any widget that Tkinter provides even if PAGE doesn’t support it.

I’ve put the code for this month’s project in a github repository at https://github.com/gregwa1953/FCM-197.

Until next time, as always; stay safe, healthy, positive and creative!

issue197/python.1696088272.txt.gz · Dernière modification : 2023/09/30 17:37 de auntiee