pythontkintercustomtkinter

CTk Text Snippet viewer - Can't pack in the right order


I am currently writing a little Text Adventure as a school project and am somewhat stuck on this problem.

Part of the setup needed:

        self.frame = cTk.CTkFrame(self)
        self.frame.place(relx=0.05, rely=0.05, relwidth=0.9, relheight=0.45)

        self.canvas = cTk.CTkCanvas(self.frame, bg="grey", highlightthickness=0)
        self.canvas.pack(side="left", fill="both", expand=True, padx=5, pady=5)

        self.color_frame = cTk.CTkFrame(self.canvas, corner_radius=0)
        self.color_frame.pack(fill="both", expand=True)

        self.text_frame = cTk.CTkFrame(self.canvas, corner_radius=0)
        self.text_frame_id = self.canvas.create_window((0, 0), window=self.text_frame, anchor="nw")

        self.scrollbar = cTk.CTkScrollbar(self.frame, command=self.canvas.yview)
        self.scrollbar.pack(side="right", fill="y", padx=5, pady=5)

        self.canvas.configure(yscrollcommand=self.scrollbar.set)

        self.text_frame.bind("<Configure>", lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")))
        self.canvas.bind("<Configure>", self.update_text_frame_width)

Actually problematic code:

    def add_text_field(self):
        text = self.TestingEntry.get()
        if text != "":
            text_field = cTk.CTkLabel(self.text_frame, text=text, wraplength=self.canvas.winfo_width() - self.scrollbar.winfo_width() - 200)
            separator = cTk.CTkFrame(self.text_frame, height=2, bg_color="grey")
            text_field.pack(fill="x", padx=5, pady=5, expand=True, anchor="w")
            separator.pack(fill="x", anchor="w")
            if self.text_frame.winfo_children():
                first_child = self.text_frame.winfo_children()[0]
                text_field.pack(fill="x", padx=5, pady=5, expand=True, anchor="w", before=first_child)
                separator.pack(fill="x", anchor="w", before=first_child)
            self.canvas.yview_moveto(0)

Whenever trying to run this it sometime work but most often simply fails on the packing order of the seperator and the text_field which both get packed as children of the text_frame.

I want this function to add the newest text_field at the top position (before=first_child) and then follow that up with a new seperator. This cycle should repeat for any following entries. Whenever this code actually works and doesn't just throw an error immediately it gets confused with multiple entries and starts to put new entries at the bottom instead of the top.

I would gladly appreciate any help with this issue as i am running out of ideas to try.

I already tried to change the order of the packing as well as the index of the first child multiple times but sadly without any changes in the output.

Full source code at: https://github.com/PHinterbauer/CTk-Text-Adventure-3BWHII Problem is in ./TESTING/text_snippet_4_trying_expand.py


Solution

  • There are a couple of problems that together are causing problems. For example, you're using winfo_children after creating the widgets so the frame will always have children. That makes the if statement moot, since by the time you've called the if statement the widget already has children.

    The main problem is your use of winfo_children. That will return a list ordered by the order in which the child widgets were created, not the order that they appear in the window. To get the widgets in the order that they appear in the window, you need to use pack_slaves instead.

    first_child = self.text_frame.pack_slaves()[0]