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

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Antworten