Seite 1 von 1
objekte dynamisch verteilen
Verfasst: Samstag 9. Oktober 2010, 18:03
von Xynon1
Hi,
gibt es schon eine Möglichkeit in einem Frame die maximale Breite anzugeben, welche bei zB. pack(side=LEFT) eingehalten wird und das objekt in eine weitere Zeile gepackt wird.
Oder muss ich mir dafür selbst was schreiben, so dass ich die größen aller Elemente zusammenrechne und bei einem fall der übertretung es dan eine zeile umpacke.
mir ist eigentlich egal ob pack() grid() oder place(), würde aber lieber nur pack arbeiten, also
statt Frame
---------------------------------------
| "pack" "pack" "pack" "dies passt nicht mehr", "pack" |
---------------------------------------
Frame1
---------------------------------------
| "pack" "pack" "pack" |
---------------------------------------
Zusätzlicher Frame2
---------------------------------------
| "dies passt nicht mehr", "pack" |
---------------------------------------
Re: objekte dynamisch verteilen
Verfasst: Dienstag 12. Oktober 2010, 14:46
von Xynon1
Ich nehme, daraus resultierend das keine Antwort bisher kam an, dass es so etwas in der Art noch nie geplant, nie gewollt und schon gar nicht erst gebaut wurde.
Edit: Yuhuu, man muss nur etwas provozieren/herausfordern und schon läufts.

Re: objekte dynamisch verteilen
Verfasst: Dienstag 12. Oktober 2010, 15:08
von wuf
Hallo Xynon1
Ich verstehe evt. nicht genau was du meinst. Habe hier einmal etwas ausprobiert:
Code: Alles auswählen
import Tkinter as tk
app_win = tk.Tk()
app_win.geometry('400x300')
frame = tk.Frame(app_win, bg='yellow', width=100, height=50)
frame.pack(side='left')
frame.propagate(False)
frame = tk.Frame(app_win, bg='green', width=100)
frame.pack(side='left', fill='y')
frame.propagate(False)
frame = tk.Frame(app_win, bg='red', width=100, height=50)
frame.pack(side='left', anchor='nw')
frame.propagate(False)
app_win.mainloop()
Gruß wuf

Re: objekte dynamisch verteilen
Verfasst: Dienstag 12. Oktober 2010, 16:22
von Xynon1
Zum Beispiel möchte ich Labels ungefähr so auf einen Frame packen (ich geh mal von dienem Beispiel aus)
Code: Alles auswählen
import Tkinter as tk
app_win = tk.Tk()
app_win.geometry('400x300')
color = ["yellow", "green", "red"]
frame = tk.Frame(app_win, borderwidth=3, relief="groove", width=100, height=50)
frame.pack()
#frame.propagate(False)
for i in xrange(50):
lb = tk.Label(frame, bg=color[i%3])
lb.pack(side="left")
app_win.mainloop()
Allerdings ist das jetzt natürlich größer als eingestellt, dafür nutzt du ja die methode .propagate(False), um eine feste Größe beizubehalten.
So, aber mit der Methode fehlen gut 30 Label und da ist mein Problem.
Diese sollten nun zB. in einem neuen Frame darunter angezeigt werden.
Hier mal manuell eingestellt:
Code: Alles auswählen
import Tkinter as tk
app_win = tk.Tk()
app_win.geometry('400x300')
color = ["yellow", "green", "red"]
for j in xrange(5):
frame = tk.Frame(app_win, borderwidth=3, relief="groove", width=100, height=50)
frame.pack()
frame.propagate(False)
for i in xrange(10):
lb = tk.Label(frame, bg=color[i%3])
lb.pack(side="left")
app_win.mainloop()
Der Haken ist nur ich weiß natürlich nicht wie viele Elemente existieren, also dargestellt werden müssen, dennoch sollten sie OHNE Scrollbar sichtbar sein.
Scrollbar sollte nur bei zu knapper Monitor größe in der Vertikalen angezeigt werden.
Re: objekte dynamisch verteilen
Verfasst: Dienstag 12. Oktober 2010, 17:27
von wuf
Hallo Xynon1
So wie ich dich verstehe möchtest du in einem Frame mit fest vorgegebener geometrie eine grössere Menge Labels der Reihe nach von links nach rechts platzieren. Sobald ein Label bei seiner Platzierung den rechten Rand des fest eingestellten Frames überlappt dieses Label automatisch ganz auf der linken Seite des Frames in einer zweiten Reihe platzieren. Verstehe ich das richtig?
Elemente sind bei dir Labels?
Gruß wuf

Re: objekte dynamisch verteilen
Verfasst: Dienstag 12. Oktober 2010, 17:52
von Xynon1
Nein, die Label waren nur als Veranschaulichung, mit Elementen meine ich jedes Objekt was zu Tkinter Widgets gehört.
Also auch alle abgeleiteten Klassenobjekte, vom einfachen Frame, über Label bis hinzu Menubuttons.
Halt jedes Klassenobjekt, zum selber bauen einer solchen Funktion würde ich einfach die winfos nehmen die ja Tk und BaseWidget von Misc abgeleiten und somit ja bei jedem "Element" verfügbar sind.
Abgesehen von den Labels, hast du es aber voll erfasst.
Meine Frage war halt nur ob es sowas schon gibt.
Re: objekte dynamisch verteilen
Verfasst: Dienstag 12. Oktober 2010, 19:03
von numerix
Xynon1 hat geschrieben:Meine Frage war halt nur ob es sowas schon gibt.
Was du suchst, klingt nach dem, was das Flow-Layout in Java/Swing leistet.
Ich kenne zumindest nichts dergleichen für Tkinter und die geringe Resonanz auf diesen Thread ist vielleicht ein Indiz dafür, dass der Bedarf danach auch eher gering ist. Für Tkinter fallen mir dazu nur "schmutzige" und umständliche Lösungen ein, die man nicht wirklich wollen kann, wie z.B. ein Canvas als Hauptframe zu verwenden, die benötigten Widgets zunächst im unsichtbaren Bereich zu platziert, dann die Maße zu ermitteln und dann zu rechnen, wo es hingehört.
Wenn das für dich so wichtig ist, solltest du dich vielleicht bei den anderen GUI-Toolkits einmal umschauen; falls es das da auch nicht gibt, bliebe noch Jython ...
Re: objekte dynamisch verteilen
Verfasst: Dienstag 12. Oktober 2010, 19:36
von wuf
Hallo numerix
Danke für deine Ergänzungen. Sorry habe nicht von Anfang an verstanden was Xynon1 genau wollte. Habe hier einmal versucht das Skript etwas in Richtung was sich Xynon1 wünscht zu modifizieren:
Code: Alles auswählen
import Tkinter as tk
MAIN_FRAME_WIDTH = 100
MAIN_FRAME_HEIGHT = 100
app_win = tk.Tk()
app_win.geometry('400x300')
color = ["yellow", "green", "red"]
frame = tk.Frame(app_win, borderwidth=3, relief="groove",
width=MAIN_FRAME_WIDTH, height=MAIN_FRAME_HEIGHT)
frame.pack()
frame.propagate(False)
flex_frame = tk.Frame(frame)
flex_frame.pack(side='top', anchor='nw')
for i in xrange(50):
lb = tk.Label(flex_frame, bg=color[i%3])
lb.pack(side="left", anchor='nw')
flex_frame.update_idletasks()
flex_frame_width = flex_frame.winfo_reqwidth()
if flex_frame_width > MAIN_FRAME_WIDTH:
lb.destroy()
flex_frame = tk.Frame(frame)
flex_frame.pack(side='top', anchor='nw')
lb = tk.Label(flex_frame, bg=color[i%3])
lb.pack(side="left", anchor='nw')
app_win.mainloop()
I love dirty programming
Getestet auf Linux SuSE 11.0
Gruß wuf

Re: objekte dynamisch verteilen
Verfasst: Dienstag 12. Oktober 2010, 20:20
von numerix
wuf hat geschrieben:I love dirty programming
Naja, verglichen mit dem, was mir zunächst in den Sinn gekommen ist, ist deine Variante von "dirty" doch noch ziemlich weit entfernt ...
Re: objekte dynamisch verteilen
Verfasst: Dienstag 12. Oktober 2010, 21:30
von Xynon1
Ja, genau sowas, so ausführlich hättest du es gar nicht machen müssen, mir hätten eigentlich die funktionen update_idletasks() und winfo_reqwidth() statt winfo_width() (womit ich es ebend noch vergeblich probiert hatte

)
Aber Danke für deine Mühen.
Wäre jetzt nur noch schön wenn man sich das lb.destroy() sparen könnte, aber mir fällt auch nichts besseres ein.
@numerix
Mich erinnert das eher an Container für zB Drag and Drop-Inhalte und zum Teil wollte ich es auch für Bilder nutzen.
und bei solchen Sachen finde ich das doch sehr nützlich.