Listboxen

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.
mosimfs
User
Beiträge: 28
Registriert: Sonntag 30. Juni 2019, 13:07

Guten Tag, bin Neueinsteiger hier.
Mein Programm, eine Art Fotobewertung für einen Club. Siehe Anhang.
Mein Problem, ich verwende viele Listboxen mit je einen Eintrag, die ich mit "grid" positioniere.
Nun, auf den letzten Eintrag bzw. die letzte Listbox kann ich zugreifen und auch auswerten, die Anderen kann ich zwar auch auswählen und sie werden auch blau markiert, da müsste ich wahrscheinlich vorher die jeweilige Listbox auswählen können.
Nur wie?
Sorry, Bild einfügen ist nicht so einfach auch das Listing feigelt. :wink:
bitte könnt ihr mir helfen!
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Eine Listbox mit nur einem Eintrag ist irgendwie unsinnig. Ich verstehe auch Dein Problem nicht. Was willst Du wie auswerten?
Listing kannst Du einfach mit Code-Tag </> hier direkt einfügen.
mosimfs
User
Beiträge: 28
Registriert: Sonntag 30. Juni 2019, 13:07

Danke vorerst für melde.
Abgesehen ob's Sinn macht, die Frage ist:
Kann man per Mausklick eine der Listboxen auswählen und den einen Eintrag auslesen? lg
mosimfs
User
Beiträge: 28
Registriert: Sonntag 30. Juni 2019, 13:07

zum Sinn vom Aufbau:
ich fand vorerst keine bessere Lösung die Einträge so fromatiert darzustellen und durch Auswahl den Eintrag auszulesen.
nochmal, wie wird hier ein Bild eingebunden?
nun der Teil meines Programm:

Code: Alles auswählen

  
    try:
        f = open(SO+datei, "r")
        x=0
        for Text in f:
            Text = Text.split(" | ")
            Text = str(Text[0])[0:2] + ". " + str(Text[0])[12:17] + " " + \
                   str(Text[1]) + "               "
            Text = Text[0:39]
            x+=1
            if a==0:
                Daten(x, Text) # Listbox erzeugen
                z = x
        if m == 1:
            Daten(z, Text)
        f.close()
        Eingang.config(text= Y+"-Eingänge ", bg="#fff")
        
        Anzeige.bind("<<ListboxSelect>>", Detail) # Eintrag abfragen
       
    except:
        Eingang.config(text= " keine Daten vorhanden ", bg="#fff")
        z=0
        
#----------------------------------------------------------------------------
        
def Daten(x, MEtext):
    global Anzeige
    
    Anzeige=Listbox(master=window, height=1, width=35, bd=2, font=("Courier", 13), relief=RAISED)
    Anzeige.insert(END, MEtext)
    if x <= 26:
        Anzeige.grid(column=0, row=x, columnspan=5, pady=3, padx=3, sticky=W)
    elif x > 26 and x <= 52:
        Anzeige.grid(column=5, row=x-26, columnspan=11, pady=3, padx=3, sticky=W)        
    elif x > 52 and x <= 78:
        Anzeige.grid(column=11, row=x-52, columnspan=16, pady=3, padx=3, sticky=W)        
    elif x > 78 and x <= 104:
        Anzeige.grid(column=17, row=x-78, columnspan=20, pady=3, padx=3, sticky=W)

#----------------------------------------------------------------------------
        
def Detail(event):
    print(Anzeige.get(Anzeige.curselection()))
    Button(master=window).grid_forget()
 
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Was sind denn `a`, `m` oder `Y` und was wird mit `z` gemacht? Einbuchstabige Variablennamen sind nie gut, vor allem, wenn sie noch global sind und aus dem Nichts kommen.
Schreibe Funktionen, benutze kein ›global‹ und benenne Deine Variablen aussagekräftig.
Wenn `a` null ist, dann macht die for-Schleife nichts und `z` wird nicht definiert, was dann zwei Zeilen später zu einem NameError führt, falls `m == 1`, was man aber nicht wissen kann, weil das auch aus dem Nichts kommt.
`Text` ist ein String und wird per `split` zu einer Liste von Strings, dem Du dann wieder den Wert eines Strings zuweist. Variablen sind nicht teuer, man muß sie nicht sofort recyclen.
Ein String per `str` nochmal in einen String umzuwandeln ist sinnlos.
Indexzugriffe vermeiden, und benutze Stringformatierung statt hier mit + zu arbeiten.
Keine nakten `except`, das macht es unmöglich, Programmierfehler zu finden. Wenn Du testen willst, ob die Datei lesbar ist, reicht ein IOError.

`Daten` ist keine Funktion. Funktionen werden nach Tätigkeiten benannt, vergiß dass es `global` gibt, hier willst Du eine Funktion schreiben, die als Rückgabewert die Listbox hat. Was soll `MEtext` bedeuten?
Die vier if-Blöcke unterscheiden sich nur durch column und row. Der Aufruf gehört also hinter die ifs und für column und row kannst Du Variablen benutzen.

Code: Alles auswählen

def create_listbox(window, number, content):
    display = tk.Listbox(master=window, height=1, width=35, bd=2, font=("Courier", 13), relief=tk.RAISED)
    display.insert(END, content)
    if number <= 26:
        column = 0
        row = number
    elif number <= 52:
        column = 5
        row = number - 26
    elif number <= 78:
        column = 11
        row = number - 52
    elif number <= 104:
        column = 5
        row = number - 78
    else:
        raise ValueError("number too large")
    display.grid(column=column, row=row, columnspan=20, pady=3, padx=3, sticky=tk.W)
    return display
Da Du nur EINE globale Variable `Anzeige` hast, kann `Detail` auch nur die letzte Listbox ansprechen. Was ist der Sinn, einen Knopf zu erzeugen, der explizit NICHT angezeigt wird?
mosimfs
User
Beiträge: 28
Registriert: Sonntag 30. Juni 2019, 13:07

Danke für deine Hilfe, es gibt allerdings auf diese Art keine Anzeige am Display, auch keine Fehlermeldung.
Soweit ich's erkenne, du hast 'grid' halt hinten angestellt.
Sag mir wie kann ich ein Foto das meinen Aufbau zeigt ins Forum stellen.
lg
Benutzeravatar
__blackjack__
User
Beiträge: 14044
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@mosimfs: Du kannst Bilder bei einem Hoster wie imgur.com hochladen und dann hier mit dem img-Tag in den Beitrag einbinden.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
mosimfs
User
Beiträge: 28
Registriert: Sonntag 30. Juni 2019, 13:07

nur kurz: Deine Ausführung funktioniert, weiß nicht warum jetzt. Auch die String's sind für die Katz.
Das Problem mit der Auswahl ist halt das gleiche geblieben. Stimmt, die Listboxen heißen alle Anzeige bzw. jetzt display.
Dennoch jede Listbox hat eine eigene .67967184 .67967744 .67967856 usw. da sollte es doch eine Möglichkeit der Auswahl geben, oder?
lg
mosimfs
User
Beiträge: 28
Registriert: Sonntag 30. Juni 2019, 13:07

Bild

ob's auf diese Art funktioniert :|
Benutzeravatar
__blackjack__
User
Beiträge: 14044
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@mosimfs: Das geht zwar sicherlich, ist aber der falsche Weg. Statt sich das hinterher irgendwie aus Tk wieder raus zu popeln, sollte man sich die Objekte in Python einfach merken. Zum Beispiel in dem man sie in eine Liste steckt.

Wobei die Listboxen nicht alle `Anzeige` oder `display` heissen, sondern immer nur *eine* davon heisst so. Denn sobald die nächste an den Namen gebunden wird, ist die davor ja eben nicht mehr an diesen Namen gebunden.

Vielleicht suchst Du aber auch `functools.partial()` um die jeweilige Listbox für den Aufruf einer Rückruffunktion beim `bind()` schon mal als Argument zu binden.

Edit: Für das img-Tag musst Du eine URL direkt zur Bilddatei haben, nicht eine URL zu einer Webseite in der das Bild angezeigt wird.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
mosimfs
User
Beiträge: 28
Registriert: Sonntag 30. Juni 2019, 13:07

auch vielen Dank für die Hilfe.
Die Einträge lese ich im Vorfeld aus den eingehenden Mail's der Mitglieder aus. Zum einen die Fotos die zur Bewertung gehen, zum anderen die Bewertungen und alles ladet in Dateien. Im nächsten Schritt geht's zur Auswertung. Den Listenaufbau verwende ich zum auswählen der Teilnehmer und Anzeigen der Bewertung. Das ganze läuft am Raspi rund um die Uhr, voll automatisch. Wenn's wahr ist?

PS. functools.partial() ?? des mit dem Bild einfügen is a nu spanisch.
mosimfs
User
Beiträge: 28
Registriert: Sonntag 30. Juni 2019, 13:07

nur so eine Überlegung,
ich könnte ja die Listboxen über einen Namen mit Index bezeichnen, aber was bringt's?
beim anklicken und auslesen (????.bind("<<ListboxSelect>>", Detail) bzw.(????.get(Anzeige.curselection()))
Wo und wie wird der Name (????) ausgelesen.
eine andere Frage: kann man so einen Beitrag im Forum verschieben oder umbenennen, vielleicht kennen eure Kollegen eine Lösung.
lg aus Scharnstein
mosimfs
User
Beiträge: 28
Registriert: Sonntag 30. Juni 2019, 13:07

und gleich noch ein mal,
im Detail(event), im (event) steht <tkinter.Event object at 0x0000000003CE30F0>
kann ich da was extrahieren?
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Du sollst Detail mit Hilfe von functools.partial (wenn Du nicht weißt, was das ist, kannst Du in der Hilfe nachlesen, oder in der Python-Dokumentation) die aktuelle Listbox übergeben. Ich denke, es wäre auch nicht schlecht, alle Listboxen in einer Liste zu sammeln, um später vielleicht alles Selections abzufragen.

Das ist die Lösung. Irgendwo in den Eingeweiden von Tkinter rumzuwühlen ist keine Lösung.
Benutzeravatar
__blackjack__
User
Beiträge: 14044
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wobei im `Event`-Objekt tatsächlich auch das `Widget` steckt das dieses Ereignis ausgelöst hat — als Attribut auf dem Python-Objekt.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
mosimfs
User
Beiträge: 28
Registriert: Sonntag 30. Juni 2019, 13:07

Wenn ich lästig sein darf, dieses functools.partial , wie kann ich's anwenden?
Und, dass müsste ja vor dem bind geschehen.
Die Tatsache das sich die Einträge anklicken lassen und sich auf Blau ändern, da muss doch eine Aktion laufen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hast du dir die Dokumentation mal angeschaut? https://docs.python.org/2/library/funct ... ls.partial

Da wird das erklaert. Und du kannst damit eben Zusaetzliche Argumente an den callback binden.
mosimfs
User
Beiträge: 28
Registriert: Sonntag 30. Juni 2019, 13:07

Danke, schaut vielversprechend aus!
Ob ich's umsetzen kann? Hmm
mosimfs
User
Beiträge: 28
Registriert: Sonntag 30. Juni 2019, 13:07

Hallo, ich komme nicht recht weiter.
`functools.partial()`, das verstehe ich nicht, kann's nicht einsetzen.
Ok, def Detail(event) lässt sich auslesen: event.widget.get (int(event.widget.curselection()[0])) und erspart mir den Listboxname Global zu setzen.
Daß, wiederum müsste noch auch mit "<<ListboxSelect>>",l funktionieren. zB. print("<<ListboxSelect>>", Detail)
gibt "<<ListboxSelect>> <function Detail at 0x0000000003D7EE18>" aus. Jetzt richtig extrahieren und einsetzen statt
Listboxname .bind("<<ListboxSelect>>", Detail). Wer kann es?

Nochmal zum Sinn der Ausführung: Am Raspi eine Benutzerfreundliche grafische Oberfläche gestallten, da geht kein Weg um Tkinter vorbei oder.
Eine Listbox und die Clubmitglieder per Scrollbar auswählen gefällt mir nicht.

Wäre schön wenn's brauchbare Ideen gib. :wink: lg
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was an functools.partial verstehst du nicht? Was hast du versucht? Es nunmal die Loesung fuer dein Problem.

Und natuerilch kannst du auch andere Toolkits wie Qt oder Kivy nutzen. Nur sind solche Probleme auch dort zu loesen, und die Mittel der Wahl sind die gleichen.
Antworten