phylophase
phylophase

Reputation: 15

Why canvas not scrolling with scrollbar and auto resizing when adding widgets?

When i put widgets inside my canvas, the widgets bypass the canvas size. But when I scroll, the canvas won't move.
On top of that, the canvas auto re-sizes when I add more widgets. I thought the canvas isn't supposed to re-size because I already added a scroll bar?

Here's my code:

from tkinter import *
from tkinter import ttk
import mysql.connector

class CanvasScroll:

    def on_resize(self,event):
        self.canvas.config(width = 1185, height = 530)

    def add_crew(self):
        crewFrame = CrewFrame()


    def callback_list(self):
        index = self.notebook.index(self.notebook.select()) + 1
        self.tmpframe = Try2(self.contentframe, index)


    def __init__(self, master):
        self.canvas = Canvas(master, width = 1185, height = 530, scrollregion = (0, 0, 1216, 700), bg = 'white', confine = True)
        self.canvas.grid(row = 2, column = 0, sticky = 'news')

        self.xscroll = ttk.Scrollbar(master, orient = HORIZONTAL, command = self.canvas.xview)
        self.xscroll.grid(row = 3, column = 0, sticky = 'we')

        self.yscroll = ttk.Scrollbar(master, orient = VERTICAL, command = self.canvas.yview)
        self.yscroll.grid(row = 2, column = 1, sticky = 'ns')

        self.canvas.config(xscrollcommand = self.xscroll.set, yscrollcommand = self.yscroll.set)
        self.canvas.bind("<Configure>", self.on_resize)


        self.option = ttk.Frame(master, height = 150, width = 1206)
        self.option.grid(row = 0, column = 0, sticky = 'we', columnspan = 5)

        self.addicon = PhotoImage(file = 'C:\\Users\\rain\\Desktop\\Fyosh!\\logo\\add.gif').subsample(2,2)
        self.btnAdd = ttk.Button(self.option, image = self.addicon, text = 'Add Crew', compound = TOP, command = self.add_crew)
        self.btnAdd.grid(row = 0, column = 0, padx = 50, pady = 5)

        self.updateicon = PhotoImage(file = 'C:\\Users\\rain\\Desktop\\Fyosh!\\logo\\update.gif').subsample(2,2)
        self.btnUpdate = ttk.Button(self.option, image = self.updateicon, text = 'Update Crew', compound = TOP)
        self.btnUpdate.grid(row = 0, column = 1, padx = 50)

        self.deleteicon = PhotoImage(file = 'C:\\Users\\rain\\Desktop\\Fyosh!\\logo\\delete.gif').subsample(2,2)
        self.btnDelete = ttk.Button(self.option, image = self.deleteicon, text = 'Delete Crew', compound = TOP)
        self.btnDelete.grid(row = 0, column = 2, padx = 50)

        self.reloadicon = PhotoImage(file = 'C:\\Users\\rain\\Desktop\\Fyosh!\\logo\\Refresh.png').subsample(7,7)
        self.reloadbtn = ttk.Button(self.option, image = self.reloadicon, command = self.callback_list, text = 'Load List', compound = TOP)
        self.reloadbtn.grid(row = 0, column = 3, padx = 50)

        self.tabframe = ttk.Frame(master, height = 20)
        self.tabframe.grid(row = 1, sticky = 'we')

        self.notebook = ttk.Notebook(self.tabframe)
        self.notebook.grid(row = 0, column = 0, sticky = 'we')

        db = mysql.connector.connect(user = 'root', password = '', host = 'localhost', database = 'fat2x_payroll')
        cursor = db.cursor()

        ships = ("SELECT * from tbl_shiplist")

        try:
            cursor.execute(ships)
            result = cursor.fetchall()
            self.tab = {}
            for row in result:
                self.tab[row[0]] = {
                    "shipname": ttk.Frame(self.notebook)
                    }
                self.notebook.add(self.tab[row[0]]["shipname"], text = row[1])
                db.close()

        except:
            messagebox.showinfo("alert", "ship list error")

        self.canvas.label = ttk.Label(self.canvas, text = "hahahahahha").grid(column = 0)
        self.canvas.label1 = ttk.Label(self.canvas, text = "hahahahahha").grid(column = 1)
        self.canvas.label2 = ttk.Label(self.canvas, text = "hahahahahha").grid(column = 2)
        self.canvas.label3 = ttk.Label(self.canvas, text = "hahahahahha").grid(column = 3)
        self.canvas.label4 = ttk.Label(self.canvas, text = "hahahahahha").grid(column = 4)
        self.canvas.label5 = ttk.Label(self.canvas, text = "hahahahahha").grid(column = 5)
        self.canvas.label6 = ttk.Label(self.canvas, text = "hahahahahha").grid(column = 6)
        self.canvas.label7 = ttk.Label(self.canvas, text = "hahahahahha").grid(column = 7)
        self.canvas.label8 = ttk.Label(self.canvas, text = "hahahahahha").grid(column = 8)

def start():
    master = Tk()
    master.geometry("1206x690+10+10")
    master.resizable(0,0)
    master.title("Crew Panel")
    canvasScroll = CanvasScroll(master)

if __name__ == "__main__":
    start()

Upvotes: 1

Views: 1152

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 385980

The canvas can only scroll objects that are embedded on the canvas. In the case of widgets, that means that you've called the create_window method of the canvas for the widgets you want to be affected by the scrollbar.

If you want to use grid to organize widgets, and you want those widgets to be in a scrollable container, the usual method is to put those widgets inside a frame, and then add the frame to the canvas with create_window. You can see an example of this technique in this answer: https://stackoverflow.com/a/3092341/7432

As for the auto-resize, this behavior is completely unrelated to using a scrollbar. If you use grid or pack on a widget, the parent will always resize unless you've turned geometry propagation off. It doesn't matter if it's a Canvas or a Frame or a Toplevel, or any other class of widget.

Upvotes: 1

Related Questions