python Can I duplicate a listbox in two notebook pages

Question:

I’m using python 3.4 and tkinter. I have a notebook with two pages. I have a listbox that needs to be on both pages.

I’m wondering if I can setup the listbox once and use it on both pages, or if I need to setup a separate listbox on each page and manage both as the list box in one page changes?

Asked By: user1904898

||

Answers:

You cannot pack/grid/place the listbox inside two different frames simultaneously.

However, you can re-pack/grid/place the listbox each time the notebook tab changes. To do so, I used the <<NotebookTabChanged>> event which is triggered each time the notebook tab changes:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()

notebook = ttk.Notebook(root)
notebook.pack()

frame1 = tk.Frame(notebook, bg='red', width=400, height=400)
frame1.pack_propagate(False)

frame2 = tk.Frame(notebook, bg='blue', width=400, height=400)
frame2.pack_propagate(False)

notebook.add(frame1, text='frame 1')
notebook.add(frame2, text='frame 2')

var = tk.StringVar(root, 'a b c d e f g')
listbox = tk.Listbox(notebook, listvariable=var)

def display_listbox(event):
    tab = notebook.tabs()[notebook.index('current')]
    listbox.pack(in_=tab)

notebook.bind('<<NotebookTabChanged>>', display_listbox)

root.mainloop()

Explanations about display_listbox:

  • notebook.tabs() returns (frame1, frame2) (i.e the tuple of the tabs)
  • notebook.index('current') returns the index of the currently visible tab
  • the in_ option can be used to specify the widget in which we want to pack the listbox (it also works with grid and place)
Answered By: j_4321

Sharing the same listvariable between the two list boxes is sufficient to keep them synchronized.

import tkinter as tk
from tkinter import ttk

rootWin = tk.Tk()
rootWin.title('Talk Like A Pirate')

listvar = tk.StringVar()

#create a notebook
pirateBook = ttk.Notebook(rootWin)

#create a tab
tab1 = tk.Frame(pirateBook)

#create a listbox in the tab
listbx1 = tk.Listbox(tab1,
    listvariable=listvar,
    height=21,
    width=56,
    selectmode='single'
    )
listbx1.pack()

#create another tab
tab2 = tk.Frame(pirateBook)

#create a listbox in the second tab
listbx2 = tk.Listbox(tab2,
    listvariable=listvar,
    height=21,
    width=56,
    selectmode='single'
    )
listbx2.pack()

#add the tabs to the notebook
pirateBook.add(tab1, text="Tab 1")
pirateBook.add(tab2, text="Tab 2")

#pack the notebook
pirateBook.pack()

#you can access the listbox through the listvariable, but that takes
#   a list as the argument so you'll need to build a list first:
ls=list()   #or you could just ls = []

#build a list for the list box
ls.append("Arr, matey!")
ls.append("Dead men tell no tales!")
ls.append("Heave ho, me hearties!")
ls.append("I'll cleave ye t'yer brisket a'fore sendin' ye to Davey Jones Locker!")

#then just set the list variable with the list
listvar.set(ls)

#or you can manipulate the data using Listbox()'s data manipulation
#   methods, such as .insert()
listbx1.insert(1, "Shiver me timbers!")
listbx2.insert(3, "Yo ho ho!")
listbx1.insert(5, "Ye scurvy dog!")
listbx2.insert('end', "Ye'll be walking the plank, Sharkbait!")

#you'll see this if you run this program from the command line
print(listbx1.get(5))

rootWin.mainloop()

You would do this a little bit differently if you had your tabs in their own classes, making the common variable global, for instance, but the same idea still applies: sharing a common listvariable.

Answered By: Ian Moote
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.