Reputation: 3
I recently learned about the Notebook widget. And I wanted to add tabs dynamically.
from tkinter import *
from tkinter import ttk
root = Tk ()
n = ttk.Notebook (root)
n.pack (fill = X)
tab = 1
def new_tab ():
global tab
text = Text (root)
text.pack ()
n.add (text, text = ("tab" + str (tab)))
tab += 1
def check ():
'' 'code to insert text into Text widget' ''
...
plus = Button (root, text = '+', command = new_tab)
plus.pack (side = LEFT)
check_button = Button (root, text = 'check', command = check)
check_button.pack (side = LEFT)
root.mainloop ()
I added tabs, but when I try to insert any text using insert in the check function, python gives an error. But the problem is not entirely a bug. I wanted to insert text into the text widget in the current tab.
Upvotes: 0
Views: 748
Reputation: 123531
You need to make a text widget that exists outside of the new_tab()
function — in your code it's a local variable which cannot be accessed after the function returns.
A simple way (but not the best, since global variables are bad) is to make the text
variable a global. A better way would be to use classes to encapsulate your application's data.
Here's an example of the former:
from tkinter import *
from tkinter import ttk
root = Tk()
n = ttk.Notebook(root)
n.pack(fill=X)
tab = 1
text = None
def new_tab():
global tab
global text
text = Text(root)
text.pack()
n.add(text, text=("tab" + str(tab)))
tab += 1
def check():
""" Insert text into Text widget if it exists. """
if text:
text.insert(END, 'new text\n')
plus = Button(root, text='+', command=new_tab)
plus.pack(side=LEFT)
check_button = Button(root, text='check', command=check)
check_button.pack(side=LEFT)
root.mainloop()
For comparison, here's an example of the latter which has a minimal number of globals because it's based on the object-oriented programming paradigm, aka the OOP way, of implementing software — namely by defining a class that encapsulates the whole application.
Note I've also changed how the import
s are being done because, for the most part, wildcard imports are also considered a poor programming practice (see Should wildcard import be avoided?).
import tkinter as tk
import tkinter.ttk as ttk
from tkinter.constants import *
class MyApplication(tk.Tk):
def __init__(self):
super().__init__()
self.nb = ttk.Notebook(self)
self.nb.pack(fill=X)
self.tab = 1
self.text = None
self.plus = tk.Button(self, text='+', command=self.new_tab)
self.plus.pack(side=LEFT)
self.check_button = tk.Button(self, text='check', command=self.check)
self.check_button.pack(side=LEFT)
def new_tab(self):
self.text = tk.Text(self)
self.text.pack()
self.nb.add(self.text, text=("tab" + str(self.tab)))
self.tab += 1
def check(self):
""" Insert text into Text widget if it exists. """
if self.text:
self.text.insert(END, 'new text\n')
app = MyApplication()
app.mainloop()
Upvotes: 2