Hilfe zu columnconfigure und columnspan

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
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo,
benötige Eure Hilfe zu columnconfigure und columnspan.
Ich habe dazu einen Testcode, den ich am Ende bereitstellen werde.

In dem Beispiel hat die erste bis dritte Reihe 4 Spalten, die Breite der Widgets ist 10.
Die vierte bis fünfte Reihe hat 6 Spalten, die Breite der Widgets ist 10.
Ab der sechsten Reihe sind es 8 Spalten und die Breite der Widgets ist 40.
Die Widgets sollen von links nach rechts aneinander liegen.

Ich habe schon einiges ausprobiert, komme aber nicht auf das gewünschte Ergebnis.
Hoffe, Ihr könnt mir dabei helfen!

Hier der Beispielcode:

Code: Alles auswählen

import tkinter as tk

class AutoScrollbar(tk.Scrollbar):

	def set(self, low, high):
		if float(low) <= 0.0 and float(high) >= 1.0:
			self.tk.call("grid", "remove", self)
		else:
			self.grid()
		tk.Scrollbar.set(self, low, high)

	def pack(self, **kw):
		raise (TclError,"pack cannot be used with \
		this widget")

	def place(self, **kw):
		raise (TclError, "place cannot be used  with \
		this widget")

root = tk.Tk()

yscrollbar = AutoScrollbar(root)

yscrollbar.grid(row=0, column=1, sticky=tk.NS)

xscrollbar = AutoScrollbar(root, orient=tk.HORIZONTAL)

xscrollbar.grid(row=1, column=0, sticky=tk.EW)

canvas = tk.Canvas(root, yscrollcommand=yscrollbar.set,
	xscrollcommand=xscrollbar.set)

canvas.grid(row=0, column=0, sticky=tk.NSEW)

yscrollbar.config(command=canvas.yview)
xscrollbar.config(command=canvas.xview)

root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)

frame = tk.Frame(canvas)
frame.rowconfigure(1, weight=1)
frame.columnconfigure(1, weight=1)

rows = 20
for i in range(0,rows):
	frame.columnconfigure(i, weight=1)
	for j in range(0,9):
		button = tk.Button(frame, padx=8, pady=8, text="[%d,%d]" % (i,j))
		if i < 3:
			frame.columnconfigure(i, weight=3)
			button.grid(row=i, columnspan=3, sticky=tk.W)
			button.config(width=15)
			if j == 3:
				break
		elif i >= 3 and i < 5:
			frame.columnconfigure(i, weight=5)
			button.grid(row=i, columnspan=5, sticky=tk.W)
			button.config(width=10)
			if j == 5:
				break
		else:
			button.grid(row=i, column=j, sticky=tk.W)
			button.config(width=40)

canvas.create_window(0, 0, anchor=tk.NW, window=frame)

frame.update_idletasks()

canvas.config(scrollregion=canvas.bbox("all"))

root.mainloop()
Benutzeravatar
peterpy
User
Beiträge: 188
Registriert: Donnerstag 7. März 2013, 11:35

Hallo Nobuddy,

ich versteh nicht was Du willst:
laut deinem Code sollen in den Zeilen 0 bis 2 je neun Tasten in einer Zeile angeordnet werden?
Laut deinem Beschrieb aber nur vier. Du Iterierst aber über neun Spalten(j), erzeugst also 9 Tasten.
Da Du column nicht angegeben hast, werden alle in Spalte Null plaziert.
Was willst Du mit dem weight? Die bezeichnet den Faktor zum dehnen.
Mit columnspan erstreckt sich dein Widget über die angegebene Anzahl Spalten, beginnend mit column=j
Du willst deine Tasten über 4, 6 und 8 Spalten verteilen. Also benötigst Du 24 Spalten.
In den ersten drei Zeilen erstreckt sich eine Taste über 24 / 4 = sechs Spalten
In den Zeile drei bis fünf erstrecken sich die Tasten über vier Spalten und der Rest über drei Spalten.
Um die Tastenbreite gleich zu halten, gibst Du sticky=tk.E+tk.W an.
Gruss Peter
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Dein Code stimmt nicht mit der Erklärung oben überein.
Dass man mit 4 Leerzeichen pro Ebene einrückt, und nicht mit Tabs oder 2 Leerzeichen, wurde Dir hier schon öfter geschrieben. tk.call ist hier überflüssig (hab ich Dir auch schon geschrieben).
Die vielen if-Abfragen machen es sehr schwierig, überhaupt zu verstehen, wann was passiert.

Code: Alles auswählen

import tkinter as tk


def create_button_row(frame, row, count, span):
    for j in range(count):
        button = tk.Button(frame, padx=8, pady=8, text="[%d,%d]" % (row, j), width=5*span)
        button.grid(row=row, column=j*span, columnspan=span, sticky=tk.EW)


def main():
    frame = tk.Tk()

    for row in range(0, 3):
        create_button_row(frame, row, count=3, span=3)
    for row in range(3, 5):
        create_button_row(frame, row, count=6, span=2)
    for row in range(5, 20):
        create_button_row(frame, row, count=9, span=8)
                
    frame.mainloop()

if __name__ == "__main__":
    main()
Benutzeravatar
peterpy
User
Beiträge: 188
Registriert: Donnerstag 7. März 2013, 11:35

@sirius, ich denke Nobuddy wollte das so:

Code: Alles auswählen

import tkinter as tk


def create_button_row(frame, row, count, span):
    for j in range(count):
        button = tk.Button(frame, padx=8, pady=8, text="[%d,%d]" % (row, j), width=5*span)
        button.grid(row=row, column=j*span, columnspan=span, sticky=tk.EW)


def main():
    frame = tk.Tk()

    for row in range(0, 3):
        create_button_row(frame, row, count=3, span=8)
    for row in range(3, 5):
        create_button_row(frame, row, count=4, span=6)
    for row in range(5, 24):
        create_button_row(frame, row, count=8, span=3)
                
    frame.mainloop()

if __name__ == "__main__":
    main()
Gruss Peter
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo und Danke, für Eure Hilfe!

Der Code ist ja fast identisch, von Euch beiden.
Peter verwendet die Widgetbreite, was meiner Vorstellung entspricht.
Jedoch, wird nicht die Breite 10, 15, 40 verwendet.
Die Spalten der Reihen, sollen keine Abhängigkeit zu einander haben, daher auch die unterschiedlichen Breiten der Widgets.
Habe den Code mal entsprechend geändert, aber das Ergebnis entspricht immer noch nicht dem.

Code: Alles auswählen

import tkinter as tk


def create_button_row(frame, row, count, span, width):
    for j in range(count):
        button = tk.Button(frame, padx=8, pady=8, 
			text="[%d,%d]" % (row, j), width=width)
        button.grid(row=row, column=j*span, columnspan=span, sticky=tk.EW)


def main():
    frame = tk.Tk()

    for row in range(0, 3):
        create_button_row(frame, row, count=3, span=8, width=15)
    for row in range(3, 5):
        create_button_row(frame, row, count=4, span=6, width=10)
    for row in range(5, 24):
        create_button_row(frame, row, count=8, span=3, width=40)

    frame.mainloop()

if __name__ == "__main__":
    main()
Benutzeravatar
peterpy
User
Beiträge: 188
Registriert: Donnerstag 7. März 2013, 11:35

Hallo Nobuddy,

was willst Du?
8 Spalten und die Breite der Widgets ist 40 = 320 Zeichen
6 Spalten, die Breite der Widgets ist 10 = 60 Zeichen
4 Spalten, die Breite der Widgets ist 10 = 40 Zeichen

Wenn deine Tasten auf die Breite beschränkt werden sollen, sieht das irgendwie komisch aus.

Code: Alles auswählen

button.grid(row=row, column=j*span, columnspan=span)
Du musst dich entscheiden,, willst Du eine "pyramidenstumpf-förmige" Anordnung?
Dann brauchen die unterschiedlichen Spaltenvarianten je einen Frame.
Gruss Peter
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

peterpy hat geschrieben: Donnerstag 30. Juni 2022, 14:42 Du musst dich entscheiden,, willst Du eine "pyramidenstumpf-förmige" Anordnung?
Dann brauchen die unterschiedlichen Spaltenvarianten je einen Frame.
Das ist es eine "pyramidenstumpf-förmige" Anordnung".
Dachte, dass das ohne weiteren Frame gehen würde, was wohl nicht der Fall ist.

Euer Code, war für mich aufschlussreich, kannte ich bisher so nicht.

Danke für Eure Hilfe :wink:
Antworten