2

I'm new to tkinter and I don't quite get it yet. I want to creat a scrollable table on a canvas using labels in a grid. I've seen some examples using the pack-manager which leads to even more chaos in my ui so I figured I'd rather stick with grid. However regardless of how many cells I choose the canvas and frame expand accordingly to display all cells hence leaving no scrollable region. How do I deal with this problem?

Any help is greatly appreciated. Many thanks in advance.

import tkinter as tk

def start_gui():
    main_window = MainWindow()
    main_window.set_grid(20,4)
    main_window.root.mainloop()

class MainWindow:
    def __init__(self, root = tk.Tk()):
        self.root = root
        self.root.title('Some Table')

        self.frame = tk.Frame(root, width=100, height=100)
        self.frame.grid(row = 0, column = 0)

        self.canvas = tk.Canvas(self.frame, width = 100, height = 100)
        self.canvas.configure(scrollregion=(0, 0, 0, 1000))
        self.canvas.grid(row = 0, column = 0)

        self.vbar = tk.Scrollbar(self.frame, orient = 'vertical', command= self.canvas.yview)
        self.vbar.grid(row = 0, column = 1, sticky = 'ns')

        self.canvas.config(yscrollcommand = self.vbar.set)

    def set_grid(self, rows, columns):
        for i in range(rows):
            for j in range(columns):
                label = tk.Label(self.canvas, text = 'some label', relief = 'solid', width = 20)
                label.grid(row = i, column = j)

if __name__ == '__main__':
    start_gui()
2
  • to add to canvas use canvas.create_window(..., window=label) and remove label.grid() - or put Frame to Canvas (create_window) and then put Labels in Frame Commented Jul 22, 2019 at 10:22
  • @furas Thanks for your reply. I've seen that before and tried it. I really don't understand how to use create_window. It only played havoc on my ui and I don't know how to uniformly create a table with that method. Commented Jul 22, 2019 at 13:34

1 Answer 1

2

Welcome to stackoverflow.

You're not far away. I've amended your code to make both Canvas and Scrollbar children of root. Frame is a child of canvas but is displayed as a Canvas window object, not by using grid.

A config callback is bound to a Frame configure event to set the Canvas scrollarea to be the Frame size as Frame changes size with it's contents.

import tkinter as tk

def start_gui():
    main_window = MainWindow()
    main_window.set_grid(20,4)
    main_window.root.mainloop()

class MainWindow:
    def __init__(self, root = tk.Tk()):
        self.root = root
        self.root.title('Some Table')
        root.columnconfigure( 0, weight=1 ) # Stretch Column 0 to fit width.
        root.rowconfigure( 0, weight=1 ) # Stretch row 0 to fit height.

        self.canvas = tk.Canvas(root)
        self.canvas.grid(row = 0, column = 0, sticky = 'nsew')
        # Make canvas fit the whole of root. Useful to play with sizes.

        self.frame = tk.Frame(self.canvas)
        self.canvas.create_window( 0, 0, window = self.frame, anchor=tk.NW )
        # Makes frame an object in canvas

        self.vbar = tk.Scrollbar(root, orient = 'vertical', command= self.canvas.yview)
        # The scrollbar is a child of root.
        self.vbar.grid(row = 0, column = 1, sticky = 'ns')

        self.canvas.config(yscrollcommand = self.vbar.set)

        self.frame.bind('<Configure>', self.on_config) 
        # Bind on_config to a Frame config event.

    def on_config( self, e ):
        # print(e.widget, e)
        # Set the canvas scrollregion to fit the whole of frame.
        self.canvas.configure(scrollregion=(0, 0, e.width, e.height))

    def set_grid(self, rows, columns):
        for i in range(rows):
            for j in range(columns):
                tk.Label(self.frame, text = str(i)+' : '+str(j), width = 20).grid(row = i, column = j)

if __name__ == '__main__':
    start_gui()
Sign up to request clarification or add additional context in comments.

2 Comments

@ReblochonMasque I did that already. For some reason it's not working. Apologies. Ofcourse I'd like to give credit where it's due.
If you feel like you didn't get the credit you rightfully deserve I'm very sorry. For some reason this website doesn't allow me to upvote your comment. I also clicked on the anwser solved button and now I'm seeing it wasn't accepted. Maybe I didn't even tag you properly. Hope you're reading this. And thanks again

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.