Checkbuttons im Submenü

Fragen zu Tkinter.
Antworten
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Ich habe in einem Submenü zwei Checkbuttons.
Wenn ich da auf eine Checkbutton drücke, geht aber das Menü wieder zu.
Wenn ich auch den zweiten Checkbutton ankreuzen will, muss ich das Submenü wieder aufmachen.
Ich hätte aber gerne, dass man auch den zweiten Checkbutton ankreuzen kann, ohne dass das Menü wieder zugeht.
Gibt es dafür eine Lösung?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

OK, wenn keiner eine Lösung weiß, muss ich eben eine basteln
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Habe schon etwas herausgefunden.

Wenn das sub sub Menü in der Cascade zum ersten Mal aufgeht, bekommt man 3 <Configure> events. Später sind es dann 2. Damit weiß man, wo dieses Menü ist und wie breit und wie hoch es ist:

Code: Alles auswählen

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


event_count = 0

def onFormEvent( event ):
    dir_event = dir( event )
    global event_count
    print('EVENT COUNT = ' + str(event_count))
    event_count += 1          
    print('_____________________')
    for key in dir_event:
        if not key.startswith( '_' ):
            print('%s=%s' % ( key, getattr( event, key ) ))
    print('------------------------')

class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        # widget definitions ===================================
        self.menu = Menu_1(self)
        self['menu'] = self.menu

class Menu_1(tk.Menu):

    def __init__(self,master,**kwargs):
        tk.Menu.__init__(self,master,**kwargs)
        # widget definitions ===================================
        self.Menu = Menu_2(self,activeforeground='black', activebackground='#7bfeff', fg='black', bg='white', tearoff=0, relief='solid')
        self.dyntk_name = 'File'
        self.add_cascade(menu=self.Menu,underline=0, label='File')

class Menu_2(tk.Menu):

    def __init__(self,master,**kwargs):
        tk.Menu.__init__(self,master,**kwargs)
        self.config(activeforeground='black', activebackground='#7bfeff', fg='black', bg='white', tearoff=0, relief='solid')
        # widget definitions ===================================
        self.dyntk_name = 'command1'
        self.add_command(underline=0, label='command1')
        self.dyntk_name = 'command2'
        self.add_command(underline=0, label='command2')
        self.dyntk_name = 'command3'
        self.add_command(underline=0, label='command3')
        self.dyntk_name = 'command4'
        self.add_command(label='command4')
        self.dyntk_name = 'command5'
        self.add_command(label='command5')
        self.dyntk_name = 'separator'
        self.add_separator()
        self.dyntk_name = 'command6'
        self.add_command(label='command6')
        self.Menu = Menu_3(self,activeforeground='black', activebackground='#7bfeff', fg='black', bg='white', tearoff=0, relief='solid')
        print('Menu_3',str(self.Menu))
        print()
        self.dyntk_name = 'cascade'
        self.add_cascade(menu=self.Menu,underline=0, label='cascade')
        self.dyntk_name = 'separator_quit'
        self.add_separator()
        self.dyntk_name = 'command7'
        self.add_command(label='command7')

class Menu_3(tk.Menu):

    def __init__(self,master,**kwargs):
        tk.Menu.__init__(self,master,**kwargs)
        self.config(activeforeground='black', activebackground='#7bfeff', fg='black', bg='white', tearoff=0, relief='solid')
        # widget definitions ===================================
        self.dyntk_name = 'command1'
        self.add_command(underline=0, label='command1')
        self.dyntk_name = 'command2'
        self.add_command(underline=9, label='command2')
        self.dyntk_name = 'command3'
        self.add_command(underline=9, label='command3')
        self.dyntk_name = 'separator'
        self.add_separator()
        self.dyntk_name = 'command4'
        self.add_command(label='command4')

        self.bind( '<Configure>', onFormEvent )

if __name__ == '__main__':
    Application().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Das ist dann das Menü, das wir brauchen. Und dieses ist der erste Streich:

Code: Alles auswählen

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


event_count = 0

def onFormEvent( event ):
    dir_event = dir( event )
    global event_count
    print('EVENT COUNT = ' + str(event_count))
    event_count += 1          
    print('_____________________')
    for key in dir_event:
        if not key.startswith( '_' ):
            print('%s=%s' % ( key, getattr( event, key ) ))
    print('------------------------')

class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        # widget definitions ===================================
        self.menu = Menu_1(self)
        self['menu'] = self.menu

class Menu_1(tk.Menu):

    def __init__(self,master,**kwargs):
        tk.Menu.__init__(self,master,**kwargs)
        # widget definitions ===================================
        self.Menu = Menu_2(self,activeforeground='black', activebackground='#7bfeff', fg='black', bg='white', tearoff=0, relief='solid')
        self.dyntk_name = 'File'
        self.add_cascade(menu=self.Menu,underline=0, label='File')

class Menu_2(tk.Menu):

    def __init__(self,master,**kwargs):
        tk.Menu.__init__(self,master,**kwargs)
        self.config(activeforeground='black', activebackground='#7bfeff', fg='black', bg='white', tearoff=0, relief='solid')
        # widget definitions ===================================
        self.dyntk_name = 'command1'
        self.add_command(underline=0, label='command1')
        self.dyntk_name = 'command2'
        self.add_command(underline=0, label='command2')
        self.dyntk_name = 'command3'
        self.add_command(underline=0, label='command3')
        self.dyntk_name = 'command4'
        self.add_command(label='command4')
        self.dyntk_name = 'command5'
        self.add_command(label='command5')
        self.dyntk_name = 'separator'
        self.add_separator()
        self.dyntk_name = 'command6'
        self.add_command(label='command6')
        self.Menu = Menu_3(self,activeforeground='black', activebackground='#7bfeff', fg='black', bg='white', tearoff=0, relief='solid')
        print('Menu_3',str(self.Menu))
        print()
        self.dyntk_name = 'cascade'
        self.add_cascade(menu=self.Menu,underline=0, label='cascade')
        self.dyntk_name = 'separator_quit'
        self.add_separator()
        self.dyntk_name = 'command7'
        self.add_command(label='command7')

class Menu_3(tk.Menu):

    def __init__(self,master,**kwargs):
        tk.Menu.__init__(self,master,**kwargs)
        self.config(tearoff=0, relief='flat', bd = 0, activeborderwidth = 0)
        self.bind( '<Configure>', onFormEvent )

if __name__ == '__main__':
    Application().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class menu_toplevel(tk.Toplevel):

    def __init__(self,master,**kwargs):
        tk.Toplevel.__init__(self,master,**kwargs)
        self.overrideredirect(True)
        self.lift()
        self.config(bd=1, relief='solid', bg='white')
        # widget definitions ===================================
        self.checkbutton1 = tk.Checkbutton(self,text='checkbutton1', activeforeground='black', bg='white', bd='0', font='TkMenuFont', anchor='w', activebackground='#7bfeff', fg='black', highlightthickness='0')
        self.checkbutton2 = tk.Checkbutton(self,text='checkbutton2', activeforeground='black', bg='white', highlightcolor='black', bd='0', font='TkMenuFont', anchor='w', activebackground='#7bfeff', highlightbackground='white', fg='black', highlightthickness='0')
        self.command1 = tk.Button(self,pady='1', bd='0', font='TkMenuFont', relief='flat', anchor='w', padx='1m', activebackground='#7bfeff', activeforeground='black', fg='black', highlightthickness='0', bg='white', text='command1')
        self.command2 = tk.Button(self,pady='1', bd='0', font='TkMenuFont', relief='flat', anchor='w', padx='1m', activebackground='#7bfeff', activeforeground='black', fg='black', highlightthickness='0', bg='white', text='command2')
        self.command3 = tk.Button(self,pady='1', bd='0', font='TkMenuFont', relief='flat', anchor='w', padx='1m', activebackground='#7bfeff', activeforeground='black', fg='black', highlightthickness='0', bg='white', text='command3')
        self.help = tk.Button(self,pady='1', bd='0', font='TkMenuFont', relief='flat', anchor='w', padx='1m', activebackground='#7bfeff', activeforeground='black', fg='black', highlightthickness='0', bg='white', text='Help')
        self.separator1 = tk.Frame(self,bg='black', height=1)
        self.separator2 = tk.Frame(self,bg='black', height=1)
        self.checkbutton1.pack(padx=2, pady=2, anchor='w', fill='x')
        self.checkbutton2.pack(padx=2, pady=1, anchor='w')
        self.separator1.pack(pady=1, fill='x')
        self.command1.pack(padx=2, pady=1, anchor='w', fill='x')
        self.command2.pack(padx=2, pady=1, anchor='w', fill='x')
        self.command3.pack(padx=2, pady=1, anchor='w', fill='x')
        self.separator2.pack(fill='x')
        self.help.pack(padx=2, pady=1, anchor='w', fill='x')

if __name__ == '__main__':
    menu_toplevel(tk.Tk()).mainloop()
Und dieses war der zweite Streich
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Soweit bin ich gekommen:

Code: Alles auswählen

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk

class MenuToplevel(tk.Toplevel):

    def __init__(self,master,**kwargs):
        tk.Toplevel.__init__(self,master,**kwargs)
        self.withdraw()
        self.overrideredirect(True)
        self.lift()

        self.config(bd=1, relief='solid', bg='white')
        # widget definitions ===================================
        self.checkbutton1 = tk.Checkbutton(self, text='checkbutton1', activeforeground='black', bg='white', bd='0', font='TkMenuFont', anchor='w', activebackground='#7bfeff', fg='black', highlightthickness='0')
        self.checkbutton2 = tk.Checkbutton(self,text='checkbutton2', activeforeground='black', bg='white', highlightcolor='black', bd='0', font='TkMenuFont', anchor='w', activebackground='#7bfeff', highlightbackground='white', fg='black', highlightthickness='0')
        self.command1 = tk.Button(self,command = self.button_click,pady='1', bd='0', font='TkMenuFont', relief='flat', anchor='w', padx='1m', activebackground='#7bfeff', activeforeground='black', fg='black', highlightthickness='0', bg='white', text='command1')
        self.command2 = tk.Button(self,command = self.button_click,pady='1', bd='0', font='TkMenuFont', relief='flat', anchor='w', padx='1m', activebackground='#7bfeff', activeforeground='black', fg='black', highlightthickness='0', bg='white', text='command2')
        self.command3 = tk.Button(self,command = self.button_click,pady='1', bd='0', font='TkMenuFont', relief='flat', anchor='w', padx='1m', activebackground='#7bfeff', activeforeground='black', fg='black', highlightthickness='0', bg='white', text='command3')
        self.help = tk.Button(self,command = self.button_click,pady='1', bd='0', font='TkMenuFont', relief='flat', anchor='w', padx='1m', activebackground='#7bfeff', activeforeground='black', fg='black', highlightthickness='0', bg='white', text='Help')
        self.separator1 = tk.Frame(self,bg='black', height=1)
        self.separator2 = tk.Frame(self,bg='black', height=1)
        self.checkbutton1.pack(padx=2, pady=2, anchor='w', fill='x')
        self.checkbutton2.pack(padx=2, pady=1, anchor='w')
        self.separator1.pack(pady=1, fill='x')
        self.command1.pack(padx=2, pady=1, anchor='w', fill='x')
        self.command2.pack(padx=2, pady=1, anchor='w', fill='x')
        self.command3.pack(padx=2, pady=1, anchor='w', fill='x')
        self.separator2.pack(fill='x')
        self.help.pack(padx=2, pady=1, anchor='w', fill='x')
        
        self.may_destroy = True
        self.bind('<Enter>', self.clear_destroy)
        self.bind('<Leave>', self.set_destroy)


    def set_destroy(self,event):
        self.may_destroy = True

    def clear_destroy(self,event):
        self.may_destroy = False

    def button_click(self):
        tk.Toplevel.destroy(self)

    def destroy(self):
        if self.may_destroy:
            tk.Toplevel.destroy(self)


class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        # widget definitions ===================================
        self.menu = Menu_1(self)
        self['menu'] = self.menu

class Menu_1(tk.Menu):

    def __init__(self,master,**kwargs):
        tk.Menu.__init__(self,master,**kwargs)
        # widget definitions ===================================
        self.Menu = Menu_2(self,activeforeground='black', activebackground='#7bfeff', fg='black', bg='white', tearoff=0, relief='solid')
        self.dyntk_name = 'File'
        self.add_cascade(menu=self.Menu,underline=0, label='File')

class Menu_2(tk.Menu):

    def __init__(self,master,**kwargs):
        tk.Menu.__init__(self,master,**kwargs)
        self.config(activeforeground='black', activebackground='#7bfeff', fg='black', bg='white', tearoff=0, relief='solid')
        # widget definitions ===================================
        self.dyntk_name = 'command1'
        self.add_command(underline=0, label='command1')
        self.dyntk_name = 'command2'
        self.add_command(underline=0, label='command2')
        self.dyntk_name = 'command3'
        self.add_command(underline=0, label='command3')
        self.dyntk_name = 'command4'
        self.add_command(label='command4')
        self.dyntk_name = 'command5'
        self.add_command(label='command5')
        self.dyntk_name = 'separator'
        self.add_separator()
        self.dyntk_name = 'command6'
        self.add_command(label='command6')
        self.Menu = Menu_3(self,activeforeground='black', activebackground='#7bfeff', fg='black', bg='white', tearoff=0, relief='solid')
        self.dyntk_name = 'cascade'
        self.add_cascade(menu=self.Menu,underline=0, label='cascade')
        self.dyntk_name = 'separator_quit'
        self.add_separator()
        self.dyntk_name = 'command7'
        self.add_command(label='command7')

class Menu_3(tk.Menu):

    def __init__(self,master,**kwargs):
        tk.Menu.__init__(self,master,**kwargs)
        self.config(tearoff=0, relief='flat', bd = 0, activeborderwidth = 0)
        self.bind( '<Configure>', self.onFormEvent )
        self.bind( '<Unmap>', self.onUnmap)
        self.bind( '<Visibility>', self.onVisibility)
        self.x = 0
        self.y = 0

    def onFormEvent(self,event ):
        self.x = getattr( event, 'x')
        self.y = getattr( event, 'y')

    def onUnmap(self,event):
        self.menu_toplevel.destroy()

    def onVisibility(self,event):
        self.menu_toplevel = MenuToplevel(self)
        self.menu_toplevel.deiconify()
        self.menu_toplevel.geometry('+{}+{}'.format(self.x,self.y))


if __name__ == '__main__':
    Application().mainloop()
Aber das Problem ist: solange das Menü geöffnet ist, geht nichts Anderes. Und wie man das Menü schließt, weiß ich nicht. Außerdem wäre so etwas auch Menü unübliches Verhalten.

Man könnte es natürlich statt als sub sub Menü nur als sub Menü machen und die Cascade in einen Command umfunktionieren und diesesToplevel dann unter dem Command platzieren. Nur ich möchte nicht weiteren Platz in der Menüleiste verschwenden. Außerdem wo wäre die x-Koordinate des commands?

Und selber eine Art von ganzem Menü aus Buttons statt Commands und Cascaden zusammenzubauen, geht mir zu weit.
Antworten