Listbox aus externer Funktion füllen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Frankie_MUC
User
Beiträge: 3
Registriert: Donnerstag 11. Juli 2019, 18:47

Hallo zusammen,
ich bin Neu beim Thema Python und finde die Sprache einfach top.
Natürlich stößt man als Anfänger auf ein paar Hindernisse :geek:
Ok, jetzt zu meinem Problem, bei dem ich einfach nicht weiter komme:

Ich habe eine GUI und rufe über einen Button eine Funktion (def) in einer anderen Datei auf. Nun möchte ich (ist nur ein Test für eine andere Idee), einen String zurückgeben und in die Listbox der GUI eintragen (insert).
Komme hier nicht weiter...

Hier die GUI...

Code: Alles auswählen

import tkinter
from empfangen import *


class MyApp(tkinter.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.pack()
        self.createWidgets()
    def createWidgets(self):
        self.nameEntry = tkinter.Entry(self)
        self.nameEntry.pack(padx=10, pady=10)
        self.name = tkinter.StringVar()
        self.name.set("Ihr Name...")
        self.nameEntry["textvariable"] = self.name
        self.ok = tkinter.Button(self)
        self.ok["text"] = "Ok"
        self.ok["command"] = self.quit
        self.ok.pack(side="right")
        self.rev = tkinter.Button(self)
        self.rev["text"] = "Umdrehen"
        self.rev["command"] = self.onReverse
        self.rev.pack(side="right", padx=10, pady=10)
        self.empf = tkinter.Button(self)
        self.empf["text"] = "senden/empfangen"
        self.empf["command"] = self.senden
        self.empf.pack(side="right")
    def onReverse(self):
        self.name.set(self.name.get()[::-1])
    def senden(self):
        testtext = self.nameEntry.get()
        empfang(testtext)

root = tkinter.Tk()
app = MyApp(root)
app.mainloop()

Hier die andere Datei...

Code: Alles auswählen

def empfang(txt):
    print(txt)
    MyApp().nameEntry.set("Hallo")
Wahrscheinlich ganz einfach, ich komme aber einfach nicht darauf.

Viele Grüße
Frankie
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

`MyApp()` erzeugt eine neue Instanz, die nichts mit dem zu tun hat, was Du in Deiner Hauptdatei erzeugt hast.
`empfang` braucht ein weiteres Argument (app), das Du beim Aufrufen als `self` übergeben mußt.

*-Importe sind auch bei selbst geschriebenen Modulen schlecht. Frames sollten sich nicht selbst positionieren. Das `pack` solltest Du aus `__init__` in Dein Hauptprogramm verschieben.
Frankie_MUC
User
Beiträge: 3
Registriert: Donnerstag 11. Juli 2019, 18:47

Hallo Sirius3,

2 Tage habe ich an der Antwort jetzt vertrödelt und dann war es so einfach. Das war der richtige Anstoß :D

Folgendes habe ich geändert und schon funktioniert es:

Dem empfang das self mitgegeben und das pack() vor das mainloop() gesetzt.

Code: Alles auswählen

    def senden(self):
        testtext = self.nameEntry.get()
        empfang(self, testtext)

root = tkinter.Tk()
app = MyApp(root)
app.pack()
app.mainloop()
In der externen Datei dann noch

Code: Alles auswählen

app.nameEntry.insert(0, "Hallo")
Ja, manchmal braucht es nur einen Anstoß.

Sage schon einmal vielen Dank.

Grüße
Frankie
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das es geht ist schön. Aber so macht man das nicht. Empfang sollte was auch immer dann im Textfeld stehen sollte einfach zurück geben. Und in der GUI stopfst du das dann zusammen. Sonst koppelst du deine Code aneinander und bekommst Schwierigkeiten wenn du zb die Struktur der GUI änderst. Und plötzlich musst du allen möglichen Code anfassen.
Frankie_MUC
User
Beiträge: 3
Registriert: Donnerstag 11. Juli 2019, 18:47

Ok. das werde ich noch ändern.
Übergebe es an eine Variable und diese werde ich dann dem Entry übergeben (in der Datei mit der app).

Denke so hast Du es gemeint.

Grüße
Frankie
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Klingt gut, ja.
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Frankie_MUC: Noch ein paar Anmerkungen zur Klasse im ersten Beitrag:

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). Also beispielsweise `on_reverse()` statt `onReverse()`.

Das `My` bei `MyApp` ist sinnlos. Wessen Anwendung soll das denn sonst sein? Wenn es nicht auch `YourApp` oder etwas ähnliches gibt, von dem man diese Klasse abgrenzen muss, ist so ein „my“ als Vorsilbe absolut sinnfrei.

Das erstellen der Widgets in eine eigene Methode heraus zu ziehen, so dass in der `__init__()` im Grunde nur dieser Aufruf steht, macht keinen Sinn.

Du gibst nie Tk-Optionen beim erstellen von Widgets an, sondern änderst die erst alle nachträglich – warum so umständlich?

Es wird da wirklich fast alles an das `App`-Objekt gebunden obwohl nur `self.name` tatsächlich verwendet wird. Man könnte sich dann auch die Abkürzungen bei den Namen sparen, weil man sich die Namen an sich komplett sparen kann.

Die Werte für die Seiten für `pack()` gibt es als Konstanten im `tkinter`-Modul um Tippfehler zu vermeiden und dem Leser zu zeigen, das man da nicht irgendwelche Werte angeben kann.

Du mischt im gleichen Containerwidget die Richtung/Seite bei `pack()`. Das kann das Ergebnis haben was Du sehen möchtest, das kann aber auch ganz anders interpretiert werden. Die Schaltflächen sollten in einem eigenen `Frame` angeordnet werden.

Die Hauptschleife kann man letztlich auf jedem `Widget` aufrufen, aber üblicherweise macht man das auf dem `Tk`-Exemplar.

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk

from empfangen import empfang


class App(tk.Frame):
    
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        self.name = tk.StringVar(value='Ihr Name…')
        tk.Entry(self, textvariable=self.name).pack(padx=10, pady=10)
        
        frame = tk.Frame(self)
        tk.Button(frame, text='Ok', command=self.quit).pack(side=tk.RIGHT)
        tk.Button(
            frame, text='Umdrehen', command=self.on_reverse
        ).pack(side=tk.RIGHT, padx=10, pady=10)
        tk.Button(
            frame, text='Senden/Empfangen', command=self.senden
        ).pack(side=tk.RIGHT)
        frame.pack()
    
    def on_reverse(self):
        self.name.set(self.name.get()[::-1])
    
    def senden(self):
        empfang(self.name.get())


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


if __name__ == '__main__':
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten