4

Fairly new to tkinter and python I was wondering how to achieve a button that would act like this :

  • Click on button drops down a list (so that's a combobox)
  • Each line of the list has a checkbox.
  • Finally if a checkbox is clicked run a function, or (even better) once combobox is no more dropped run a function with items checked as args.

UPDATE

The button/menuButton will have to act like a filter. When menu is dropped down user can uncheck multiple options (without the menu to disappear each time an item is clicked) he don't want. Therefore it's really important to be able to see checkboxes so as the user know which options are currently active.

I finally used the idea of Bryan by creating a top level frame. Here is what I have :

Lich4r
  • 1,305
  • 2
  • 13
  • 27
  • I don't think that with a `Combobox` widget you can do it. Of course, there might be a workaround or other solutions... – nbro Mar 12 '15 at 20:44
  • That's what I told myself cause for the moment when I put a checkbutton widget in the combobox it displays `.4335930840` not the checkbutton – Lich4r Mar 12 '15 at 20:49
  • @Lich4r is this code publicly available as a module? If not can you drop it here or as a gist if you still have it? much appreciated :) – evn Jul 24 '20 at 19:02
  • @evn I found my file back (I've stopped coding). The thing is on my mac (py 3.5.3) it works well but the frame does not really display on windows (py 3.9). How can I share it to you? – Lich4r Nov 19 '20 at 16:46
  • @Lich4r Feel free to email it if that works: ebinder@stevens.edu. Thanks so much! – evn Nov 19 '20 at 19:37

2 Answers2

3

There is no widget to do what you want. You'll have to create a toplevel window with a bunch of checkbuttons. You can then trigger the appearance with a normal button.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • I knew Bryan would come up with an answer :P Looking at your code this is nearly perfect. The only problem is that I don't see checkboxes and when an item menu is clicked menu disappears. I am gonna update my question so as to put more context – Lich4r Mar 12 '15 at 22:32
  • Why should I create another window ? I was thinking of creating a frame and put all the checkbuttons in it but I absolutely don't know how I could "drop down" a frame from a button without moving all stuff below that button. The frame would have to appear on top of all existing other widgets. Is that what you mean by "top level window" ? – Lich4r Mar 12 '15 at 23:36
  • 1
    @FromBabylon: you can use a frame if you want. You can simulate it dropping down by using the `place` geometry manager. The advantage to using a toplevel window is that it wpold be an i dependent window. E user could, for example, leave it open and move it to a separate monitor. – Bryan Oakley Mar 12 '15 at 23:44
  • I have never used place so I'm gonna have a look to it. But my app is using mainly grid and pack for some containers. The "app" I'm doing is a Logviewer. So if user has to open a new window to choose its filters that's not really convenient. Think about opening a new windows before choosing which view you would like for your current file explorer (list or grid for example) that would sucks ^^ having a simple button on top of existing window is much more convenient ! The 'menu solution' could be good if I was able to see the little checks aside text of checkbuttons but I can't see them.. – Lich4r Mar 12 '15 at 23:50
  • I have been trying to use place so as to drag down a frame containing checkbuttons without success. I can easily make a new Frame appear on click of a button on top of other widgets if frame's parent is the "master parent" of other widgets but that supposes I also used place as the manager for other widgets in "master parent" which is not the case in my app. Also how could I get the current x, y coordinates of a given widgets in the WINDOW so as to place correctly the frame just under the button ? – Lich4r Mar 13 '15 at 03:36
  • @FromBabylon: you can use `place` for one widget without using it for all widgets. – Bryan Oakley Mar 13 '15 at 10:36
  • Thanks I thought I should never mix geometry managers in the same parent. I now have what I update in the question. It's good but miss shadow and rounded corner for the frame. I've seen your work to create a rounded corner frame using ttk styles but doesn't render well on retina screen. Also placing frame is not that simple as it depends on window title bar height so I'm not sure my code would work well under another OS – Lich4r Mar 14 '15 at 19:18
  • @FromBabylon: you can't mix `grid` and `pack`, but `place` is usually safe. – Bryan Oakley Mar 14 '15 at 19:38
1

I don't think the OptionMenu is intended to hold anything but strings. It sounds like you want the functionality of a Listbox, which has options to allow for multiple selections, get all selected items, and so on.

This gives you an OptionMenu with checkboxes in the contained Menu. Check whichever items you like, then right-click in the tkinter window to print the values of the checkboxes to the console.

from tkinter import *

master = Tk()

var = StringVar(master)
var.set("Check")
w = OptionMenu(master, variable = var, value="options:")
w.pack()
first = BooleanVar()
second = BooleanVar()
third = BooleanVar()
w['menu'].add_checkbutton(label="First", onvalue=True, 
                          offvalue=False, variable=first)
w['menu'].add_checkbutton(label="Second", onvalue=True, 
                          offvalue=False, variable=second)
w['menu'].add_checkbutton(label="Third", onvalue=1, 
                          offvalue=False, variable=third)


master.bind('<Button-3>', lambda x: print("First:", first.get(), " Second:", 
           second.get(), " - Third:", third.get()))
mainloop()

See also this.

Community
  • 1
  • 1
TigerhawkT3
  • 48,464
  • 6
  • 60
  • 97
  • 1
    Listbox won't fit here because it can't be "dropped down". I want the list to appear only if user click on the button – Lich4r Mar 12 '15 at 21:19
  • It looks like (http://stackoverflow.com/questions/17580218/change-the-options-in-optionmenu-in-python-tkinter) you can access the Menu widget contained in the OptionMenu with `my_optionmenu['menu']`, allowing you to use Menu methods (http://effbot.org/tkinterbook/menu.htm) to add various widgets - such as Checkbuttons - to that Menu. – TigerhawkT3 Mar 12 '15 at 21:58
  • Same problem as above. I don't see checkboxes – Lich4r Mar 12 '15 at 22:37
  • There are no classic checkboxes (i.e., a white box that turns grey on click and displays a check on release), but a check does appear next to selected items. As far as having the menu persist through selections, the most I can think of at the moment is binding each item to a callback that pops the menu again, but I don't know how to open a menu programmatically. – TigerhawkT3 Mar 12 '15 at 22:47
  • I don't see any checks appearing. If I do that I will never be able to close the menu ^^ – Lich4r Mar 12 '15 at 22:49
  • Here's what I'm seeing after clicking the first and third options: http://i.imgur.com/d6RjJqE.png Are you seeing something different? If you somehow bind each option to reopen the menu, you could close the menu by clicking elsewhere in the tkinter window, outside of the menu. – TigerhawkT3 Mar 12 '15 at 23:15
  • Indeed I don't see any checks. Menu is the same before/after a click – Lich4r Mar 12 '15 at 23:33