Frame gefüllt mit flexibel vielen Labels

Fragen zu Tkinter.
Antworten
moccajoghurt
User
Beiträge: 23
Registriert: Freitag 20. Juli 2012, 15:12

Hallo,

ich schreibe momentan ein Programm, bei dem über die Google Bildersuche Bilder dynamisch in mein Fenster geladen werden. Jetzt möchte ich eine Möglichkeit haben, dass das Fenster gleich groß bleibt, obwohl sich immer mehr Labels im Fenster befinden. Das heißt man soll nach unten scrollen können, um die weiteren Labels zu sehen. Außerdem sollten immer ca. 5 Labels in eine Reihe passen, bevor eine neue Zeile begonnen wird.
Außerdem muss ich Mausklicks auf die jeweiligen Frames erkennen können, weil dann eine größere Version vom Bild gedownloaded wird.

Habe momentan leider keine Idee wie das am besten umzusetzen ist. Bin über jeden Tipp dankbar.

Gruß moccajoghurt!
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Also wegen dem Runterscrollen würde ich einfach die "Labels" in einen Frame packen und dann einen Scrollbar daneben hin.
Du willst Labels und darauf einen Mausklick erkennen, ich würde vorschlagen das du einfach Buttons hernimmst. :wink:
Dann kannst du daran eine Funktion binden, die das Bild Herunterlädt.(

Code: Alles auswählen

functools.partial
, das brauchst du dazu)
Wenn du willst das die Buttons so Flach aussehen wie Labels dann schreibe einfach relief='flat' als Argument rein.

So jetzt hab ich aber schon genug Denk Arbeit abgenommen, jetzt bist du dran mit dem Programm mal anzufangen, weil den Kompletten Code schreibe ich dir nicht.
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
fnorb
User
Beiträge: 7
Registriert: Sonntag 5. August 2012, 11:18

Hallo moccajoghurt,

die Antwort von Py-Prog wird Dir nicht weiterhelfen. Er hat Dir leider keine Denkarbeit abgenommen, weil keine geleistet:
1. Das functools-Modul ist überhaupt nicht notwendig, kannst Du also getrost vergessen.
2. Buttons sind gar nicht notwendig, auch für Labels kann der Mausklick abgefangen werden.
3. Es ist mit Tkinter nicht möglich scrollbare Frames zu erzeugen. (Soweit ich weiß, hat Tix eine entsprechende Klasse).

Ich würde Dir empfehlen, die Bildauflistung (5 in einer Reihe) entweder in einem Text-Widget oder einem Canvas-Widget anzuzeigen.
Diese beiden Möglichkeiten haben jeweils ihre Vor- und Nachteile. Einfacher ist wahrscheinlich das Text-Widget, da es Dir das Layouting abnimmt.

In ein Text-Widget kannst Du auch Subwidgets einfügen, z.B. Labels.
An Deiner Stelle würde ich die Idee "genau 5 Label in einer Reihe" fallenlassen, denn mittels Text-Widget kannst Du genau so viele Labels in einer Reihe darstellen wie in dessen Breite hineinpassen (automatischer Zeilenumburch), was sich besser macht wenn man die Fenstergröße ändert.

Beim Text-Widget musst Du beachten, dass es in Deinem Anwendungsfall wahrscheinlich schreibgeschützt sein sollte, Du also jedesmal bevor Du ein oder mehrere Subwidgets einfügst den Schreibschutz aufhebst und anschließend wieder einschaltest.

Um einen Mausklick auf ein Label festzustellen musst Du das entsprechende Ereignis abfangen (via dessen bind(...)-Methode).

Gruß
moccajoghurt
User
Beiträge: 23
Registriert: Freitag 20. Juli 2012, 15:12

Hi fnorb!
Danke für deine Antwort.
Ich habe es bereits umgesetzt, indem ich ein Canvas-Widget verwendet habe. Das Text-Widget wäre anscheinend aber die bessere Variante gewesen, weil das Layouting besser gelöst wird. Vielleicht ändere ich es nochmal, wenn das Projekt fertig ist und auf Anklang stößt.
Habe auch Labels anstatt Buttons verwendet.
Jetzt weiß ich zumindest, dass meine Lösung gar nicht so unkonventionell ist, weil du es genauso vorgeschlagen hast :)
Gruß!
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

fnorb hat geschrieben:die Antwort von Py-Prog wird Dir nicht weiterhelfen. Er hat Dir leider keine Denkarbeit abgenommen, weil keine geleistet:
Also wenn ich mir mal ansehe was du geschrieben hast sowohl die Beleidigung als auch den Rest und wenn ich mir mal deine Anzahl an Beiträgen Ansehe dann kann ich nur eins sagen:
Du bist lieber mal ganz still!
fnorb hat geschrieben:1. Das functools-Modul ist überhaupt nicht notwendig, kannst Du also getrost vergessen.
Und wie willst du dann erreichen das du einer Funktion ein Bild übergibst was du dann mit bind an ein Label binden kannst?
Mit lambda würde es auch gehen, aber da finde ich functools schöner, BlackJack ist da auch meiner Meinung, bzw. habe ich mich seiner Meinung Anschlossen.
fnorb hat geschrieben:2. Buttons sind gar nicht notwendig, auch für Labels kann der Mausklick abgefangen werden.
Ja, wenn man unschön Programmieren will, dann nicht, man kann auch wie du es machen würdest mit der bind Funktion ein label zweckentfremden.

Code: Alles auswählen

3. Es ist mit Tkinter nicht möglich scrollbare Frames zu erzeugen. (Soweit ich weiß, hat Tix eine entsprechende Klasse).
Da hast du ausnahmsweise recht, ich hatte keine Lust da nach zuschauen ob das geht oder nicht.
Aber es ging da nur um den Ansatz, weil es nicht geht hätte er es gemerkt das es nicht geht und hätte dann bei Google nach solchen Klassen oder Anderen Lösungen suchen können, was nicht zu viel verlangt wäre, wenn man nichts findet dann kann man ja hier immer noch Fragen.
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
fnorb
User
Beiträge: 7
Registriert: Sonntag 5. August 2012, 11:18

Hallo Py-Prog,

sorry, falls Du Dich angegriffen fühltest. Ich wollte Dich nicht beleidigen.

Vielleicht habe ich mich tatsächlich im Ton vergriffen.

Aber ich finde nicht, dass es weiterhilft, wenn man Lösungsvorschläge unterbreitet -- wie bspw. eine Scrollbar zu einem Frame -- ohne diese anscheinend selbst je getestet zu haben.

Auch die Aussage, lieber Buttons statt Labels zu nehmen, hilft bei dem beschriebenen Problem nicht wirklich weiter.
In habe in den letzten zehn Jahren Python/Tkinter-Programmierung noch nie das functools-Modul benötigt.
Natürlich kann man via Lambda-Ausdrücken weitere Argumente übergeben, aber selbst das ist nicht nötig, da man dem Label selbst Attribute geben kann (z.B. auch eine Bild-URL), welche in der Ereignisbehandlung ausgelesen werden können:

Code: Alles auswählen

def onclick( data ):
     print( data.widget.spam )

label = tkinter.Label( ... )
label.spam = 'eggs'
label.bind( '<Button>', onclick )
...
Wie man's letztlich macht (ich bevorzuge abgeleitete Klassen) ist Geschmackssache.

Moccajoghurt hatte lediglich um einen Hinweis gebeten, wie man beliebig viele Labels (je 5 in einer Reihe) in ein scrollbares Container-Widget plaziert. Du hast geantwortet, Du könntest ihm nicht noch die ganze Denkarbeit abnehmen, bist aber in Deiner Antwort gar nicht auf den Kern der Frage eingegangen. Fast jeder der mit Tkinter arbeitet wird nämlich irgendwann auf das gleiche Problem eines fehlenden ScrollableFrame stoßen und sich darüber ärgern, dass man das Problem recht häßlich mittel Text- oder Canvas-Widget angehen muss.

Aber nochmal: sorry, falls ich Dich beleidigt haben sollte.

Gruß

P.S. Was hat die Anzahl der Beiträge damit zu tun?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

fnorb hat geschrieben:In habe in den letzten zehn Jahren Python/Tkinter-Programmierung noch nie das functools-Modul benötigt.
Natürlich kann man via Lambda-Ausdrücken weitere Argumente übergeben, aber selbst das ist nicht nötig, da man dem Label selbst Attribute geben kann (z.B. auch eine Bild-URL), welche in der Ereignisbehandlung ausgelesen werden können:
[...]
Wie man's letztlich macht (ich bevorzuge abgeleitete Klassen) ist Geschmackssache.
Welchen Ansatz man hier verwendet hat meiner Meinung nach nicht viel mit Geschmack zu tun. Deine Vorschläge haben alle Nachteile gegenüber der functools.partial-Lösung. Eine eigene Klasse für einen Button ist meiner Meinung nach der vollkommen falsche Ansatz. Damit vermischt du Daten und GUI, und sprichst außerdem dem Widget mehr Funktionalität zu als es haben sollte. Nur weil bei einer Aktion mit einem Button bestimmte Daten benötigt werden, handelt es sich ja noch nicht um eine neue Art von Button. Hinzu kommt, dass man damit eigentlich nur unnötig viel Code erzeugt.

Das Zuweisen von neuen Attributen von außen an eine existierende Instanz hat ähnliche Nachteile, lediglich der zusätzliche Code entfällt. Hinzu kommt allerdings die Gefahr, dass man die Attribute der bestehenden Instanz kennen muss - ggf. auch über mehrere Versionen hinweg - und im schlimmsten Fall irgendwo etwas zerschießt. Hinzu kommt dann noch, dass man sich zusätzlichen unnötigen Zustand einbaut, welchen man natürlich eigentlich vermeiden möchte.

Mit dem funktionalen Ansatz hat mal alle diese Probleme nicht. Kein zusätzlicher Code, keine Veränderung von existierenden Objekten, saubere Trennung von Daten und GUI und kein zusätzlicher Zustand. Es gibt also durchaus jede Menge objektiver Gründe warum partial deinem Ansatz überlegen ist.
Das Leben ist wie ein Tennisball.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

fnorb hat geschrieben:Hallo Py-Prog,

sorry, falls Du Dich angegriffen fühltest. Ich wollte Dich nicht beleidigen.

Vielleicht habe ich mich tatsächlich im Ton vergriffen.
Ja hast du, mein verhalten war aber auch nicht ganz richtig, vergessen wir's ...
fnorb hat geschrieben: Aber ich finde nicht, dass es weiterhilft, wenn man Lösungsvorschläge unterbreitet -- wie bspw. eine Scrollbar zu einem Frame -- ohne diese anscheinend selbst je getestet zu haben.
Wie bereits gesagt ich bin davon ausgegangen dass das geht.
fnorb hat geschrieben:Auch die Aussage, lieber Buttons statt Labels zu nehmen, hilft bei dem beschriebenen Problem nicht wirklich weiter.
Es würde aber den Code leichter verständlich machen und siehe EyDu's Beitrag.
fnorb hat geschrieben:In habe in den letzten zehn Jahren Python/Tkinter-Programmierung noch nie das functools-Modul benötigt.
Nicht benötigt, oder einfach nicht hergenommen? :wink:
fnorb hat geschrieben:Moccajoghurt hatte lediglich um einen Hinweis gebeten, wie man beliebig viele Labels (je 5 in einer Reihe) in ein scrollbares Container-Widget plaziert. Du hast geantwortet, Du könntest ihm nicht noch die ganze Denkarbeit abnehmen, bist aber in Deiner Antwort gar nicht auf den Kern der Frage eingegangen. Fast jeder der mit Tkinter arbeitet wird nämlich irgendwann auf das gleiche Problem eines fehlenden ScrollableFrame stoßen und sich darüber ärgern, dass man das Problem recht häßlich mittel Text- oder Canvas-Widget angehen muss.
Also für mich hörte sich das so an als wir ihm seine Hausaufgaben machen sollten, weil da einfach gar kein Ansatz dar war. Und es war für mich nicht eine Frage sondern die Frage wie er einen Mausklick abfragen kann, wie immer 5 Bilder in einer reihe angezeigt werden und wie das mit dem Scrollbar geht. Und es war eben zu keiner Frage ein Ansatz dar. Und ich wollte ihm eigentlich bloß sagen dass er mal anfangen soll einen Ansatz zu schreiben. Das war eigentlich gar nicht bös gemeint, ...

fnorb hat geschrieben:P.S. Was hat die Anzahl der Beiträge damit zu tun?
Gar nichts, aber würdest du dich von jemanden der seinen ersten Beitrag schreibt beleidigen lassen?
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Py-Prog hat geschrieben:
fnorb hat geschrieben:Auch die Aussage, lieber Buttons statt Labels zu nehmen, hilft bei dem beschriebenen Problem nicht wirklich weiter.
Es würde aber den Code leichter verständlich machen und siehe EyDu's Beitrag.
Ich habe mich lediglich zur Bevorzugung von functools.partial gegenüber anderen Konstrukten geäußert. Mit der Buttons-vs.-Labels-Diskussion hat mein Beitrag nichts zu tun.
Das Leben ist wie ein Tennisball.
Antworten