Menu, Auswahl wird schon bei Initialisierung ausgeführt

Fragen zu Tkinter.
Antworten
pyzip
User
Beiträge: 89
Registriert: Freitag 16. Juni 2017, 19:36

Hallo, arbeite an einem Eingabefenster, das ein Menu, ein Label und ein Text-Widget mit Scrollbars enthalten soll. Nachdem ich das Text-Widget mit viel Mühe hinbekommen habe, komme ich nun mit dem Menu nicht klar. Es ist aus einem Tutorial und führt zu meiner Überraschung "command=" sofort aus. Erst wenn alle Menupunkte durch sind, kommt mein eigentliches Fenster und die Menupunkte haben keine Funktion mehr. Was verstehe ich dabei nicht? Ich hoffe auf Hilfe (wie immer...)
Danke und hier ist mein Programm:

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Oct 16 16:50:22 2018

@author: pyzip
"""

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import tkinter as tk
from tkinter import messagebox, simpledialog, filedialog
 
class Diagramm(tk.Frame):
   
    def __init__(self, master):
        super().__init__(master)
        self.master = master

        self.menu = tk.Menu(self.master)
        self.master.config(menu=self.menu)
        self.filemenu = tk.Menu(self.menu)
        self.menu.add_cascade(label="File", menu=self.filemenu)
        self.filemenu.add_command(label="New", command=self.ask_new_filename())
        self.filemenu.add_command(label="Open...", command=self.choose_file())
        self.filemenu.add_separator()
        self.filemenu.add_command(label="Exit", command=self.master.quit)
        
        self.helpmenu = tk.Menu(self.menu)
        self.menu.add_cascade(label="Help", menu=self.helpmenu)
        self.helpmenu.add_command(label="About...", command=self.about())

        self.frame_l = tk.Frame(self.master, bg="yellow")
        self.frame_l.pack(fill=tk.BOTH,expand=True,padx=2,pady=2)

        self.frame_e = tk.Frame(self.master, bg="green",padx=2,pady=2)
        self.frame_e.grid_rowconfigure(0, weight=1)
        self.frame_e.grid_columnconfigure(0, weight=1)
        
        self.xscrollbar = tk.Scrollbar(self.frame_e, orient=tk.HORIZONTAL)
        self.xscrollbar.grid(row=1, column=0, sticky=tk.EW)
        
        self.yscrollbar = tk.Scrollbar(self.frame_e)
        self.yscrollbar.grid(row=0, column=1, sticky=tk.NS)
        
        self.text = tk.Text(self.frame_e, wrap=tk.NONE, bd=0,
                    xscrollcommand=self.xscrollbar.set,
                    yscrollcommand=self.yscrollbar.set)
        
        self.text.grid(row=0, column=0, sticky=tk.NSEW)
        
        self.xscrollbar.config(command=self.text.xview)
        self.yscrollbar.config(command=self.text.yview)

        self.frame_e.pack(padx=50,pady=2)
           
        self.labelText = tk.StringVar()
        self.labelText.set("Direkteigabe")

        self.w = tk.Label(self.frame_l, bg="red", textvariable=self.labelText)
        self.w.pack()
        
        ausgabe = "Hier steht Text..."
        self.text.insert(tk.END, ausgabe)

        
    def choose_file(self):
        self.file = filedialog.askopenfilename(filetypes = 
                    (("Text files","*.txt"),("all files","*.*")))
        return self.file
    
    def schliessen(self, master):
        antwort = messagebox.askyesno(
            'Schließen?',
            'Soll das Programm geschlossen werden?'
            ' Ggf. nicht gespeicherte Daten können verloren gehen!'
        )
        if antwort:
            master.quit()
     
    
    def about(self):
        messagebox.showinfo('Über', 'blabla')
     
     
    def ask_new_filename(self):
        filename_name = simpledialog.askstring(
            'Filename', 'Name ?'
        )
        if filename_name:
            new_filename = filename_name
            print("new_filename = ", new_filename)
            self.labelText.set(new_filename + "   "  + "Editor")

def main():
    
    title = "Eingabe"
    root = tk.Tk()
    root.title(title)

    w=800
    h=500
    ws=root.winfo_screenwidth()
    hs=root.winfo_screenheight()
    x=(ws/2)-(w/2)
    y=(hs/2)-(h/2)
    root.geometry('%dx%d+%d+%d'%(w,h,x,y))   
    
    dia = Diagramm(root)
    dia.pack()
    
     
    root.mainloop()


if __name__ == '__main__':
    main()
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@pyzip: Dass das sofort ausgeführt wird, sollte Dich aber nicht überraschen, denn Du hast das ja genau so im Code verlangt. Aufrufe und Argumente, bzw. deren Auswertung funktionieren in Python immer gleich. Erst werden die Argumente ausgewertet und dann wird eine Funktion oder Methode mit den ausgewerteten Argumenten aufgerufen. Das es sich um Tkinter handelt und das Argument `command` heisst, ändert daran nichts. `command` erwartet eine Rückruffunktion oder -methode als Argument. Du übergibst aber nicht die Methoden sondern rufst sie auf und übergibst deren Rückgabewert. Der 'Exit'-Menüpunkt funktioniert ja wie er soll. Vergleich mal was Du da nicht machst, im Gegensatz zu denen die nicht so funktionieren wie Du erwartet hast.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
pyzip
User
Beiträge: 89
Registriert: Freitag 16. Juni 2017, 19:36

@__blackjack__: Danke für die rasche Antwort! Bin nicht sicher, dass ich das richtig verstanden habe. Habe jetzt versuchsweise die Funktionen fürs Menu vor die Menu-Def. in gleicher Ebene geschoben und jetzt geht es!
Also

Code: Alles auswählen

 
class Diagramm(tk.Frame):
   
    def __init__(self, master):
        super().__init__(master)
        self.master = master
        def hello():
            print("hello!")
        
        def choose_file():
            file = filedialog.askopenfilename(filetypes = 
                        (("Text files","*.txt"),("all files","*.*")))
            print(file)
            return file
        
        self.menu = tk.Menu(self.master)
        self.master.config(menu=self.menu)
        self.filemenu = tk.Menu(self.menu)
        self.menu.add_cascade(label="File", menu=self.filemenu)
        self.filemenu.add_command(label="New", command=hello)
        self.filemenu.add_command(label="Open...", command=choose_file)
       
Habe mich an den "Buttons", die ich bisher genutzt habe, orientiert und dort wird der doch z.b mit einem "command=self.save" initialisiert, wobei "safe" eine Funktion der Klasse ist. Dachte also, dass der "Command" bei Menus auch erst ausgeführt wird, wenn der Menu-Eintrag angeklickt wird.
Ich hoffe, ich habe mich verständlich ausgedrückt. Habe trotzdem das Gefühl, dass ich noch nicht genau verstanden habe, was ich da gemacht habe.
Gruß pyzip
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Du hast nicht nur (unsinnigerweise) die Funktionen verschoben, sondern auch noch etwas anderes geändert. Was ist das?

Was bewirkt der Rückgabewert von `choose_file`?
pyzip
User
Beiträge: 89
Registriert: Freitag 16. Juni 2017, 19:36

Sorry, hat etwas gedauert...habe übersehen, dass "self.choose_file()" keine Methode ist. Es muß heissen "self.choose_file". Dann ist die Verschiebung natürlich überflüssig! Und der Rückgabewert von `choose_file` scheint mir auch sinnlos, da der Filename ja eh schon zugewiesen ist.
Also vielen Dank erst einmal und "gut's Nächtle", pyzip
Antworten