Listbox liefert tupel zurück, ist aber bei erster Selektion leer

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
bigbonzo
User
Beiträge: 21
Registriert: Samstag 30. November 2019, 10:23

Hallo, mehr schlecht als recht habe ich bereits ein paar Python Programme erstellt, aber hier komme ich auch nach langem Suchen nicht weiter. Die Antwort ist bestimmt ganz einfach.
Ich habe eine tkinter Listbox gefüllt, nach Selektion mache ich dann mit foto = Image.open(lb.get(lb.curselection()[0])) weiter. Das funktioniert auch gut, nur nicht nach erster Selektion, da passiert nichts, das zurück gelieferte Tupel ist leer. Erst nach der zweiten Selektion, aber dann auch beständig, wird das Tupel erwartungsgemäß zurück geliefert und mein Programm läuft weiter.

Also wie kann man das Problem bei ersten Selektion mit dem leeren Tupel umgehen ???

Vielen Dank.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Wie sieht den dein Code aus?
bigbonzo
User
Beiträge: 21
Registriert: Samstag 30. November 2019, 10:23

auch hier mein Dank. Die Listbox heißt lb
foto = lb.get(lb.curselection()[0])

Das Tupel: libo = lb.curselection()

1. Selektion libo= ()
2. Selektion libo= (0,)
3. Selektion libo= (1,)
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Ohne ein lauffähiges Minimalbeispiel, das den Fehler zeigt, kann man da wenig sagen.
bigbonzo
User
Beiträge: 21
Registriert: Samstag 30. November 2019, 10:23

Ich habe den Code auf das Problem reduziert. Das Programm sucht Bilder in einem Standard Windows Verzeichnis, ggf. ändern.
Erkannte Fehler:
# erst beim zweiten Klick wird ein Bild angezeigt, da erst Tupel leer
# Bilder werden im Ausgabe Frame nicht ausgetauscht, sondern dazu gepackt.

import tkinter as tk
from tkinter import *
import os
from PIL import ImageTk
from PIL import Image


class fotoframe():
def __init__(self):
self.bottomFrame=Frame(root, bg="red")
self.bottomFrame.pack(side=BOTTOM,fill=X)

def searchfiles(extension, folder):
lb.delete(0,END)
for r, d, f in os.walk(folder):
for file in f:
if file.endswith(extension):
#lb.insert(0, r + "\\" + file)
lb.insert(0,file)

def foto_anzeigen(foto_verz):
libo = lb.curselection()
print("libo=",libo)

if len(libo) <=0:
return
foto = lb.get(lb.curselection()[0])
fotofr=fotoframe()

foto= (foto_verz +"\\" +foto)
print (foto)

### Foto Größe ändern
img = ImageTk.PhotoImage(Image.open(foto))
image=Image.open(foto)
image=image.resize((250,250),Image.ANTIALIAS)
photo=ImageTk.PhotoImage(image)

### Foto ausgeben
foto_label=Label(fotofr.bottomFrame,anchor=N, image=photo)
Label.image=photo

foto_label.config=Label(image=photo)
foto_label.update()
foto_label.pack(fill=BOTH, expand=0)

################ Programmbeginn ##########
root = tk.Tk()
root.geometry("400x600")

entries = []

topFrame=Frame(root, bg="red")
topFrame.pack(side=TOP,fill=X)

fotofr=fotoframe()

foto_verz="C:\\Windows\\Web\\Wallpaper\\Theme2"
bt = tk.Button(root, text="Fotos anzeigen", command=lambda:searchfiles('.jpg', foto_verz))
bt.pack(side=TOP)

lb = tk.Listbox(root)
lb.pack(fill="both", expand=1)
lb.bind("<Button-1>",lambda x: foto_anzeigen(foto_verz))


root.mainloop()
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich vermute mal das "<Button-1>" eine schlechte Idee ist, weil das ja auch das Binding ist was ausgewertet wird um überhaupt eine Auswahl zu treffen. Und wenn Deine Funktion dann abgearbeitet wird bevor die zur Auswahl abgearbeitet wird, ist natürlich nix ausgewählt. Und bei den folgenden Auswahlen ist dann zwar etwas ausgewählt, aber wahrscheinlich das was vor dem Klick aktuell war. Ich würde da ja "<<ListboxSelect>>" statt "<Button-1>" verwenden.

Ansonsten ist der Code sehr schlecht. Lauter komische kryptische Abkürzungen, Sternchen-Import, Variablen auf Modulebene, eine völlig sinnfreie Klasse, Pfadoperationen mit Zeichenketten und ``+`` statt mit dem `pathlib`-Modul, bei den kryptischen Abkürzungen sehr ähnliche Variationen für verschiedene aber doch ähnliche Dinge, …

Vernünftige Namen und kein Hauptprogramm auf Modulebene wären die beiden ersten Sachen die Du angehen solltest. Auf Modulebene gehört nur Code der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Was dann dazu führt das Funktionen und Methoden nicht mehr einfach so auf globale Werte zugreifen können, sondern die sauber als Argument(e) übergeben bekommen. Was bei GUIs in der Regel bedeutet das man objektorientierte Programmierung, also eigene Klassen verwenden muss, wenn man das sinnvoll umsetzen will.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten