Fenster nur einmal aufrufen und Zugriff von außen auf Funktionen

Fragen zu Tkinter.
Antworten
EtR
User
Beiträge: 6
Registriert: Montag 11. Dezember 2017, 22:41

Dienstag 12. Dezember 2017, 17:17

Hallo,

ich bin Anfänger in Python und habe 2 Probleme mit meinem Programm:
1. Wenn ich mehrfach auf den Button "zeige Fenster" drücke entstehen logischerweise mehrere "fenster1". Das möchte ich aber nicht haben. Es soll trotz mehrfachen Aufrufs nur eine Instanz entstehen, die dann mit dem Button "lösche Fenster" mit einem Klick geschlossen wird.

2. Ich möchte in einer anderen Funktion außerhalb von "fenster()" Signale abfragen und dann je nach Signal z.B. die Funktionen up() und down() ansteuern, um so an unterschiedliche Wert in der Listbox heranzukommen. Aber durch Funktionen außerhalb von "fenster()" kann ich ja nicht auf die inneren Funktionen (up(), down()) zugreifen. Ich habe nicht den geringsten Ansatz, wonach ich in Google suchen soll, um das Problem zu lösen.

Danke und Gruß
EtR

Code: Alles auswählen

import tkinter as tk

def fenster():
    def down():
        global aktive
        fenster1.see(aktive+1)
        aktive = (fenster1.curselection()[0])+1
        if aktive > (fenster1.size()-3): aktive = (fenster1.size()-3) # die letzten beiden Zeilen werden ausgeblendet
        fenster1.select_set(aktive)
        fenster1.select_clear(aktive-1)
    def up():
        global aktive
        fenster1.see(aktive-2)
        aktive = (fenster1.curselection()[0])-1
        if aktive < 1 : aktive = 1
        fenster1.select_set(aktive)
        fenster1.select_clear(aktive+1)
    def ende():
        b_up.destroy()
        b_down.destroy()
        fenster1.destroy()
        b_ende.destroy()
    
    b_ende = tk.Button(root, text='lösche Fenster', width=80, command=ende)
    b_ende.place(x = 95, y = 5, width=80, height=20) 
    b_up = tk.Button(root, text='up', width=80, command=up)
    b_up.place(x = 195, y = 5, width=80, height=20) 
    b_down = tk.Button(root, text='down', width=80, command=down)
    b_down.place(x = 295, y = 5, width=80, height=20) 
   
    
    fenster1 = tk.Listbox(root,selectmode='browse',height=15, width=100)
    fenster1.config(bg='lightgreen', font=('times', 10, 'italic'))
    fenster1.place(x = 30, y = 40, width=80, height=200)
    for i in range(0,10):
        fenster1.insert('end',str(i))
    fenster1.select_set(aktive)
    fenster1.see(aktive-2)

root = tk.Tk()
root.title("Test")
root.geometry("800x600")
root["bg"] = "Black"
aktive = 4
button1 = tk.Button(root, text='zeige Fenster', width=80, command=fenster)
button1.place(x = 5, y = 5, width=80, height=20) 

root.mainloop()

Sirius3
User
Beiträge: 8609
Registriert: Sonntag 21. Oktober 2012, 17:20

Dienstag 12. Dezember 2017, 18:20

@EtR: für GUI-Programmierung braucht man Objektorientierung. Vergiss dass es global gibt, oder dass man Funktionen in Funktionen definieren kann. Das Hauptfenster muß eine Klasse sein, und für fenster1 brauchst Du eine zweite. Dann mußt Du Dir im Hauptfenster nur merken, ob das fenster1 offen ist oder nicht. Vergiß auch, dass es `place` gibt. Damit kann man keine OBerflächen machen, die unter unterschiedlichen Systemen mit unterschiedlichen Auflösungen gut aussehen oder gar benutzbar sind (wie bei mir zum Beispiel).

Code: Alles auswählen

import tkinter as tk

class Fenster(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.active = 4
        tk.Button(self, text='up', command=self.move_up).grid(row=1, column=1)
        tk.Button(self, text='down', command=self.move_down).grid(row=1, column=2)
        self.listbox = tk.Listbox(self, selectmode='browse',
            bg='lightgreen', font=('times', 10, 'italic'))
        self.listbox.grid(row=2, column=1)
        for i in range(0,10):
            self.listbox.insert('end', i)
        self.listbox.select_set(self.active)
        self.listbox.see(self.active-2)

    def move_down(self):
        self.listbox.see(self.active + 1)
        self.active = min(self.listbox.curselection()[0] + 1, self.listbox.size() - 3)
        self.listbox.select_set(self.active)
        self.listbox.select_clear(self.active-1)

    def move_up(self):
        self.listbox.see(self.active - 2)
        self.active = max(self.listbox.curselection()[0] - 1, 1)
        self.listbox.select_set(self.active)
        self.listbox.select_clear(self.active+1)
   
class MainWin(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Test")
        self.fenster = None
        self.button = tk.Button(self, text='zeige Fenster', command=self.show_fenster)
        self.button.grid(row=1, column=1)

    def show_fenster(self):
        if self.fenster is None:
            self.button['text'] = 'lösche Fenster'
            self.fenster = Fenster(self)
            self.fenster.grid(row=2, column=1)
        else:
            self.button['text'] = 'zeige Fenster'
            self.fenster.destroy()
            self.fenster = None

def main():
    root = MainWin()
    root.mainloop()

if __name__ == '__main__':
    main()
EtR
User
Beiträge: 6
Registriert: Montag 11. Dezember 2017, 22:41

Dienstag 12. Dezember 2017, 19:55

Hallo Sirius3 ,
danke für Deine schnelle Antwort!!! Dieser Weg wird wohl zu meinen Ziel führen.
Vor der objektorientierten Programmierung habe ich mich bisher gefürchtet. Aber was muss, das muss!!!
Hast Du vielleicht einen guten Linke auf ein Tutorial für objektorientierten Programmierung :K

Gruß EtR
Antworten