Home > Mobile >  Updating size of frame in canvas in customtkinter
Updating size of frame in canvas in customtkinter

Time:02-04

I have created a GUI with a scrollbar in customtkinter, but I have some problems with it. The GUI consists of two frames: the first one is a scrollable canvas frame with input fields; the second frame consists of a single button that, when clicked, adds fields to the first frame. The problem is that the height of the first frame is initially set to 400, but I want to add some height each time the Add row button is clicked. I tried to do it by self.canvas.itemconfigure(self.window, height=400 (50*self.xr), but it doesn't seem to work: there is no visual effect, but after printing the height of the frame is changed.

import customtkinter

class Adder:

    def __init__(self, app):
    self.app = app
    self.app.title("self.Scrollbar testing")
    self.app.geometry('{}x{} {} {}'.format(550, 460, 750, 250))
    self.xr = 1

    self.app.grid_rowconfigure(0, weight=1)
    self.app.grid_columnconfigure(0, weight=1)

    self.frame = customtkinter.CTkFrame(master=self.app)
    self.frame.grid(row=0,column=0, padx=15,pady=15, sticky="NSEW")

    self.frame.grid_rowconfigure(0, weight=1)
    self.frame.grid_columnconfigure(0, weight=1)

    self.canvas = customtkinter.CTkCanvas(self.frame)
    self.canvas.grid(row=0,column=0, sticky="NSEW")

    self.canvas.grid_rowconfigure(0, weight=1)
    self.canvas.grid_columnconfigure(0, weight=1)

    self.frame_2 = customtkinter.CTkFrame(master=self.canvas)

    self.scrollbar = customtkinter.CTkScrollbar(master=self.frame, orientation="vertical", command=self.canvas.yview, height=460, width=15)
    self.scrollbar.grid(row=0, column=0, sticky="NE")

    self.canvas.configure(yscrollcommand=self.scrollbar.set)
    self.canvas.bind("<Configure>", lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")))

    self.window = self.canvas.create_window((0,0), window=self.frame_2, anchor="nw", height=400)

    self.entry_1 = customtkinter.CTkEntry(master=self.frame_2, placeholder_text=f"entry")
    self.entry_1.grid(row=0, column=0, sticky="NSEW", padx=10, pady=10)

    self.entry_2 = customtkinter.CTkEntry(master=self.frame_2, placeholder_text=f"entry")
    self.entry_2.grid(row=0, column=1, sticky="NSEW", padx=10, pady=10)

    self.entry_3 = customtkinter.CTkEntry(master=self.frame_2, placeholder_text=f"entry")
    self.entry_3.grid(row=0, column=2, sticky="NSEW", padx=10, pady=10)

    self.frame_3 = customtkinter.CTkFrame(master=self.app)
    self.frame_3.grid(row=1,column=0, sticky="NSEW", pady=10)

    def add_row():

        self.canvas.itemconfigure(self.window, height=400 (50*self.xr))

        self.entry_1 = customtkinter.CTkEntry(master=self.frame_2, placeholder_text=f"entry")
        self.entry_1.grid(row=self.xr, column=0, sticky="NSEW", padx=10, pady=10)

        self.entry_2 = customtkinter.CTkEntry(master=self.frame_2, placeholder_text=f"entry")
        self.entry_2.grid(row=self.xr, column=1, sticky="NSEW", padx=10, pady=10)

        self.entry_3 = customtkinter.CTkEntry(master=self.frame_2, placeholder_text=f"entry")
        self.entry_3.grid(row=self.xr, column=2, sticky="NSEW", padx=10, pady=10)   

        self.xr  = 1

    



    button = customtkinter.CTkButton(master=self.frame_3, text="Add row", command=add_row)
    button.grid(row=0, column=1, columnspan=3, padx=10, pady=10)

root = customtkinter.CTk()
app = Adder(root)
root.mainloop()

CodePudding user response:

I hope i understood your problem correctly as the self.canvas.itemconfigure(self.window, height=400 (50*self.xr) in fact does work (you can see it getting bigger if you make the gui bigger).

The problem you are probably having is that you cant access the newly created space by scrolling. To achieve this you will need to add

            self.canvas.configure(scrollregion=self.canvas.bbox("all"))

right below your self.canvas.itemconfigure(self.window, height=400 (50*self.xr))

This let's your scrollbar work even after you change the size by clicking the button.

import customtkinter


class Adder:

    def __init__(self, app):
        self.app = app
        self.app.title("self.Scrollbar testing")
        self.app.geometry('{}x{} {} {}'.format(550, 460, 750, 250))
        self.xr = 1

        self.app.grid_rowconfigure(0, weight=1)
        self.app.grid_columnconfigure(0, weight=1)

        self.frame = customtkinter.CTkFrame(master=self.app)
        self.frame.grid(row=0, column=0, padx=15, pady=15, sticky="NSEW")

        self.frame.grid_rowconfigure(0, weight=1)
        self.frame.grid_columnconfigure(0, weight=1)

        self.canvas = customtkinter.CTkCanvas(self.frame)
        self.canvas.grid(row=0, column=0, sticky="NSEW")

        self.canvas.grid_rowconfigure(0, weight=1)
        self.canvas.grid_columnconfigure(0, weight=1)

        self.frame_2 = customtkinter.CTkFrame(master=self.canvas)

        self.scrollbar = customtkinter.CTkScrollbar(
            master=self.frame, orientation="vertical", command=self.canvas.yview, height=460, width=15)
        self.scrollbar.grid(row=0, column=0, sticky="NE")

        self.canvas.configure(yscrollcommand=self.scrollbar.set)
        self.canvas.bind("<Configure>", lambda e: self.canvas.configure(
            scrollregion=self.canvas.bbox("all")))

        self.window = self.canvas.create_window(
            (0, 0), window=self.frame_2, anchor="nw", height=400)

        self.entry_1 = customtkinter.CTkEntry(
            master=self.frame_2, placeholder_text=f"entry")
        self.entry_1.grid(row=0, column=0, sticky="NSEW", padx=10, pady=10)

        self.entry_2 = customtkinter.CTkEntry(
            master=self.frame_2, placeholder_text=f"entry")
        self.entry_2.grid(row=0, column=1, sticky="NSEW", padx=10, pady=10)

        self.entry_3 = customtkinter.CTkEntry(
            master=self.frame_2, placeholder_text=f"entry")
        self.entry_3.grid(row=0, column=2, sticky="NSEW", padx=10, pady=10)

        self.frame_3 = customtkinter.CTkFrame(master=self.app)
        self.frame_3.grid(row=1, column=0, sticky="NSEW", pady=10)

        def add_row():

            self.canvas.itemconfigure(self.window, height=400 (50*self.xr))
            self.canvas.configure(
                scrollregion=self.canvas.bbox("all"))

            self.entry_1 = customtkinter.CTkEntry(
                master=self.frame_2, placeholder_text=f"entry")
            self.entry_1.grid(row=self.xr, column=0,
                              sticky="NSEW", padx=10, pady=10)

            self.entry_2 = customtkinter.CTkEntry(
                master=self.frame_2, placeholder_text=f"entry")
            self.entry_2.grid(row=self.xr, column=1,
                              sticky="NSEW", padx=10, pady=10)

            self.entry_3 = customtkinter.CTkEntry(
                master=self.frame_2, placeholder_text=f"entry")
            self.entry_3.grid(row=self.xr, column=2,
                              sticky="NSEW", padx=10, pady=10)

            self.xr  = 1

        button = customtkinter.CTkButton(
            master=self.frame_3, text="Add row", command=add_row)
        button.grid(row=0, column=1, columnspan=3, padx=10, pady=10)


root = customtkinter.CTk()
app = Adder(root)
root.mainloop()

CodePudding user response:

Since you are using grid to manage the entry widgets in the frame, you shouldn't set the height of the canvas object. By removing both instances of height=... the frame will automatically always be tall enough to hold all of the entry widgets.

The other thing you need to do is reconfigure the scrollregion whenever the frame changes size (either by you computing the height, or by letting grid recompute it for you.

If you remove the explicit setting of the height, you can define add_row to look like this - note the final statement that was added:


def add_row():

    self.entry_1 = customtkinter.CTkEntry(master=self.frame_2, placeholder_text=f"entry")
    self.entry_1.grid(row=self.xr, column=0, sticky="NSEW", padx=10, pady=10)

    self.entry_2 = customtkinter.CTkEntry(master=self.frame_2, placeholder_text=f"entry")
    self.entry_2.grid(row=self.xr, column=1, sticky="NSEW", padx=10, pady=10)

    self.entry_3 = customtkinter.CTkEntry(master=self.frame_2, placeholder_text=f"entry")
    self.entry_3.grid(row=self.xr, column=2, sticky="NSEW", padx=10, pady=10)

    self.xr  = 1

    self.canvas.configure(scrollregion=self.canvas.bbox("all"))

  • Related