Canvas feste Grösse geben

Fragen zu Tkinter.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Mittwoch 25. Juni 2008, 13:14

Normale Frames kann man wirklich nicht scrollen. Wie wäre es dann aber z.B. mit ScrolledWindow in Tix: http://tix.sourceforge.net/
MfG
HWK
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Mittwoch 25. Juni 2008, 20:19

Pü-Ton hat geschrieben:Es ist so, dass aus dem XML zum einen Die Namen ausgelesen werden - das sind wirklich nur Texte und daneben (rechts davon) kommen Entrys hin, in denen ein defaultwert steht. Ich kann also kein reines Textwidget nehmen...
Hi Pü-Ton!

Danke, dass Du mich mal aus meinem Winterschlaf geweckt hast. :-)

Da traust Du dem Text-Widget aber ganz schön wenig zu. Dabei ist es mindestens genauso vielseitig wie ein Canvas. Du kannst nämlich auch in Text-Widgets beliebige andere Tkinter-Widgets über die Methode window_create einbetten. Hier mal ein minimalistisches Beispiel:

Code: Alles auswählen

import Tkinter as tk
root = tk.Tk()

# Textwidget statt Canvas, das kann mehr als man denkt
text = tk.Text(root, width=60, height=20)
text.grid(row=2, column=1)

# nur die Scrollbar einfuegen
scroll_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=text.yview)
scroll_y.grid(row=2, column=2, sticky=tk.NS)

# xml-Datendict und variablen-Zwischenspeicher initialisieren
xml_dict = {"Vorname":"Michael", "Nachname":"Ballack", "Position":"Mittelfeld"}
variable_dict = {}

# xml-Daten einfuellen, pro Eintrag eine tk-Variable definieren und ein
#   Entry einfuegen
for tag_name, default_value in xml_dict.iteritems():
    text.insert(tk.END, "%s: "%tag_name)
    tk_var = tk.StringVar()
    tk_var.set(default_value)
    variable_dict[tag_name] = tk_var
    text.window_create(tk.END, window=tk.Entry(text, width=20, textvariable=tk_var))
    text.insert(tk.END, "\n")
    
# Scrollbalken verknuepfen und Textaenderungen unterbinden
text.config(yscrollcommand=scroll_y.set, state=tk.DISABLED)
root.mainloop()

# Ergebnisdict aus den xml-Schluesseln und den tk-Variablen ermitteln
result_dict = dict([(tag, variable_dict[tag].get()) for tag in xml_dict])
print result_dict
Meiner Erfahrung nach ändert sich die Größe eines Canvas beim Gridden NICHT! Vielleicht liegt es daran, dass Du ein Label-Widget als Container (Window1) missbrauchst? Im Zweifelsfall würde ich immer auf die Standard-Container Frame und Toplevel zurückgreifen.
Das Rectangle ist kein Tkinter-Widget, sondern ein Objekt das ein grafisches Element eines Canvas darstellt und es ist nicht als Container für andere Tkinter-Widgets geeignet.
Bei Verwendung des Canvas musst Du beachten, dass Du regelmäßig die Ressource "scrollregion" updatest, die dem Canvas sagt, über welchen Bereich er scrollen soll.

Code: Alles auswählen

canvas.config(scrollregion=canvas.bbox("all"))
Ich schlage vor, dass Du es erstmal mit Text-Widget und eingebetteten Entries versuchst. Wenn es unbedingt ein Canvas sein muss, kriegen wir das auch noch gebacken. Dafür brauche ich aber minimalen funktionierenden Code, bei dem sich die Größe des Canvas verändert.

Viele Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Pü-Ton
User
Beiträge: 67
Registriert: Donnerstag 8. Mai 2008, 07:52

Donnerstag 26. Juni 2008, 11:36

ich habe es jetzt endlich hinbekommen, so wie ich es wollte.

1000 dank an alle Beteiligten.

Zur Lösung bin ich über das create_window gekommen. In ein Canvas kann somit ein Window gesetzt werden, in welches wiederum alle beliebigen widgets eingebaut werden können.

Ich habe also ein Hauptframe, dass das grösste ist.
Da rein baue ich ein scrollbares Canvas, dass wiederum ein gleichgrosses Window hat, in welches ich jetzt die Daten, die ich aus einem XML lese, hineinschreiben lasse, jeweils mit Abstand...

Das war eine schwere Geburt, aber es funzt super.
Bestimmt gibts noch andere Lösungen dafür.

Hier mal der Code, falls jm mal was ähnliches vor hat:

Code: Alles auswählen

from Tkinter import*
import Tkinter as TK
import Canvas

tk = TK.Tk()
yscroll = TK.Scrollbar(tk, orient = TK.VERTICAL)
yscroll.grid(row = 1, column = 2, sticky = TK.NS)


canvas = TK.Canvas(tk,
                   width = 300,
                   height = 300,
                   scrollregion = "0 0 400 400",        ##  Scrollregion im Bereich 0,0 - 400, 400
                   yscrollcommand = yscroll.set,        ##  Canvashoehe an yscroll uebergeben
                   bg="#9999ff")
canvas.grid(row = 1, column = 1)


yscroll.config(command=canvas.yview)                  ##  yscrollwerte an canvas uebergeben

n=0
for i in range(30):
    n = n+25
    Dummy_var=Label(canvas,text="tadaaaa", font=("Arial",12, "bold"), anchor=CENTER, fg="#FFFFFF", bg="#990000", width=20)
    canvas.create_window(45,15+n,window=Dummy_var, anchor=W)


tk.mainloop()
Das gute daran ist jetzt halt, dass die Daten, die mehr Platz einnehmen als angezeigt werden können, erst dann zum Vorschein kommen, wenn gescrollt wird. Bei meinen ganzen Versuchen davor wurde das Fenster immer gleich so gross, wieviel Einträge da waren !!!

mfG Pü-Ton
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Donnerstag 26. Juni 2008, 12:35

Hi Pü-Ton!
Pü-Ton hat geschrieben:

Code: Alles auswählen

                   scrollregion = "0 0 400 400",        ##  Scrollregion im Bereich 0,0 - 400, 400
Das geht so lange gut, bis Deine Widgets tiefer als y=400 plaziert werden, während Du auch dann über 400 pixel scrollen kannst/musst, wenn sich weniger Widgets im Canvas befinden. Bitte berücksichtige daher die letzte Empfehlung meines letzten Posts weiter oben.
Pü-Ton hat geschrieben: Bei meinen ganzen Versuchen davor wurde das Fenster immer gleich so gross, wieviel Einträge da waren !!!
Das ist die meist gewünschte und manchmal verhasste Eigenschaft des grid-Managers.

[edit]Passage entfernt, da 'maxsize' kein gültiger Schlüsselwortparameter für rowconfigure/columnconfigure ist [/edit]

Grüße,
Michael
Zuletzt geändert von Michael Schneider am Freitag 27. Juni 2008, 06:58, insgesamt 2-mal geändert.
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Pü-Ton
User
Beiträge: 67
Registriert: Donnerstag 8. Mai 2008, 07:52

Donnerstag 26. Juni 2008, 12:43

hmmm,

wenn ich das

Code: Alles auswählen

canvas.config(scrollregion=canvas.bbox("all"))
verwende, ist die Scrollbar zwar da, sieht aber ausgegraut aus und der eigentliche Schieber fehlt !!!
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Donnerstag 26. Juni 2008, 12:53

Michael Schneider hat geschrieben:Aber wie weiter oben beschrieben kannst Du dessen mit rowconfigure/columnconfigure + maxsize Herr werden.
Meines Wissens gibt es dabei kein Attribut maxsize, sondern nur minsize.
MfG
HWK
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Donnerstag 26. Juni 2008, 13:21

Hallo HWK und Pü-Ton!

@HWK: ich dachte, ich hätte einfach mal maxsize eingesetzt und es gab keinen Fehler. Entweder liegt das an der Version, oder ich habe mich verschrieben und doch minsize verwendet. In älteren Versionen von tcl gibt es maxsize jedenfalls nicht, das stimmt. Ich werde mal vorsorglich meinen Kommentar editieren, damit sich da keiner ein Beispiel dran nimmt.

@Pü-Ton:
Pü-Ton hat geschrieben:hmmm,
wenn ich das

Code: Alles auswählen

canvas.config(scrollregion=canvas.bbox("all"))
verwende, ist die Scrollbar zwar da, sieht aber ausgegraut aus und der eigentliche Schieber fehlt !!!
Ja, das Graue dürfte der Schieber sein, der über die gesamte Länge der Scrollbar geht. Das passiert genau dann, wenn der gesamte Inhalt noch in den sichtbaren Bereich passt. Erst wenn die ersten Widgets außerhalb des sichtbaren Bereichs plaziert werden, wird der Scrollbereich erweitert und der Schieber wird angepasst.

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Freitag 27. Juni 2008, 06:55

HWK hat geschrieben:
Michael Schneider hat geschrieben:Aber wie weiter oben beschrieben kannst Du dessen mit rowconfigure/columnconfigure + maxsize Herr werden.
Meines Wissens gibt es dabei kein Attribut maxsize, sondern nur minsize.
Hi HWK,

Du hast recht, da muss ich wohl etwas Falsches eingetippt haben - sehr peinlich. :oops:
Deshalb habe ich auch die Finger vom Grid gelassen, wenn es darum ging, eine dynamisch erweiterbare Liste darzustellen. Als Alternative habe ich den Place-Manager verwendet und bei Scrollbefehlen das Offset der Widgetpositionen verändert.

Grüße,
Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Antworten