Anstatt Buchstaben zu verwalten, muss das Layout insbesondere kleine Frames verwalten, in die Namen geschrieben werden.
Ich muss bedenken, dass die Größe der Namen und damit die Breite der kleinen Frames variieren können. Aus diesem Grund war die Verwendung von „grid()“, wie normalerweise empfohlen, nicht geeignet und ich habe die Verwendung von „place“ für mehr Präzision vorgezogen.
Das Hauptproblem, auf das ich gestoßen bin, besteht darin, dass zwischen den Widgets obwohl nicht angegeben ein Abstand hinzugefügt wird und dies anscheinend mit der Größe des letzten Widgets zusammenhängt. Das heißt, wenn das letzte Widget aufgrund eines langen Namens groß war, wird auch der Abstand zwischen ihm und dem nächsten Widget groß sein. Das ist seltsam, weil die von mir verwendete Funktion den gleichen konstanten Abstand zwischen allen Widgets festlegt.
Darüber hinaus scheint die Tatsache, dass zusätzlicher Abstand sichtbar ist, auch die Berechnungen der Layout-Funktion (do_layout im folgenden Beispiel) ungültig zu machen. Dies bedeutet, dass die Funktion zwar davon ausgeht, dass in der Zeile noch Platz für ein weiteres Widget vorhanden ist, der zusätzliche Abstand jedoch nicht berücksichtigt wird. Das letzte Widget einer Zeile ist ebenfalls nur teilweise oder gar nicht sichtbar.
Hier ist eine vereinfachte Version meines Skripts (es ist wegen der notwendigen Funktionen/Klassen immer noch etwas lang):
Code: Select all
import customtkinter as ctk
class PersonFrame(ctk.CTkFrame):
# (I need to keep it as a Frame for future implementations)
""" Frame that shows the name of the Registered Person """
def __init__(self, master, name):
super().__init__(master, fg_color="#444455", corner_radius=8)
ctk.CTkLabel(self, text=name).pack(padx=10, pady=6)
class FlowFrame(ctk.CTkFrame):
""" Frame responsible of the flow layout """
def __init__(self, master, padx=0, pady=0):
# The [url=viewtopic.php?t=26065]problem[/url] persists even with paddings of 0
super().__init__(master)
self.padx = padx
self.pady = pady
self.widgets = []
# Binding the function 'do_layout' to the scaling of the Frame
self.bind("", self.do_layout)
def add_widget(self, widget):
self.widgets.append(widget)
widget.place(in_=self)
def do_layout(self, event=None):
""" Calculates the height that the Frame should have
and moves children widgets accordingly to a flow layout """
max_width = self.winfo_width()
if max_width max_width:
x = self.padx
y += row_height + self.pady
row_height = 0
# place() is required here to manually implement a flow layout
# (pack and grid are not suitable)
widget.place(x=x, y=y)
x += w + self.padx
row_height = max(row_height, h)
self.configure(height=y + row_height + self.pady)
class RegisteredFrame(ctk.CTkScrollableFrame):
""" Main display Frame containing the FlowFrame """
def __init__(self, master):
super().__init__(master)
self.flow = FlowFrame(self)
self.flow.pack(fill="x", expand=True)
for name in (
"LooooooooooooooongNaaaaame",
"Name",
"OtherName",
"OtherVeryLongName",
):
self.flow.add_widget(PersonFrame(self.flow, name))
class App(ctk.CTk):
def __init__(self):
super().__init__()
self.geometry("600x400")
self.title("Flow layout spacing issue")
RegisteredFrame(self).pack(fill="both", expand=True)
if __name__ == "__main__":
App().mainloop()

Auf dem Bild können wir sehen, dass der Abstand zwischen „LoooongName“ und „Name“ viel größer ist als zwischen „Name“ und „Anderer Name“. Was nicht beabsichtigt ist, da die Auffüllung „self.padx“ im Skript konstant ist.
Hier ist auch ein Bild des Ergebnisses, das ich erhalte, wenn ich das Fenster skaliere, um seine Breite zu verringern:

Hier sehen wir, dass das letzte Widget der ersten Zeile ('OtherName') noch nicht in die zweite Zeile verschoben wurde, obwohl es fast nicht mehr sichtbar ist. Wie oben erwähnt, vermute ich, dass dies daran liegt, dass die Funktion do_layout diesen unerwarteten Abstand zwischen den Widgets nicht berücksichtigt und davon ausgeht, dass in der Zeile noch Platz vorhanden ist. Dies könnte jedoch auch ein anderes und nicht zusammenhängendes Problem sein.
Ich habe versucht zu überprüfen, ob die Breite des internen Canvas des ScrollableFrame von der Breite des FlowFrame abweicht, aber das war nicht der Fall. Ich habe auch versucht zu prüfen, ob es einen Unterschied zwischen „self.winfo_width“ und „self.winfo_reqwidth“ des PersonFrame gibt, aber auch das war nicht der Fall (obwohl ich zugeben muss, dass ich den Unterschied zwischen den beiden nicht ganz verstehe).
Vielen Dank im Voraus für jede Hilfe oder Vorschläge!
Mobile version