Home > Mobile >  Jiggling borders in tkinter
Jiggling borders in tkinter

Time:10-21

Building an interface in tk/tkinter that will consist of numerous frames of various size, all of which will be populated with buttons and labels and text fields (lots of frame.pack() & frame.destroy going on). I decided to start by populating the root frame with a 6x4 grid and then overlaying that with the temporary frames as needed. My main goal is to have the frames/labels size out according the user's aspect ratio (adhering to the row/column weights I establish), but then having the borders lock into position once propagated.

Below is a simplified example of what I'm talking about (the colors are just for spacing/clarity):

import random


class CharacterInterface:
    def __init__(self, master):
        self.display_text = ['']
        self.master = master
        self.master.attributes('-fullscreen', True)
        self.master.title("Interface Template")
        self.master.configure(bg='#000000')

        # generates a 6x4 grid to underpin the interface/keep things spaced out
        for i in range(6):
            for j in range(4):
                self.master.grid_columnconfigure(i, weight=1)
                self.master.grid_rowconfigure(j, weight=1)
                self.dummy_frame = tk.Frame(self.master, relief=tk.RIDGE, borderwidth=4,
                                            bg='#'   str(2 * j)   str(2 * j)   str(2 * j)   str(i)   str(i)   str(i))
                self.dummy_label = tk.Label(master=self.dummy_frame,
                                            bg='#'   str(i)   str(i)   str(i)   str(2 * j)   str(2 * j)   str(2 * j))
                self.dummy_frame.grid(row=j, column=i, sticky='nsew')
                self.dummy_label.pack(ipadx=8, ipady=8, fill="both", expand=True)

        self.ch_frame = tk.Frame(self.master, bg='#000077')
        self.ch_frame.grid(row=0, column=0, rowspan=2, columnspan=3, sticky="nsew")
        self.ch_frame.grid_propagate(False)                     # this locks ch_frame's right border
        self.ch_frame.grid_columnconfigure(0, weight=1)
        self.ch_frame.grid_columnconfigure(1, weight=3)
        self.ch_frame.grid_rowconfigure(0, weight=1)
        self.ch_frame.grid_rowconfigure(1, weight=6)
        self.chtop_label = tk.Label(master=self.ch_frame, relief=tk.RIDGE, borderwidth=4, fg="#FFFFFF", bg='#000000',
                                    font=('Courier', 12), justify="left", anchor='nw')
        self.chtop_label.grid(row=0, column=0, columnspan=2, sticky='nsew')
        self.chleft_label = tk.Label(master=self.ch_frame, relief=tk.RIDGE, borderwidth=4, fg="#FFFFFF", bg='#000000',
                                     font=('Courier', 12), justify="left", anchor='nw')
        self.chleft_label.grid(row=1, column=0, sticky='nsew')
        self.chright_label = tk.Label(master=self.ch_frame, relief=tk.RIDGE, borderwidth=4, fg="#FFFFFF",
                                      bg='#000000', font=('Courier', 12), justify="left", anchor='nw')
        self.chright_label.grid(row=1, column=1, sticky='nsew')

        self.test_button = tk.Button(self.chright_label, text="test", bg='#000000', fg="#FFFFFF",
                                      font=('Courier', 12), relief=tk.FLAT, anchor='w', command=lambda: self.toss())
        self.test_button.pack(side='left')

    def toss(self):
        self.test_button.pack_forget()
        str_length, str_instance = random.randrange(1, 10), ""
        for i in range(str_length):
            str_instance = str_instance   'a'
        self.chleft_label['text'] = str_instance
        self.test_button.pack(side='left')


root = tk.Tk()
my_gui = CharacterInterface(root)
root.mainloop()

So here the 6x4 grid is formed, and the self.ch_frame.grid_propagate(False) setting locks in that right border on ch_frame (the parent frame to the three labels I've created). But if you click the button it will create a little string in chleft_label and that middle label border starts wiggling around on me.

Is there a way for me to lock that border in place WITHOUT using place() or assigning a width value? I suppose I could stick a placeholder string in chleft_label, but I would prefer to lock it with propagate commands rather than crummy workarounds (I'm going to be juggling a ton of these frames). I could also work around it by abandoning the grid format inside ch_frame, but then I'm losing some of the core functionality I want (only updating the frames/labels as needed).

Is this a dead end, trying to assert this sort of border positioning in a grid/pack interface?

Thanks!

CodePudding user response:

@acw1668 nailed it - I just needed to add a uniform=1 parameter to my self.ch_frame.grid_columnconfigure()s. The definition was staring right at me in the documentation:

"The space for columns belonging to a uniform group is allocated so that their sizes are always in strict proportion to their -weight values"

  • Related