Проблема связана с порядком, в котором вы упаковываете виджеты. Идея состоит в том, что пакет использует оставшееся пространство для размещения оставшегося, поэтому вам нужно упаковать сначала полосы прокрутки, а затем холст:
import tkinter as tk
from tkinter import ttk
root=tk.Tk()
frame=tk.Frame(root)
frame.pack()
canvas=tk.Canvas(frame, height=200, width=200, background="blue")
yscrollbar=tk.Scrollbar(frame, orient=tk.VERTICAL, command=canvas.yview)
xscrollbar=tk.Scrollbar(frame, orient=tk.HORIZONTAL, command=canvas.xview)
xscrollbar.pack(side=tk.BOTTOM, fill=tk.X)
yscrollbar.pack(side=tk.RIGHT, fill=tk.Y)
canvas.pack(side=tk.LEFT)
canvas.configure(yscrollcommand=yscrollbar.set)
canvas.configure(xscrollcommand=xscrollbar.set)
root.mainloop()

Однако, поскольку pack
не так интуитивно понятен, когда речь идет о более сложных GUI, я предпочитаю использовать grid
:
xscrollbar.grid(row=1, column=0, sticky='ew')
yscrollbar.grid(row=0, column=1, sticky='ns')
canvas.grid(row=0, column=0, sticky='ewns')
Но в этом случае, если вы хотите GUI для правильного изменения размера вам нужно будет добавить
frame.columnconfigure(0, weight=1)
frame.rowconfigure(0, weight=1)
, чтобы строка и столбец 0 сетки заполняли все доступное пространство.