Question

I have 3 tabs in a notebook widget, and I want to have a scrollable frame on the 3rd tab. I set up a canvas and a scrollbar and set all the commands for them to interact, but it's not working. What am I doing wrong? Full runnable code is below:

import subprocess
from Tkinter import *
from ttk import *
import piper as Piper
import sqlite3



def confCanvas(event):
    global viewKeysCanvas
    print "ConfCanvasEvent\n";
    viewKeysCanvas.configure(scrollregion=viewKeysCanvas.bbox("all"))



root =Tk()

sizex = 800
sizey = 500
posx  = 100
posy  = 100
root.wm_geometry("%dx%d+%d+%d" % (sizex, sizey, posx, posy))

root.title('Scroll Test')

note = Notebook(root)

tab1 = Frame(note)
tab2 = Frame(note)
tab3 = Frame(note)

tab1.pack()
tab2.pack()
tab3.pack(fill=BOTH, expand=True)



#tab1
printGroup = Frame(tab1)
Label(printGroup, text="Test label1").pack()
printGroup.pack()

#tab2
bulkGroup = Frame(tab2)
Label(bulkGroup, text="Test label2").pack()
bulkGroup.pack()


#tab3
vkFrame = Frame(tab3)
viewKeysCanvas = Canvas(vkFrame)
viewKeysGroup = Frame(viewKeysCanvas)
viewKeysScrollbar = Scrollbar(vkFrame, orient="vertical", command=viewKeysCanvas.yview)
viewKeysCanvas.configure(yscrollcommand=viewKeysScrollbar.set)

viewKeysScrollbar.pack(side=RIGHT, fill=Y)
viewKeysCanvas.pack(fill="both", expand=True)
viewKeysCanvas.create_window((0,0), window=tab3)
vkFrame.bind("<Configure>",confCanvas)
vkFrame.pack()

for x in range(0, 9):
    aKeyGroup = LabelFrame(viewKeysGroup, text="number: "+str(x))
    buttonFrame = Frame(aKeyGroup)
    Button(buttonFrame, text="Action 1").pack(padx=10, side=LEFT)
    Button(buttonFrame, text="Action 2").pack(padx=10, side=LEFT)
    Label(aKeyGroup, text="Public key: ").pack(side=TOP)
    Label(aKeyGroup, text="Private key: ").pack(side=TOP)
    buttonFrame.pack(padx=10, pady=10)      
    aKeyGroup.pack()



viewKeysGroup.pack(padx=10, pady=10)


note.add(tab1, text = "Test tab 1")
note.add(tab2, text = "Test tab 2")
note.add(tab3, text = "Test tab 3")


note.pack(expand=True, fill=BOTH)


root.mainloop()

I'm working with Python 2.7.3 on Debian with LXDE. I'm an experienced programmer but I'm new to Python, so please let me know if anything else I'm doing is wrong. Thanks for your help!

Was it helpful?

Solution

To get your code to work with the least amount of modification, change

viewKeysCanvas.create_window((0,0), window=tab3)

to

viewKeysCanvas.create_window((0,0), window=viewKeysGroup)

and remove

# viewKeysGroup.pack(padx=10, pady=10)

I found this out by starting from this example and then modifying it to to look more like your code. Since I modified it incrementally, I always had a working scrollable canvas. When the GUIs looked about the same, I simply compared what lines were different. Below is the code I ended up with.

I'm sorry I can't explain why these changes are necessary. I suppose changing tab3 to viewKeysGroup is plausible, but why you should refrain from packing the viewKeysGroup is beyond me.


import Tkinter as tk
import ttk

class Tab1(tk.Frame):
    def __init__(self, root):
        tk.Frame.__init__(self, root)
        tk.Label(self, text="Test label1").pack()

class Tab2(tk.Frame):
    def __init__(self, root):
        tk.Frame.__init__(self, root)
        tk.Label(self, text="Test label2").pack()

class Tab3(tk.Frame):
    def __init__(self, root):
        tk.Frame.__init__(self, root)
        self.viewKeysCanvas = tk.Canvas(self)
        self.viewKeysGroup = tk.Frame(self.viewKeysCanvas)
        self.viewKeysScrollbar = tk.Scrollbar(self, orient="vertical",
                                command=self.viewKeysCanvas.yview)
        self.viewKeysCanvas.configure(yscrollcommand=self.viewKeysScrollbar.set)
        self.viewKeysScrollbar.pack(side="right", fill="y")
        self.viewKeysCanvas.pack(fill="both", expand=True)
        self.viewKeysCanvas.create_window(0, 0, window=self.viewKeysGroup, anchor="nw")
        self.viewKeysGroup.bind("<Configure>", self.on_frame_configure)
        self.populate()

    def populate(self):
        for x in range(0, 9):
            aKeyGroup = tk.LabelFrame(self.viewKeysGroup, text="number: " + str(x))
            buttonFrame = tk.Frame(aKeyGroup)
            tk.Button(buttonFrame, text="Action 1").pack(padx=10, side="left")
            tk.Button(buttonFrame, text="Action 2").pack(padx=10, side="left")
            tk.Label(aKeyGroup, text="Public key: ").pack(side="top")
            tk.Label(aKeyGroup, text="Private key: ").pack(side="top")
            buttonFrame.pack(padx=10, pady=10)
            aKeyGroup.pack()

    def on_frame_configure(self, event):
        """Reset the scroll region to encompass the inner frame"""
        self.viewKeysCanvas.configure(scrollregion=self.viewKeysCanvas.bbox("all"))

root = tk.Tk()
sizex, sizey, posx, posy = 800, 500, 100, 100
root.wm_geometry("%dx%d+%d+%d" % (sizex, sizey, posx, posy))
root.title('Scroll Test')

note = ttk.Notebook(root)
tab1 = Tab1(note)
tab2 = Tab2(note)
tab3 = Tab3(note)

note.add(tab1, text="Test tab 1")
note.add(tab2, text="Test tab 2")
note.add(tab3, text="Test tab 3")

note.pack(expand=True, fill="both")
root.mainloop()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top