Seite 1 von 1

Datenaustausch zwischen 2 Windows

Verfasst: Samstag 18. Dezember 2021, 15:36
von sc19
Hallo,
ich bin neu auf diesem Forum und habe eine Frage die mich seit Tagen beschäftigt.
Ich habe zu Übungszwecken zwei Windows (Fenster), erstellt, das zweite Windows wird als Modul "textbetrachter" von 1. Windows (MainWindow) aufgerufen.
Soweit alles gut, das zweite Window wird über eine Tastenkombination "self.bind("<Control-s>",self.win2)" aufgerufen und das funktioniert auch wie gesagt.
Mein Problem ist, dass vor dem Aufruf folgende Variable erstellte "self.liste = frame_01.config()" und diese Variable (Werte) an das 2. Window übergeben möchte um damit dort weiterarbeiten zu können. Genau an der Stelle mache ich eben einen Programmierfehler.
Die Fehlermeldung lautet:

print(self.win.liste)
AttributeError: 'Toplevel' object has no attribute 'liste'

Hier mal das von mir gebastelte Programm:

Code: Alles auswählen

import tkinter as tk
from tkinter import ttk
import textbetrachter

class MainWindow(tk.Tk):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.title("Lektion: Frame-Widget")

        frame_01 = tk.Frame(self, bg="red", width=600, height=200)
        frame_01.grid(column=0, row=0, padx=5, pady=5, sticky="w")

        frame_01a = tk.LabelFrame(frame_01, text="Rahmen 1:", bg="gray", width=330, height=190)
        frame_01a.grid(column=0, row=0, padx=5, pady=5)

        frame_01b = tk.LabelFrame(frame_01, text="Rahmen 2:", bg="lightgray", width=330, height=190)
        frame_01b.grid(column=2, row=0, padx=(0,5), pady=5)

        self.liste  = frame_01.config()

        self.bind("<Control-s>",self.win2)

    def win2(self, event):
        self.mein_textbetrachter = textbetrachter.Textbetrachter()
        #self.mein_textbetrachter.win.liste
        self.mein_textbetrachter.win.mainloop()


root = MainWindow()
root.mainloop()
Und das ist das Modul "textbetrachter" (gespeichert als textbetrachter.py):

Code: Alles auswählen

import tkinter as tk
from tkinter import ttk

class Textbetrachter():
    def __init__(self):
        self.win = tk.Toplevel()
        self.win.title("Textbetrachter")
        self.win.resizable(False, False)

        frame_02 = tk.Frame(self.win, bg="green")
        frame_02.grid(column=0, row=0, padx=5, pady=5)

        texteditor = tk.Text(frame_02, bg="lightyellow", height=20)
        texteditor.grid(column=0, row=0, padx=5, pady=5)

        text_scroller = tk.Scrollbar(frame_02, orient="vertical", command=texteditor.yview)
        text_scroller.grid(column=1, row=0, sticky="ns")


        print(self.win.liste)

        for item in self.win.liste.config():
               texteditor.insert(tk.INSERT, (item, ":", self.win.liste[item], "\n"))
Also hier im zweiten Window möchte ich mit der Variablen "liste" weiterarbeiten, aber das funktioniert eben leider nicht. Es würde mich sehr freuen, wenn mir Jemand hierbei weiterhelfen könnte.

Liebe Grüße
sc19

Re: Datenaustausch zwischen 2 Windows

Verfasst: Sonntag 19. Dezember 2021, 13:25
von Sirius3
Wie auch bei einfachen Funktionen auch, wenn Du etwas in einer anderen Klasse verwenden willst, dann mußt Du es als Argument an __init__ übergeben.
Es darf nur ein `mainloop` im ganzen Programm geben, weitere Aufrufe machen keinen Sinn.
Anhängsel wie mein_ bieten keinen Mehrwert und können weg. Warum nennst Du ein Wörterbuch `liste`?

Code: Alles auswählen

import tkinter as tk

class Textbetrachter(tk.Toplevel):
    def __init__(self, liste):
        tk.Toplevel.__init__(self)
        self.liste = liste
        self.title("Textbetrachter")
        self.resizable(False, False)

        frame_02 = tk.Frame(self, bg="green")
        frame_02.grid(column=0, row=0, padx=5, pady=5)

        texteditor = tk.Text(frame_02, bg="lightyellow", height=20)
        texteditor.grid(column=0, row=0, padx=5, pady=5)

        text_scroller = tk.Scrollbar(frame_02, orient="vertical", command=texteditor.yview)
        text_scroller.grid(column=1, row=0, sticky="ns")

        print(self.liste)
        for item, value in self.liste.items():
            texteditor.insert(tk.INSERT, (item, ":", value, "\n"))

class MainWindow(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.title("Lektion: Frame-Widget")

        frame_01 = tk.Frame(self, bg="red", width=600, height=200)
        frame_01.grid(column=0, row=0, padx=5, pady=5, sticky="w")

        frame_01a = tk.LabelFrame(frame_01, text="Rahmen 1:", bg="gray", width=330, height=190)
        frame_01a.grid(column=0, row=0, padx=5, pady=5)

        frame_01b = tk.LabelFrame(frame_01, text="Rahmen 2:", bg="lightgray", width=330, height=190)
        frame_01b.grid(column=2, row=0, padx=(0,5), pady=5)

        self.liste  = frame_01.config()
        self.bind("<Control-s>", self.open_textbetrachter)

    def open_textbetrachter(self, event):
        self.textbetrachter = Textbetrachter(self.liste)

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

if __name__ == "__main__":
    main()

Re: Datenaustausch zwischen 2 Windows

Verfasst: Sonntag 19. Dezember 2021, 14:52
von sc19
Hallo,
erst einmal danke für Deine Bemühungen und für die schnelle Antwort.
Ich habe den Code , den Du freundlicherweise korrigiert hast ausprobiert und es funktioniert wie erwartet.
Du hast jedoch aus das Modul "textbetrachter" herausgenommen und hast es in ein Programmcode gepackt.
Das aber war u.a. wichtig für mich, da ich damit auch das Einbinden von selbsterstellten Modulen üben wollte.

Ich habe das nochmals anhand deines Programmcodes umgeschrieben und erhalte folgende Fehlermeldung beim Ausführen:
self.mein_textbetrachter = textbetrachter(self)
NameError: name 'textbetrachter' is not defined


Dann habe ich auch noch folgende Frage(n):
Ist "tk.Toplevel.__init__(self)" nicht das selbe wie "super.__init__(self)"?

Code: Alles auswählen

class Textbetrachter(tk.Toplevel):
    def __init__(self, liste):
        tk.Toplevel.__init__(self
Genauso auch hier:

Code: Alles auswählen

class MainWindow(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
ist das nicht das selbe?

Code: Alles auswählen

tk.Tk.__init__(self)
super(MainWindow, self).__init__()
Du schreibst:
Es darf nur ein `mainloop` im ganzen Programm geben, weitere Aufrufe machen keinen Sinn.
Anhängsel wie mein_ bieten keinen Mehrwert und können weg.
Ich vermute mal, dass Du damit die Trennung der beiden Klassen meinst, also das ich aus der Klasse Textbetrachter einen Modul erstellt habe und diesen über die Klasse MainWindow importiere, oder?

Re: Datenaustausch zwischen 2 Windows

Verfasst: Sonntag 19. Dezember 2021, 15:16
von __deets__
Gross- und Kleinschreibung sind wichtig in Python. Textbetrachter ist etwas anderes als textbetrachter. super() ruft *alle* potentiellen Elternklassen auf. Es ist also nicht dasselbe, kommt aber oft aufs gleiche raus.

Und was den mainloop angeht: nein, das meint Sirius3 nicht. Sondern sprichwörtlich was er gesagt hat. Dein Programm darf genau einen mainloop Aufruf enthalten. Denn ab da wandert die Kontrolle ab ins GUI-Rahmenwerk. Das geht sinnvoll nur einmal.

Re: Datenaustausch zwischen 2 Windows

Verfasst: Sonntag 19. Dezember 2021, 15:48
von sc19
Hallo und Danke vorab für Dein Kommentar. Jedoch wäre etwas mehr Kontext hilfreich.
Ist "tk.Toplevel.__init__(self)" nicht das selbe wie "super.__init__(self)"?
Ich verstehe Deinen Hinweis mit der Gross- und Kleinschreibunn im Zusammenhang mit meiner obigen Frage nicht.

Du schreibst:
Dein Programm darf genau einen mainloop Aufruf enthalten.
Aber ich habe doch auch nur einen mainloop, wo in meinem Code ist ein weiterer Aufruf.
Wäre sehr hilfreich, damit ich dass auch nachvollziehen kann.

Re: Datenaustausch zwischen 2 Windows

Verfasst: Sonntag 19. Dezember 2021, 15:50
von __deets__
Schau dir mal deinen Code an, und deine Fehlermeldung. Dann sollte der Hinweis zur Schreibweise hoffentlich klar werden.

Und nein, du hast nicht nur einen mainloop Aufruf. Bemüh mal die Textsuchfunktion in deinem Editor.

Zur Funktion super() gibt es die offizielle Dokumentation: https://docs.python.org/3/library/functions.html