Seite 1 von 1

Programm neustarten

Verfasst: Freitag 28. August 2009, 21:07
von Pascal
Hallo Leute

ich habe ein Programm, wo der Anwender nach verschiedenen Eingaben das Programm neustarten sollte.

Hier ein Beispiel:

Code: Alles auswählen

import Tkinter as tk
from random import random, sample


def entry_erstellen(e):
    feld = tk.Entry(win)
    feld.pack(padx=5)
    felder.append(feld)
    feld.insert('end', random())
    canvas.create_rectangle(sample(range(100), 4), fill='red')
    
def neu_starten1(e):
    canvas.delete('all')
    #entrys entfernen
    


win = tk.Tk()

felder = []

neustart = tk.Button(win, text='Neu starten')
neustart.pack(side='top', padx=10, pady=5)
tk.Widget.bind(neustart, '<1>', neu_starten1)

neu = tk.Button(win, text='Neues Feld')
neu.pack(padx=10, pady=5)
tk.Widget.bind(neu, '<1>', entry_erstellen)

canvas = tk.Canvas(win, width=100, height=100, bg='white')
canvas.pack(pady=20, padx=25)


win.mainloop()
Abgesehen von den Entrys funktioniert das ganz zufriedenstellend.

Allerdings finde ich das bei größeren Programmen nicht sinnvoll, alles "von Hand" zu löschen. Ich habe mir überlegt das ganze (also erstellen des Fenster usw.) als Prozedur zu machen:
(hab allerdings nur die Möglichkeit gefunden, das ganze als Klasse zu schreiben, da ich sonst ´´global`` einbringen müsste.

Code: Alles auswählen

import Tkinter as tk
from random import random, sample

class Test:

    def __init__(self):
        self.win = tk.Tk()
        self.felder = []
        neustart = tk.Button(self.win, text='Neu starten')
        neustart.pack(side='top', padx=10, pady=5)
        tk.Widget.bind(neustart, '<1>', self.neu_starten2)


        neu = tk.Button(self.win, text='Neues Feld')
        neu.pack(padx=10, pady=5)
        tk.Widget.bind(neu, '<1>', self.entry_erstellen)

        self.canvas = tk.Canvas(self.win, width=100, height=100, bg='white')
        self.canvas.pack(pady=20, padx=25)

        self.win.mainloop()


    def entry_erstellen(self, e):
        feld = tk.Entry(self.win)
        feld.pack(padx=5)
        self.felder.append(feld)
        feld.insert('end', random())
        self.canvas.create_rectangle(sample(range(100), 4), fill='red')
        
    def neu_starten1(self, e):
        self.canvas.delete('all')
        #entrys entfernen
        
    def neu_starten2(self, e):
        self.win.destroy()
        self.__init__()

Test()
Muss ich jetzt mein Programm als Klasse umschreiben?
(Wäre ... schade, da das Neustarten die letzte Funktion ist, die noch zu ergänzen wäre :roll: )

Kennt jemand noch eine andere Möglichkeit?

Verfasst: Freitag 28. August 2009, 21:13
von Pascal
das wäre übrigens die 'global-Variante':

Code: Alles auswählen

import Tkinter as tk
from random import random, sample

def neu_starten2(e):
    win.destroy()
    programm()

def entry_erstellen(e):
    feld = tk.Entry(win)
    feld.pack(padx=5)
    felder.append(feld)
    feld.insert('end', random())
    canvas.create_rectangle(sample(range(100), 4), fill='red')
    

def programm():


    global win
    win = tk.Tk()

    global felder
    felder = []


    neustart = tk.Button(win, text='Neu starten')
    neustart.pack(side='top', padx=10, pady=5)
    tk.Widget.bind(neustart, '<1>', neu_starten2)

    neu = tk.Button(win, text='Neues Feld')
    neu.pack(padx=10, pady=5)
    tk.Widget.bind(neu, '<1>', entry_erstellen)

    global canvas
    canvas = tk.Canvas(win, width=100, height=100, bg='white')
    canvas.pack(pady=20, padx=25)

    win.mainloop()


programm()

Verfasst: Freitag 28. August 2009, 21:52
von EyDu
Wenn du nicht auf Klassen umstellen willst: benutze lambda-Ausdrücke oder die Funktion "partial" aus [mod]functools[/mod].

Was du da machst ist allerdings sehr seltsam, was möchtest du denn erreichen? Ich vermute, dass du mal, dass du eigentlich ein Frame innerhalb des Fensters willst. Das kannst du dann löschen und so viele neue erstellen wie du möchtest. Alleine das mehrmals "mainloop" ausgeführt wird macht das Programm nicht besonders vertrauenswürdig.

Auch dein klassenbasierten Ansatz würde man so nicht schreiben. Die "__init__"-Methode aus einer anderen Methode aufzurufen ist sehr ungewöhnlich. Da sollte besser eine eigene Methode her.

Aber schön, dass du keine "global"s und keine *-Import mehr benutzt :-)

Verfasst: Samstag 29. August 2009, 06:02
von wuf
Hallo Pascal

Du könntest bei deinem ersten Skript die Entries bei einem Neustart auf folgende Art entfernen:

Code: Alles auswählen

def neu_starten1(e):
    canvas.delete('all')
    #entrys entfernen
    for feld in felder:
        feld.destroy()
Gruss wuf :wink:

Verfasst: Sonntag 30. August 2009, 10:39
von Pascal
Gibt es auch eine Methode zum Anzeigen sämtlicher Widget innerhalb eines Frames?

Denn dann wäre die Variante die wuf auch schon gezeigt hat meiner Meinung nach besser geeignet.

Verfasst: Sonntag 30. August 2009, 21:31
von wuf
Hallo Pascal
Pascal hat geschrieben:Gibt es auch eine Methode zum Anzeigen sämtlicher Widget innerhalb eines Frames?
Wie meinst du das genau. Du kannst sicher alle Widgets in einem Frame einbetten? Oder welche Widgets meinst du genau? Im folgenden Snippet platziere ich die Entries in einem Frame. Mit dem Neustart werden diese auch wieder aus dem Frame gelöscht und das Frame verkleinert.

Code: Alles auswählen

import Tkinter as tk
from random import random, sample


def entry_erstellen(e):

    feld = tk.Entry(frame)
    feld.pack(padx=5)
    felder.append(feld)
    feld.insert('end', random())
    canvas.create_rectangle(sample(range(100), 4), fill='red')

def neu_starten1(e):
    canvas.delete('all')
    #entrys entfernen
    for feld in felder:
        feld.destroy()
    frame.configure(height=1)

root = tk.Tk()

felder = []

neustart = tk.Button(root, text='Neu starten')
neustart.pack(side='top', padx=10, pady=5)
tk.Widget.bind(neustart, '<1>', neu_starten1)

neu = tk.Button(root, text='Neues Feld')
neu.pack(padx=10, pady=5)
tk.Widget.bind(neu, '<1>', entry_erstellen)

canvas = tk.Canvas(root, width=100, height=100, bg='white')
canvas.pack(pady=20, padx=25)

frame = tk.Frame(root, bg='green')
frame.pack()

root.mainloop()
Gruss wuf :wink: