Tkinter, I cannot get my slider to show all buttons

Here is a sample of what I am doing. I put 500 buttons on a sliding canvas, and I can only scroll to button 109. What am I doing wrong? I've tried adjusting the width on the widgets, as well as the scrollregion. I'm sure I'm overlooking something simple.

import Tkinter
from Tkinter import *
import os, signal

window1 = Tkinter.Tk()
window1.attributes('-fullscreen', True)
window1.bind("<Escape>", lambda e: e.widget.quit())

window2 = Tkinter.Label(window1)
window2.configure(bg = "blue")
window2.place(x=0, y=0, relwidth=1, relheight=1)

frame=Frame(window2, height=160)
frame.pack(anchor=Tkinter.SW,side=Tkinter.BOTTOM)

canvas=Canvas(frame,bg='black', width=5500, height=160, scrollregion=(0,0,5500,0))

hbar=Scrollbar(frame,orient=HORIZONTAL, bg='black', troughcolor='black')
hbar.pack(side=BOTTOM,fill=X)
hbar.config(command=canvas.xview)

canvas.config(xscrollcommand=hbar.set, xscrollincrement=4.5)
canvas.pack(side=LEFT,expand=True,fill=BOTH)
frm = Frame(canvas)
canvas.create_window(0, 0, window=frm, anchor='nw')

def quit():
    window1.quit()

count = 0
while (count < 500):
    X = Tkinter.Button(frm, text=str(count), height=6, width=5, padx=0, pady=0, highlightcolor="blue", highlightthickness=3, command=quit)
    X.pack(side = "left")
    count = count + 1

window1.mainloop()

Answers


The problem is that your scrollregion on the Canvas instance isn't wide enough. You can calculate how wide it needs to be based on the requested width of all the buttons, and then set the scrollregion after you've made all the buttons, like this:

import Tkinter
import os, signal

window1 = Tkinter.Tk()
window1.attributes('-fullscreen', True)
window1.bind("<Escape>", lambda e: e.widget.quit())

window2 = Tkinter.Label(window1)
window2.configure(bg = "blue")
window2.place(x=0, y=0, relwidth=1, relheight=1)

frame = Tkinter.Frame(window2, height=160)
frame.pack(anchor=Tkinter.SW,side=Tkinter.BOTTOM)

canvas=Tkinter.Canvas(frame,bg='black', width=5500, height=160)

hbar=Tkinter.Scrollbar(frame,orient=Tkinter.HORIZONTAL, bg='black', troughcolor='black')
hbar.pack(side=Tkinter.BOTTOM,fill=Tkinter.X)
hbar.config(command=canvas.xview)

canvas.config(xscrollcommand=hbar.set, xscrollincrement=4.5)
canvas.pack(side=Tkinter.LEFT, expand=True, fill=Tkinter.BOTH)
frm = Tkinter.Frame(canvas)
canvas.create_window(0, 0, window=frm, anchor='nw')

def quit():
    window1.quit()

count = 0
width = 0
while (count < 500):
    X = Tkinter.Button(frm, text=str(count), height=6, width=5, padx=0, pady=0, highlightcolor="blue", highlightthickness=3, command=quit)
    X.pack(side = "left")
    width += X.winfo_reqwidth()
    count = count + 1

canvas.config(scrollregion=(0, 0, width, 0))
window1.mainloop()

As a side note, your first two import statements are redundant. In this example, I dropped the second one to avoid polluting the global namespace.


Need Your Help

Delete Anonymous Objects in C++

c++ memory-management new-operator

In C++, if you pass an anonymous object as an argument to a named object method, does the anonymous object get deleted when you delete the named object?