Tkinter Buttons/Datein öffnen

Fragen zu Tkinter.
Antworten
Osterhase
User
Beiträge: 7
Registriert: Freitag 4. April 2014, 09:25

Hallo Liebes Python Forum,
Ich habe ein Prolem mit diesem Programm :oops:
Der benutzer soll erst die Möglichkeit haben zwischen Übersprinen und Foto Einfügen haben, falls er ein Foto einfügen möchte soll ein Fenster erscheinen wo er die Datei auswählen kann.
Vielen Dank für die Hilfe im voraus.
Fehermeldung habe ich unten drunter gestellt.

Code: Alles auswählen

from Tkinter import *

class App:
  def __init__(self, master):
    frame = Frame(master)
    frame.pack()
    self.button = Button(frame, 
                         text="ueberspringen", fg="red",
                         command=frame.ueberspringen)
    self.button.pack(side=LEFT)
    self.slogan = Button(frame,
                         text="Hello",
                         command=self.callback)
    self.slogan.pack(side=LEFT)
 # def oeffnen(self):
from tkFileDialog   import askopenfilename
def callback(self):      # Fehermeldung unten
    name= askopenfilename(0) 
    print name
    
errmsg = 'Error!'
Button(text='File Open', command=callback).pack(fill=X)
mainloop()
    

root = Tk()
app = App(root)
root.mainloop()


#Exception in Tkinter callback
#Traceback (most recent call last):
  #File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1413, in __call__
    #return self.func(*args)
#TypeError: callback() takes exactly 1 argument (0 given)
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@Osterhase: Die Funktion "callback" war früher mal eine Klassenmethode, deshalb das "self"-Argument. Du mußt Dich also entscheiden, ob Du die Klasse "App" verwenden willst, oder nicht, dann muß entweder "callback" wieder eine Klassenmethode werden, oder das "self" muß weg. Genauso schließen sich die Zeilen 21-23 oder Zeilen 26-28 gegenseitig aus.
BlackJack

@Osterhase: Ein paar Anmerkungen zum Quelltext:

Einrücktiefe ist vier Leerzeichen pro Ebene. In dem Zusammenhang lohnt sich vielleicht ein Blick in den Style Guide for Python Code.

Sternchen-Importe sollte man vermeiden. Damit holt man sich im Falle von `Tkinter` ungefähr 190 Namen ins Modul, von denen Du nur einen Bruchteil nutzt. Es wird aber schwerer nachzuvollziehen wo ein Name her kommt, wenn man Sternchen-Importe verwendet, und es besteht die Gefahr von Namenskollisionen. `Tkinter` wird üblicherweise beim Import in `tk` umbenannt.

Importe stehen üblicherweise am Anfang des Moduls, damit man leichter im Blick hat wovon ein Modul abhängt.

In Python 2 ist es empfehlenswert bei Klassen ohne Basisklasse von `object` zu erben um eine „new style”-Klasse zu erhalten. Sonst funktioniert mit der Klasse nicht alles was die Sprache an Möglichkeiten bietet.

Namen sollen dem Leser die Bedeutung eines Wertes im Programm vermitteln. So allgemeine Namen wie `button` oder `callback` tun das nicht wirklich, die sagen nur um was es sich handelt, aber nicht was die Schaltfläche oder die Rückruffunktion im Programm für eine Bedeutung haben. `slogan` ist zwar deutlich spezifischer, aber hinterlässt ein noch grösseres Fragezeichen warum eine Schaltfläche die zu einem „Datei öffnen”-Dialog führt *so* heisst‽

`Tkinter.Frame`-Objekte haben keine `ueberspringen()`-Methode. Wolltest Du da vielleicht Deinem `App`-Typ so eine Methode verpassen?

Was soll denn das Argument 0 bei `askopenfilename()` bewirken?

Auf Modulebene sollte kein Code stehen der nicht Konstanten, Funktionen, oder Klassen definiert. Das Hauptprogramm wird üblicherweise in eine Funktion mit dem Namen `main()` gesteckt und durch ein Idiom aufgerufen das verhintert, dass beim reinen Importieren des Moduls diese Funktion ausgeführt wird.

Ich wäre dann bei ungefähr so etwas hier:

Code: Alles auswählen

import Tkinter as tk
from tkFileDialog import askopenfilename


class App(object):
    def __init__(self, master):
        frame = tk.Frame(master)
        frame.pack()
        self.skip_button = tk.Button(
            frame, text='ueberspringen', fg='red', command=self.skip
        )
        self.skip_button.pack(side=tk.LEFT)
        self.select_filename_button = tk.Button(
            frame, text='oeffnen', command=self.select_filename
        )
        self.select_filename_button.pack(side=tk.LEFT)

    def skip(self):
        # 
        # TODO Implement this method.
        # 
        pass

    def select_filename(self):
        # 
        # TODO Do somtething here that makes it into a real method.
        # 
        name = askopenfilename()
        print name


def main():
    root = tk.Tk()
    _app = App(root)
    root.mainloop()


if __name__ == '__main__':
    main()
Osterhase
User
Beiträge: 7
Registriert: Freitag 4. April 2014, 09:25

Guten Morgen,
Leider habe ich immer noch eine Fehlermeldung und versteh nicht was diese zu bedueten hat :/
Ich brauche Hilfe :cry:

Code: Alles auswählen

import Tkinter as tk
from tkFileDialog import askopenfilename
     
     
class App(object):
    def __init__(self, master):
        frame = tk.Frame(master)
        frame.pack()
        self.skip_button = tk.Button(
        frame, text='ueberspringen', fg='red', command=self.skip
            )
        self.skip_button.pack(side=tk.LEFT)
        self.select_filename_button = tk.Button(
        frame, text='oeffnen', command=self.select_filename
            )
        self.select_filename_button.pack(side=tk.LEFT)
     
def skip(self):
 #
# TODO Implement this method.
 #
 pass
     
def select_filename(self):
    #
    # TODO Do somtething here that makes it into a real method.
    #
    name = askopenfilename()
    print name
     
     
def main():
    root = tk.Tk()
    _app = App(root)
    root.mainloop()
     
     
if __name__ == '__main__':
    main()


#Fehermeldung
#Traceback (most recent call last):
  #File "xy", line 39, in <module>
    #main()
  #File "xy", line 34, in main
    #_app = App(root)
  #File "xy", line 10, in __init__
    #frame, text='ueberspringen', fg='red', command=self.skip
#AttributeError: 'App' object has no attribute 'skip'

BlackJack

@Osterhase: Das bedeutet, dass die `App`-Objekte keine `skip()`-Methode haben. Einrückung ist ein wichtiger Bestandteil der Python-Syntax, die hat einfluss auf die *Bedeutung* des Quelltextes und ist nicht nur dazu da damit der menschliche Leser sich besser zurecht findet.

Vielleicht solltest Du mal ein Grundlagentutorial durcharbeiten. In der Python-Dokumentation ist eines und absoluten Anfängern wird oft Learn Python The Hard Way empfohlen. (Nicht vom Namen abschrecken lassen.)
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@Osterhase: Die Fehlermeldung sagt, dass das App-Objekt kein Attribut "skip" hat. Das kann verschiedene Ursachen haben. Entweder Du hast Dich verschrieben und meinst eigentlich, naja, ich sehe jetzt in Deinem Code eigentlich nichts, was Du stattdessen gemeint haben könntest. "skip_button" wird erst noch definiert und ist auch keine Methode, die als command-Argument erwartet wird. Auch sonst hat die Klasse keine Methoden. Dann bleibt noch die Möglichkeit, dass die Klasse das enthält, was Du denkst. Auf Modulebene gibt es nämlich eine Funktion "skip". Könnte es sein, dass das eigentlich eine Methode von "App" sein sollte?
Antworten