Programm neustarten

Fragen zu Tkinter.
Antworten
Pascal
User
Beiträge: 271
Registriert: Samstag 4. April 2009, 22:18

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?
Pascal
User
Beiträge: 271
Registriert: Samstag 4. April 2009, 22:18

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()
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

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 :-)
Das Leben ist wie ein Tennisball.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

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:
Take it easy Mates!
Pascal
User
Beiträge: 271
Registriert: Samstag 4. April 2009, 22:18

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.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

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:
Take it easy Mates!
Antworten