Seite 1 von 1

Popup - Tkinter Popup Widgets (z.B. für Context-Menüs)

Verfasst: Freitag 16. März 2007, 17:59
von Michael Schneider
Erstmal ein Hallo in die Runde!

Ich habe schon viele Programme und Codesegmente gesehen, wo die Tkinter popup-Methode für Context-Menüs verwendet wurde. Aber ich kenne kein Widget und keine wirklich einfache Methode, um schnell und unkompliziert ein Popup-Widget zu erzeugen.
Darum habe ich mir mal Gedanken gemacht, wie man die Erstellung so weit wie möglich vereinfachen kann und kam zu folgendem Ergebnis:

Code: Alles auswählen

##  -*- coding: iso-8859-1 -*-   ##

###################################
##  popup.py                     ##
##===============================##
##  Michael Schneider            ##
##  v1.0   - 16.03.2007          ##
###################################
import Tkinter as TI

class Popup:
    "Erzeugt mit wenig Aufwand ein einfaches Popup-Menu"
    def __init__(self, root, items, trigger="<3>", preselect=-1):
        """Parameter:
        root       - Widget, auf dem das Popup erscheinen soll
        
        items      - Liste oder Tupel mit Elementen, die die Einträge
                     und Callbackfunktionen repräsentieren.

                     Mögliche Elementtypen sind Tupel, Listen und Dictionaries.
                         Tupel: '(' [Aufschrift, [Callbackfunktion]] ')'   !!!Komma beachten!!!
                         Liste: '[' [Aufschrift [, Callbackfunktion]] ']'
                         Dict:  '{' [Aufschrift ':' Callbackfunktion] '}'

                     => Sind zwei Parameter angegeben, wird der erste als Aufschrift, der zweite
                         als Callback interpretiert.
                     => Wird die Callbackfunktion ausgelassen, wird nur die Aufschrift gezeigt.
                     => Werden keine Parameter übergeben, wird ein Separator eingesetzt.

        trigger      - der Tkinter-Event, der das Popup-Fenster aufruft, Default ist Rechtsklick

        preselect    - der initial ausgewählte Eintrag, Default ist -1 = popup erscheint
                         unterhalb rechts der aktuellen Mausposition
        """
        self.wMaster = root
        self.lItems = items
        self.sTrigger = trigger
        self.iPreselect = preselect
        root.bind(trigger, self)

    def __call__(self, Event):
        """Eventfunktion, die das Popup erzeugt."""
        wPopup = TI.Menu(self.wMaster, tearoff=False)
        self.create_menu(wPopup, self.lItems)
        try:
            if self.iPreselect < 0:
                wPopup.tk_popup(Event.x_root, Event.y_root)
            else:
                wPopup.tk_popup(Event.x_root, Event.y_root, self.iPreselect)
        finally:
            wPopup.grab_release()

    def create_menu(self, wPopup, lItems):
        """Analysiert die Liste der Einträge und setzt die Parameter."""
        import types
        for Item in lItems:
            if type(Item) in (types.TupleType, types.ListType):
                Command = None
                if len(Item) is 0: sLabel = ""
                if len(Item) >= 2: Command = Item[1]
                else: Command = None
                if len(Item) >= 1: sLabel = Item[0]
                self.add_menu_item(wPopup, sLabel, Command)

            if type(Item) is types.DictType:
                if Item: sLabel, Command = Item.items()[0]
                else: sLabel, Command = "", None    ##  leeres Dictionary -> Separator
                self.add_menu_item(wPopup, sLabel, Command)

    def add_menu_item(self, wPopup, sLabel, Command):
        """Erzeugt die Einträge anhand der Parameter."""
        if sLabel: wPopup.add_command(label=sLabel, command=Command)
        else: wPopup.add_separator()

if __name__=="__main__":
    def print_ok():
        print "okay gewaehlt"

    tk = TI.Tk()
    TI.Label(tk, text="Rechtsklick: langes Testmenu ; Linksklick: kurzes Testmenu").grid(padx=20, pady=10)

    ###################################################
    ##  Zwei Beispiele
    Popup(tk, ({"Ok": print_ok},
               {},
               ["nix passiert"],
               {"hier auch nicht":None},
               (),
               ("Ende", tk.destroy)))
    Popup(tk, [["Ende", tk.destroy]], trigger="<1>", preselect=0)
    tk.mainloop()
Ich denke, der Code ist nicht zu Umfangreich und die Methoden gut dokumentiert. Wäre schön, wenn ihr eure Meinung zur Brauchbarkeit und evtl. Verbesserungsvorschläge posten würdet.

Viele Grüße,
der Michel