Rechtsklick Menu

Fragen zu Tkinter.
Benutzeravatar
Fire Spike
User
Beiträge: 219
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Mittwoch 5. Februar 2020, 15:10

Hallo ich habe 2 Fragen:
  • Ich habe ein Entry.
    Wie kann ich jetzt machen das wenn ich mit rechts auf das Entry klicke ein Menu erscheint?
  • Ich habe ein Fenster in dem ich 3 verschiedene Diagramme anzeigen will. Da die sehr gross sind würde ich gerne die so scrollen dass immer nur eins sichtbar ist. Wie kann ich das machen?
    Ich zeige die Diagramme so an:

    Code: Alles auswählen

    canvas = FigureCanvasTkAgg(fig, master=self)
    canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
Ich hoffe ihr könnt mir helfen :wink:
Danke im Voraus :)
__deets__
User
Beiträge: 7633
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 5. Februar 2020, 15:19

Bezueglich des Rechtsklicks musst du mal in der Dokumentation nach Event-Binding suchen, da wird das dann erklaert.
Benutzeravatar
Fire Spike
User
Beiträge: 219
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Mittwoch 5. Februar 2020, 17:55

OK. :

Code: Alles auswählen

self.bind("<Button-3>", blabla)
Und wie mache ich das Menu?
__deets__
User
Beiträge: 7633
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 5. Februar 2020, 18:02

Indem du ein modales Fenster baust das du an der Stelle des Mauszeigers anzeigst. Und dann all die Sonderfaelle beachtest, wie zB was passiert wenn das Entry am Rande des Bildschirmes irgendwo ist, und das Menue irgendwo auftauchen wuerde, wo man es gar nicht mehr bedienen kann. Ein Start waere zB hier zu finden: https://stackoverflow.com/questions/120 ... ntext-menu
Benutzeravatar
Fire Spike
User
Beiträge: 219
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Freitag 7. Februar 2020, 18:11

Ich habe mal probiert das umzusetzen, aber ich scheitere an den Bindings, denn das vom root definiert auch das vom Menu.
Ich weiss nicht wieso das es nicht funktioniert.
Was mache ich falsch? :?:

So binde ich das Event:

Code: Alles auswählen

self.rklick = Rechtsklick(self)
binding = self.bind_all("<Button-1>", self.rklick.verstecken)
self.rklick.unbind(binding)
self.eingabe.bind("<Button-3>", self.rklick.popup)
So definiere ich das Rechtsklickmenu:

Code: Alles auswählen

class Rechtsklick():
    def __init__(self, master):
        self.master = master
        self.aMenu = tk.Menu(self.master, tearoff=0)
        self.aMenu.config(bg="white")
        self.aMenu.add_command(label="löschen", command=self.löschen)
        self.aMenu.add_command(label="Alles löschen", command=self.alles_löschen)

    def löschen(self):
        print("gelöscht")

    def alles_löschen(self):
        print("alles gelöscht")

    def popup(self, event):
        self.aMenu.post(event.x_root, event.y_root)
    
    def verstecken(self, event):
        self.aMenu.unpost()
    
    def unbind(self, binding):
        self.aMenu.unbind(binding)
Benutzeravatar
Fire Spike
User
Beiträge: 219
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Mittwoch 12. Februar 2020, 16:34

Könnt ihr mir bitte helfen?🙏🙏🙏
Wahrscheinlich habe ich genau eine Zeile zu wenig :oops:
__deets__
User
Beiträge: 7633
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 12. Februar 2020, 17:34

Dann bau bitte ein komplett lauffaehiges Beispiel, oder poste deinen gesamten Code (der natuerlich auch laeuffaehig sein muss).
Benutzeravatar
Fire Spike
User
Beiträge: 219
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Mittwoch 12. Februar 2020, 17:41

Mein ganzer Code hat 473 Zeilen, willst du den wirklich, oder soll ich ein Beispiel machen?
__deets__
User
Beiträge: 7633
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 12. Februar 2020, 18:01

Das Internet ist gross, 473 Zeilen Code passen da noch gerade so rein. Der entscheidende Punkt ist, dass es *funktionieren* muss, ohne das man da irgendwie dran rumfummeln muss (mit Ausnahme des Rechts-Klicks natuerlich). Wenn das nicht so ohne weiteres moeglich ist (weil du ZB auf GPIO eines PI zugreifst), dann bau ein Beispiel.
Benutzeravatar
Fire Spike
User
Beiträge: 219
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Mittwoch 12. Februar 2020, 21:33

Ein Beispiel weil der original Code Exceldateien braucht.

Code: Alles auswählen

import tkinter as tk

class Rechtsklick():
    def __init__(root, master):
        root.master = master
        root.aMenu = tk.Menu(root.master, tearoff=0)
        root.aMenu.config(bg="white")
        root.aMenu.add_command(label="löschen", command=root.löschen)
        root.aMenu.add_command(label="Alles löschen", command=root.alles_löschen)

    def löschen(root):
        print("gelöscht")

    def alles_löschen(root):
        print("alles gelöscht")

    def popup(root, event):
        root.aMenu.post(event.x_root, event.y_root)
    
    def verstecken(root, event):
        root.aMenu.unpost()
    
    def unbind(root, binding):
        root.aMenu.unbind(binding)
        
def main():
    root = tk.Tk()
    root.config(bg="white")
    rklick = Rechtsklick(root)
    binding = root.bind_all("<Button-1>", rklick.verstecken)
    rklick.unbind(binding)
    
    tk.Label(root, text="Name", fg="darkblue", bg="white", font=('arial', 15)).grid(row=0, column=0, sticky="w")
    root.name_eingabe = tk.Entry(root, bg="white", width=30, font=('arial', 13))
    root.name_eingabe.grid(row=1, column=0, sticky="w")
    root.name_eingabe.bind("<Button-3>", rklick.popup)
    
    tk.Label(root, text="Vorname", fg="darkblue", bg="white", font=('arial', 15)).grid(row=2, column=0, sticky="w")
    root.first_name_eingabe = tk.Entry(root, bg="white", width=30, font=('arial', 13))
    root.first_name_eingabe.grid(row=3, column=0, sticky="w")
    root.first_name_eingabe.bind("<Button-3>", rklick.popup)
    root.mainloop()
    
if __name__ == "__main__":
    main()
Es sind in Wirklichkeit viel mehr Eingabefelder darum das bind_all.
__deets__
User
Beiträge: 7633
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 12. Februar 2020, 21:57

Neben dem vergurkten root, das stattdessen ein self sein sollte, liegt das Problem in deinem rklick.unbind - damit entfernst du augenscheinlich das Binding fuer den Menueeintrag. So funktiontiert es fuer mich:

Code: Alles auswählen

import tkinter as tk

class Rechtsklick():
    def __init__(self, master):
        self.master = master
        self.aMenu = tk.Menu(master, tearoff=0)
        self.aMenu.config(bg="white")
        self.aMenu.add_command(label="löschen", command=self.löschen)
        self.aMenu.add_command(label="Alles löschen", command=self.alles_löschen)

    def löschen(self):
        print("gelöscht")

    def alles_löschen(self):
        print("alles gelöscht")

    def popup(self, event):
        self.aMenu.post(self.master.winfo_pointerx(), self.master.winfo_pointery())

    def verstecken(self, event):
        self.aMenu.unpost()

    def unbind(self, binding):
        self.aMenu.unbind(binding)


def main():
    root = tk.Tk()
    root.config(bg="white")
    rklick = Rechtsklick(root)
    #binding = root.bind_all("<Button-1>", rklick.verstecken)
    #rklick.unbind(binding)

    tk.Label(root, text="Name", fg="darkblue", bg="white", font=('arial', 15)).grid(row=0, column=0, sticky="w")
    root.name_eingabe = tk.Entry(root, bg="white", width=30, font=('arial', 13))
    root.name_eingabe.grid(row=1, column=0, sticky="w")
    root.name_eingabe.bind("<Button-3>", rklick.popup)

    tk.Label(root, text="Vorname", fg="darkblue", bg="white", font=('arial', 15)).grid(row=2, column=0, sticky="w")
    root.name_eingabe = tk.Entry(root, bg="white", width=30, font=('arial', 13))
    root.name_eingabe.grid(row=3, column=0, sticky="w")
    root.name_eingabe.bind("<Button-3>", rklick.popup)
    root.mainloop()

if __name__ == "__main__":
    main()
Benutzeravatar
Fire Spike
User
Beiträge: 219
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Donnerstag 13. Februar 2020, 16:50

so muss ich ja bei jedem Objekt

Code: Alles auswählen

bind("<Button-1>", self.rklick.verstecken)
hinzufügen und wie gesagt: das sind sehr viele :shock:
__deets__
User
Beiträge: 7633
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 13. Februar 2020, 16:56

Ich glaube eher das unbiding ist das Problem. Aber wenn es auf die eine Art geht, und auf die andere nicht - was willst du sonst machen?
Sirius3
User
Beiträge: 11539
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 13. Februar 2020, 17:01

@Fire Spike: wenn man etwas an sehr vielen Stellen im Code gleichartig ändern muß, dann ist das ein Zeichen dafür, dass man besser eine Funktion schreibt.
Benutzeravatar
Fire Spike
User
Beiträge: 219
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Donnerstag 13. Februar 2020, 17:09

wie würdest den du Entrys, Text, Button und Label mit einer Funktion diese Binding hinzufügen?
Antworten