I am working on a small texteditor in python. With app being my master i am trying to implement a textWidget, in which i want to place a functional scrollbar.
The problem i am facing is following:
In order to have a textWidget to place my scrollbar in, i have to implement my textWidget first. But already as an argument in Tk.Text i need to place the yscrollcommand for my scrollbar. Which means that my textWidget will not know what my scrollbar is.
If i turn it around i am not able to create my scrollbar within the textWidget, because it is not yet created.
First example where my textWidget is created first
# MENU BAR EXAMPLE
menu_bar = Tk.Menu()
# Set menu bar as menu for the app
app.config(menu=menu_bar)
# Fill menubar with "File" menu
filemenu = Tk.Menu(app,menu_bar, tearoff=0)
#filemenu.add_command(label="Exit", command=exit)
menu_bar.add_cascade(label="File", menu=filemenu)
menu_bar.add_cascade(label="File2", menu=filemenu)
filemenu.add_command(label="Exit", command=exit)
# BUTTON EXAMPLE
button = Tk.Button(app, text="Exit", command=quit)
button.pack(side=Tk.BOTTOM, fill=Tk.X)
# TEXT WIDGET
textWidget = Tk.Text(textWidget, yscrollcommand=scrollbar.set)
textWidget.pack(expand=True,fill=Tk.BOTH)
# SCROLLBAR
scrollbar=Tk.Scrollbar(textWidget)
scrollbar.pack(side=Tk.RIGHT, fill= Tk.Y)
scrollbar.config(command=textWidget.yview)
#Start the main event loop (i.e. run the tkinter program)
app.mainloop()
######################################################
Second example where scrollbar is created first
# MENU BAR EXAMPLE
menu_bar = Tk.Menu()
# Set menu bar as menu for the app
app.config(menu=menu_bar)
# Fill menubar with "File" menu
filemenu = Tk.Menu(app,menu_bar, tearoff=0)
#filemenu.add_command(label="Exit", command=exit)
menu_bar.add_cascade(label="File", menu=filemenu)
menu_bar.add_cascade(label="File2", menu=filemenu)
filemenu.add_command(label="Exit", command=exit)
# BUTTON EXAMPLE
button = Tk.Button(app, text="Exit", command=quit)
button.pack(side=Tk.BOTTOM, fill=Tk.X)
# SCROLLBAR
scrollbar=Tk.Scrollbar(textWidget)
scrollbar.pack(side=Tk.RIGHT, fill= Tk.Y)
scrollbar.config(command=textWidget.yview)
# TEXT WIDGET
textWidget = Tk.Text(textWidget, yscrollcommand=scrollbar.set)
textWidget.pack(expand=True,fill=Tk.BOTH)
And this is how i had to do to make it work. But it feelsBadMan if i have to create a textWidget, create a scrollbar and then create a textWidget again.
# MENU BAR EXAMPLE
menu_bar = Tk.Menu()
# Set menu bar as menu for the app
app.config(menu=menu_bar)
# Fill menubar with "File" menu
filemenu = Tk.Menu(app,menu_bar, tearoff=0)
#filemenu.add_command(label="Exit", command=exit)
menu_bar.add_cascade(label="File", menu=filemenu)
menu_bar.add_cascade(label="File2", menu=filemenu)
filemenu.add_command(label="Exit", command=exit)
# BUTTON EXAMPLE
button = Tk.Button(app, text="Exit", command=quit)
button.pack(side=Tk.BOTTOM, fill=Tk.X)
# TEXT WIDGET
textWidget = Tk.Text(app)
textWidget.pack(expand=True,fill=Tk.BOTH)
# SCROLLBAR
scrollbar=Tk.Scrollbar(textWidget)
scrollbar.pack(side=Tk.RIGHT, fill= Tk.Y)
textWidget = Tk.Text(textWidget, yscrollcommand=scrollbar.set) # <--- Creating textWidget again
#textWidget.pack(side=Tk.LEFT, fill=Tk.BOTH)
scrollbar.config(command=textWidget.yview)
textWidget.pack(expand=True,fill=Tk.BOTH)
# Start the main event loop (i.e. run the tkinter program)
app.mainloop()
Any ideas? =)
It takes three steps:
create the text widget
create the scrollbar, and link it to the text widget
link the text widget to the scrollbar
You can reverse the order if you want: create the scrollbar, then the text, then configure the scrollbar. Also, the scrollbar should not be placed inside the text widget. The text widget and the scrollbar typically share the same parent.
Example:
textWidget = Tk.Text(app)
scrollbar = Tk.Scrollbar(app, command=textWidget.yview)
textWidget.configure(yscrollcommand=scrollbar.set)
Related
I want to make a window to display data stored inside dictionaries. I have created a canvas, scrollbar and a frame inside the canvas to place my Text widgets to display the information. When I execute my code the layout is just as I want it, but the bar is missing from the scroll bar and I can't figure out why. Here is my code for the GUI portion:
root = Tk()
# create top part
top=Frame(root)
# create a canvas to scroll
holder = Canvas(top)
# create scroll bar
scroll = Scrollbar(top, orient=VERTICAL, command=holder.yview)
# configure scrollbar for canvas
holder.configure(yscrollcommand=scroll.set)
holder.bind('<Configure>', lambda e: holder.configure(scrollregion=holder.bbox("all")))
# create frame for content inside canvas and add it to the canvas
content = Frame(holder, relief=RAISED)
holder.create_window(0, 0, window=content, anchor='nw')
# create bottom part
bottom = Frame(root, relief=SUNKEN)
root.rowconfigure(0, weight=18)
root.rowconfigure(1, weight=1, minsize=50)
root.columnconfigure(0, weight=1)
holder.pack(side=LEFT, fill=BOTH, expand=1)
scroll.pack(side=RIGHT, fill=Y)
content.pack(fill=X)
top.grid(row=0, column=0, sticky='NSEW')
bottom.grid(row=1, column=0, sticky='NSEW')
num=0
for site in sites:
temp=Text(content, height = 5)
temp.configure(state= DISABLED)
temp.pack(fill=X, side=TOP, padx= 5, pady= 5)
siteBoxes.append(temp)
num += 1
root.mainloop()
here is a screenshot of what the result looks like
Program GUI screenshot
there are that many text boxes there just to test the scrollbar, the data display within the Text widgets haven't been written yet.
I found the culprit, it was the line content.pack(fill=X), since I already have it in the window of the canvas this line of code was causing the issue. How ever now the Text widget no longer spans all of the horizontal space, how would I fix this issue while still using .create_window()?
I have just started using Tkinter and I have a frame insdie of a canvas placed using the create_window funcion so that I may have a working scrollbar for my program. The issue is the Text widgets that I place in the frame inside of the canvas is not spanning horizontally inside the canvas and I have no idea how to make this happen. I have tried using pack() or grid() and grid_rowconfigure, but if I don't use create_window then the bar on my scroll bar disappears. I can't seem to find any post that addresses this issue, but I may be wrong. Here is the snippet of my code that deals with the GUI of this window:
root = Tk()
# create top part
top=Frame(root)
# create a canvas to scroll
holder = Canvas(top)
# create scroll bar
scroll = Scrollbar(top, orient=VERTICAL, command=holder.yview)
# configure scrollbar for canvas
holder.configure(yscrollcommand=scroll.set)
holder.bind('<Configure>', lambda e: holder.configure(scrollregion=holder.bbox("all")))
# create frame for content inside canvas and add it to the canvas
content = Frame(holder, relief=RAISED)
holder.create_window((0,0), window=content, anchor='nw')
# create bottom part
bottom = Frame(root, relief=SUNKEN)
root.rowconfigure(0, weight=18)
root.rowconfigure(1, weight=1, minsize=50)
root.columnconfigure(0, weight=1)
holder.pack(side=LEFT, fill=BOTH, expand=1)
scroll.pack(side=RIGHT, fill=Y)
top.grid(row=0, column=0, sticky='NSEW')
bottom.grid(row=1, column=0, sticky='NSEW')
num=0
for site in sites:
temp=Text(content, height = 5)
temp.configure(state= DISABLED)
temp.pack(fill=X, side=TOP, padx= 5, pady= 5)
siteBoxes.append(temp)
num += 1
root.mainloop()
First, you should update scrollregion of holder whenever the internal frame content (not the canvas holder) is resized.
Second, you can update the width of the internal frame content whenever the canvas holder is resized.
Below is the updated code:
root = Tk()
# create top part
top=Frame(root)
# create a canvas to scroll
holder = Canvas(top)
# create scroll bar
scroll = Scrollbar(top, orient=VERTICAL, command=holder.yview)
# configure scrollbar for canvas
holder.configure(yscrollcommand=scroll.set)
### --- expand the width of the internal frame to the width of canvas
holder.bind('<Configure>', lambda e: holder.itemconfigure(internal, width=e.width))
# create frame for content inside canvas and add it to the canvas
content = Frame(holder, relief=RAISED)
### --- update scrollregion whenever the internal frame is resized
content.bind('<Configure>', lambda e: holder.configure(scrollregion=holder.bbox("all")))
### --- save the item ID of the internal frame
internal = holder.create_window((0,0), window=content, anchor='nw')
# create bottom part
bottom = Frame(root, relief=SUNKEN)
root.rowconfigure(0, weight=18)
root.rowconfigure(1, weight=1, minsize=50)
root.columnconfigure(0, weight=1)
holder.pack(side=LEFT, fill=BOTH, expand=1)
scroll.pack(side=RIGHT, fill=Y)
top.grid(row=0, column=0, sticky='NSEW')
bottom.grid(row=1, column=0, sticky='NSEW')
num=0
for site in sites:
temp=Text(content, height = 5)
temp.configure(state= DISABLED)
temp.pack(fill=X, side=TOP, padx= 5, pady= 5)
siteBoxes.append(temp)
num += 1
root.mainloop()
So I wanted to implement a scrollbar on the mainframe in Tkinter however that is not possible thus I have to use Canvas. With canvas, I am able to implement a scrollbar and use other widgets accordingly. Everything worked fine until I attempted to add widgets into the Canvas.
Error Faced: Scrollbar looks off and unable to scroll
So what did I do wrong and how can I fix it?
Code (Python 3.8.2)
from tkinter import *
root = Tk()
root.geometry("950x600")
# create canvas
canvas = Canvas(root, width=932, height=600, borderwidth=0, highlightthickness=0, bg="black")
canvas.grid()
# create a scrollbar
vsb = Scrollbar(root, orient="vertical", command=canvas.yview)
vsb.grid(row=0, column=1, sticky='ns')
canvas.configure(yscrollcommand=vsb.set)
# Test the ability to scroll
for x in range(30):
Label(canvas, text="test").grid(row=x)
root.mainloop()
Note: I only want to add other widgets, including scrollbar using only grid manager
Things to add
#1 a frame inside a canvas
#2 binding an event (configure) that changes the canvas view thing with scroll
#3 create a window with the given frame
from tkinter import *
root = Tk()
root.geometry("950x600")
# create canvas
canvas = Canvas(root, width=932, height=600, borderwidth=0, highlightthickness=0, bg="black")
vsb = Scrollbar(root, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=vsb.set)
# create a scrollbar
f=Frame(canvas)#1
canvas.grid()
canvas.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))#2
canvas.create_window((0,0),anchor='nw',window=f,width=932)#3
vsb.grid(row=0, column=1, sticky='ns')
# Test the ability to scroll
for x in range(300):
Label(f, text="test").grid(row=x)
root.mainloop()
So I have a starter tab which has a textbox inside. I also want to create a new tab on the click of a button. When I create the new tab it does not show the textbox. I want all the tabs to have the same textbox and the same widgets.
Here is my code so far:
from tkinter import *
from tkinter import ttk
root = Tk()
root.geometry("600x600")
def newTab(*args): # How do I keep the textbox and other widgets in the new tabs
newFrame = Frame(root, width=500, height=500)
newFrame.pack()
tabsArea.add(newFrame, text="Untitled.txt")
button = Button(root, command=newTab).pack()
# Tab Area --- First Tab
tabsArea = ttk.Notebook(root)
tabsArea.pack(pady=15)
# Create Main Frame
frame = Frame(root)
frame.pack(pady=5)
# Add Frame to Tab
tabsArea.add(frame, text="Untitled.txt")
# Textbox
textBox = Text(frame).pack()
root.mainloop()
How do I configure the text box and widgets in the newFrame/new tab?
You need to add a new text widget in each tab. Your code is just creating empty frames. Also, you shouldn't be calling newFrame.pack() since you are adding newFrame to the notebook.
Here is a slimmed down version of your code that shows the basic concept:
from tkinter import *
from tkinter import ttk
root = Tk()
root.geometry("600x600")
def newTab(*args):
newFrame = Frame(root, width=500, height=500)
tabsArea.add(newFrame, text="Untitled.txt")
text = Text(newFrame)
text.pack(fill="both", expand=True)
button = Button(root, text="New Tab", command=newTab)
tabsArea = ttk.Notebook(root)
button.pack(side="top")
tabsArea.pack(pady=15, fill="both", expand=True)
# Add the first tab
newTab()
root.mainloop()
I have the canvas and the scrollbar are on the Tk.
I have a frame on the canvas.
I adding into this frame new frames with the widgets on it and I want to scroll these widgets.
The scrollbar doesn't scroll the widgets at all, and when I add widgets which go below the window than the scrollbar turn into gray and I can't use it at all.
I am new to tkinter and python. I just don't know yet what am I doing. I didn't try to make it with a class(Should I?). I tried to use the ttk, and looked around sites for a non class answers but none of them worked.
from tkinter import *
from tkinter.ttk import *
actor_number=0
global tk
def new_actor_button_command():
global menu_frame
global actor_number
global canvas
new_actor_frame=Frame(menu_frame,width=500,height=200)
new_actor_frame.grid(row=1+actor_number,column=0,pady=20)
actor_name_label=Label(new_actor_frame,text="Actor Name")
new_actor_frame.place(relx=0.0, rely=0.0, anchor=CENTER)
delete_actor_button=Button(new_actor_frame,text="Delete
Actor",command=delete_actor_button_command)
new_actor_frame.grid(row=1+actor_number,column=1)
actor_name_label.grid(row=2+actor_number,column=1)
delete_actor_button.grid(row=2+actor_number,column=2)
actor_number+=1
canvas.update_idletasks()
scrollbar.config(command=canvas.yview)
canvas.configure(scrollregion=canvas.bbox("all"))
def make_new_actor():
global canvas
global menu_frame
new_actor_button=Button(menu_frame,text="Add New
Actor",command=new_actor_button_command)
new_actor_button.grid(row=0,column=0)
def new_command():
global actor_number
actor_number=0
make_new_actor()
tk=Tk()
tk.geometry("1200x800")
menubar=Menu(tk)
filemenu=Menu(menubar,tearoff=0)
filemenu.config(font=("Verdana",16))
filemenu.add_command(label="New",font=("Verdana",16),command=new_command)
menubar.add_cascade(label="File", menu=filemenu)
global scrollbar
canvas=Canvas(tk,width=1000,height=1000)
scrollbar=Scrollbar(tk,orient="vertical",command = canvas.yview)
menu_frame=Frame(canvas,width=1000,height=1000)
canvas.create_window(0,0,window=menu_frame)
canvas.configure(yscrollcommand=scrollbar.set)
canvas.configure(scrollregion=canvas.bbox("all"))
canvas.place(relx=0.0, rely=0.0)
menu_frame.pack(side=LEFT,expand=True)
scrollbar.pack(side=RIGHT,fill=Y)
tk.config(menu=menubar)
tk.mainloop()
It should scroll the vidgets inside"menu_frame".
Scrolling Canvas is not easy.
It scroll items (if you add enough items in menu_frame) but it may need other changes in new_actor_frame
from tkinter import *
from tkinter.ttk import *
def new_actor_button_command():
new_actor_frame = Frame(menu_frame, width=500, height=200)
new_actor_frame.grid(row=actor_number, column=0)
actor_name_label = Label(new_actor_frame, text="Actor Name")
actor_name_label.grid(row=0, column=1)
delete_actor_button=Button(new_actor_frame,text="Delete Actor")#, command=delete_actor_button_command)
delete_actor_button.grid(row=0, column=2)
def new_command():
global actor_number
actor_number += 1
new_actor_button = Button(menu_frame, text="Add New Actor", command=new_actor_button_command)
new_actor_button.grid(row=actor_number, column=0)
def update_canvas(event=None):
canvas.configure(scrollregion=canvas.bbox("all"))
actor_number=0
tk = Tk()
tk.geometry("1200x800")
menubar = Menu(tk)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="New", command=new_command)
menubar.add_cascade(label="File", menu=filemenu)
tk.config(menu=menubar)
canvas = Canvas(tk, background='white')#, width=1000, height=1000)
canvas.pack(side='left', fill='both', expand=True)
scrollbar = Scrollbar(tk, orient="vertical", command=canvas.yview)
scrollbar.pack(side='right', fill='y')
menu_frame = Frame(canvas)
canvas.create_window(0, 0, window=menu_frame, anchor='nw')
canvas.configure(yscrollcommand=scrollbar.set)
canvas.bind('<Configure>', update_canvas) # update when change size
tk.mainloop()