So I want to have a vertical and horizontal scroll bar on the window that automatically updates for the size of the canvas. I got it partly there, and right now the code creates extra scroll bars for each update and the horizontal scroll bar doesn't span the length of the whole canvas. Here is a sample I created to illustrate this:
import tkinter
from tkinter import ttk
root = tkinter.Tk()
root.state("zoomed")
bigframe = tkinter.Frame(root)
bigframe.pack(fill="both", expand=1)
canvas = tkinter.Canvas(bigframe)
canvas.pack(side="left", fill="both", expand=1)
scrollbarv = ttk.Scrollbar(bigframe, orient="vertical", command=canvas.yview)
scrollbarh = ttk.Scrollbar(bigframe, orient="horizontal", command=canvas.xview)
scrollbarv.pack(side="right", fill="y")
scrollbarh.pack(side="bottom", fill="x")
canvas.configure(yscrollcommand=scrollbarv.set, xscrollcommand=scrollbarh.set)
canvas.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
mainframe = tkinter.Frame(canvas)
canvas.create_window((0, 0), window=mainframe, anchor="nw")
i = 1
text = "Hello World! "
def click():
global i
global text
for t in range(10):
i += 1
text += "Hello World! "
tkinter.Label(mainframe, text=text).pack()
scrollbar = ttk.Scrollbar(bigframe, orient="vertical", command=canvas.yview)
scrollbar.pack(side="right", fill="y")
button = tkinter.Button(mainframe, text="Click me!", command=click)
button.pack()
root.mainloop()
This is what happens when I click the button 4 times:
I believe the horizontal scrollbar being small is due to me saying canvas.pack(side="left", fill="both", expand=1), but if I say side="top then the vertical scroll bars don't span the height of the canvas.
Is there some specific piece of code that is causing the multiple scrollbars issue or the horizontal bar issue? And if so, how should I fix it?
You have to destroy the old scrollbar before you add a new one. Just add scrollbar.destroy() to your click function, like I did below:
def click():
global i
global text
for t in range(10):
i += 1
text += "Hello World! "
tkinter.Label(mainframe, text=text).pack()
scrollbar = ttk.Scrollbar(bigframe, orient="vertical", command=canvas.yview)
scrollbar.destroy()
scrollbar.pack(side="right", fill="y")
I made the following changes to your code. At first it doesn't work, however if I resize the window it works perfectly.
import tkinter
from tkinter import ttk
root = tkinter.Tk()
root.state("zoomed")
bigframe = tkinter.Frame(root)
bigframe.pack(fill="both", expand=1)
canvas = tkinter.Canvas(bigframe)
canvas.pack(side="left", fill="both", expand=1)
scrollbarv = ttk.Scrollbar(bigframe, orient="vertical",
command=canvas.yview)
scrollbarh = ttk.Scrollbar(root, orient="horizontal",
command=canvas.xview)
scrollbarv.pack(side="right", fill="y")
scrollbarh.pack(side="bottom", fill="x")
canvas.configure(yscrollcommand=scrollbarv.set,
xscrollcommand=scrollbarh.set)
canvas.bind("<Configure>", lambda e:
canvas.configure(scrollregion=canvas.bbox("all")))
mainframe = tkinter.Frame(canvas)
canvas.create_window((0, 0), window=mainframe, anchor="nw")
i = 1
text = "Hello World! "
def updateScrollRegion():
canvas.update_idletasks()
canvas.config(scrollregion=mainframe.bbox())
def click():
global i, scrollbarv, text
for t in range(10):
i += 1
text += "Hello World! "
tkinter.Label(mainframe, text=text).pack()
button = tkinter.Button(mainframe, text="Click me!", command=click)
button.pack()
root.mainloop()
Related
I use scrollbar widget and I want to change the shape of it.
Here's my questions below.
Can I use the image on the scroll bar?
How can I modify the color and shape with the options like relief, background, highlightbackground, highlightcolor or highlightthickness? I already tried but not a thing has changed.
from tkinter import *
root = Tk()
root.geometry("640x480")
frame = Frame(root)
frame.pack()
scrollbar = Scrollbar(frame, relief=RAISED, width=20, bd=5, activebackground="yellow", elementborderwidth=10, troughcolor="yellow", highlightbackground="red")
scrollbar.pack(side="right", fill="y")
listbox = Listbox(frame, selectmode="extended", height=10, bg="green", fg="white", yscrollcommand=scrollbar.set)
for i in range(1, 32):
listbox.insert(END, str(i) + "day")
listbox.pack()
scrollbar.config(command = listbox.yview) # scrollbar와 listbox를 mapping 해줌
root.mainloop()
I have an Python3 Tkinter Programm. I have 3 Frames in the Main Window and in one Frame an canvas with scroll Option - now i want resitze the Canvas Area .
Now if i resize it moves the Scroll Bar for Y out the Window and the scrollbar for x works also not as expected (get bigger but slide area don't change)
How i Mange it to resize an Canvas in an grid Layout - The Window must be the same size , the Scrollbas must be updatet and the Canvas Plane must be bigger.
an excerpt from my code:
import tkinter as tk
def menu_build():
caninfo[0] += 10
cangui.configure(width = caninfo[0])
#cangui.configure(scrollregion=cangui.bbox("all"))
def gui():
master = tk.Tk()
master.title( "Easy Switch" )
master.geometry("480x320")
frametop = tk.Frame(master, bg="blue", bd=2)
frametop.grid(column=0,row=0)
frameex = tk.Frame(master, bg="yellow", bd=2)
frameex.grid(column=1,row=1)
framegui = tk.Frame(master, bg="red", bd=2)
framegui.grid(column=0, columnspan=2, row=1)
menu = tk.Menu(master)
master.config(menu=menu)
filemenu = tk.Menu(menu)
menu.add_cascade(label="Config", menu=filemenu)
filemenu.add_command(label="Resize",command=menu_build)
global cangui
cangui = tk.Canvas(framegui, width=385, height=250)
#caninfo = [385,250]
cangui.grid(row=1, column=2)
scroll_x = tk.Scrollbar(framegui, orient="horizontal", command=cangui.xview)
scroll_x.grid(row=2, column=2, sticky="ew")
scroll_y = tk.Scrollbar(framegui, orient="vertical", command=cangui.yview)
scroll_y.grid(row=1, column=3, sticky="ns")
cangui.configure(yscrollcommand=scroll_y.set,xscrollcommand=scroll_x.set)
cangui.configure(scrollregion=cangui.bbox("all"))
cwcb = tk.Checkbutton(framegui, text="ccw").grid(row=2,column=0)
cangui.create_arc(90,90,110,110,style=tk.PIESLICE,width=4,start=0,extent=300)
master.mainloop()
global caninfo
caninfo = [385,250]
if __name__ == "__main__":
gui()
no need to resize the canvas Area
wrote an extra funktion
win = [int(cangui.cget("width")),int(cangui.cget("height"))]
draw_xy = cangui.bbox("all")
swin = (min(0,draw_xy[0]),min(0,draw_xy[1]),max(draw_xy[2],win[0]),max(draw_xy[3],win[1]))
cangui.configure(scrollregion=swin)
reason: canvas.bbox("all") gives only the positon from most upper/left grafic and i want 0/0
I am trying to make a gui that has two separate text outputs with horizontal and vertical scollbars for each text box that are fixed to the right and bottom edges of each respective text windows. I am struggling with how to do this with the tkinter grid and any help would be appreciated.
import tkinter as tk
class WeatherGUI(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
# Horizontal (x) Scroll bar
self.xscrollbar = tk.Scrollbar(self, orient="horizontal")
self.xscrollbar.grid(column=5, row=10, sticky="we")
# Vertical (y) Scroll Bar
self.yscrollbar = tk.Scrollbar(self)
self.yscrollbar.grid(column=5, row=10, sticky='ns')
self.xscrollbar2 = tk.Scrollbar(self, orient="horizontal")
self.xscrollbar2.grid(column=9, row=10, sticky="we")
# Vertical (y) Scroll Bar
self.yscrollbar2 = tk.Scrollbar(self)
self.yscrollbar2.grid(column=9, row=10, sticky='ns')
self.NSW_actual_text = tk.Text(self, width=50, wrap = "none", xscrollcommand=self.xscrollbar.set, yscrollcommand=self.yscrollbar.set,)
self.NSW_actual_text.grid(column=0, columnspan=4, row= 8,padx=(20, 10))
self.NSW_forecast_text = tk.Text(self, width=50, wrap = "none", xscrollcommand=self.xscrollbar.set, yscrollcommand=self.yscrollbar.set)
self.NSW_forecast_text.grid(column=8, columnspan=4, row= 8,padx=(20, 10))
self.xscrollbar.config(command=self.NSW_actual_text.xview)
self.yscrollbar.config(command=self.NSW_actual_text.yview)
self.xscrollbar2.config(command=self.NSW_forecast_text.xview)
self.yscrollbar2.config(command=self.NSW_forecast_text.yview)
self.btn1 = tk.Button(self, text="Generate NWS Actual", command=self.GenerateNWSActual)
self.btn1.grid(column=1, row=0)
self.btn2 = tk.Button(self, text="Generate NWS Forecast", command=self.GenerateNWSForecast)
self.btn2.grid(column=10, row=0)
def GenerateNWSActual(self):
self.NSW_actual_text.insert('1.0', "This is where actual weather would go")
def GenerateNWSForecast(self):
self.NSW_forecast_text.insert('1.0', "this is where forecast weather would go")
app = WeatherGUI()
app.mainloop()
The following example allows you to attach two functional scrollbars (x, y) to a Text widget
from tkinter import *
# Create Window
root = Tk()
# Create ScrollBars
xScrollbar = Scrollbar(root, orient=HORIZONTAL)
yScrollbar = Scrollbar(root, orient=VERTICAL)
# Create Text Widget with scroll commands
TextWidget = Text(root, xscrollcommand=xScrollbar, yscrollcommand=yScrollbar)
# Package Componets
xScrollbar.pack(side=BOTTOM, fill=X)
yScrollbar.pack(side=RIGHT, fill=Y)
TextWidget.pack(fill=BOTH, expand=20)
# Assign Scrollbars with TextWidget
xScollbar.config(command=TextWidget.xview)
yScollbar.config(command=TextWidget.yview)
You can use this examble for both of your TextWidgets in your weather application.
Consider the following example:
from tkinter import *
startingWin = Tk()
canvas = Canvas(startingWin, height=600)
canvas.grid(row=0, column=0,sticky="nsew")
canvasFrame = Frame(canvas)
canvas.create_window(0, 0, window=canvasFrame, anchor='nw')
for i in range(70):
element = Button(canvasFrame, text='Button %s ' % i)
element.grid(row=i, column=0)
yscrollbar = Scrollbar(startingWin, orient=VERTICAL)
yscrollbar.config(command=canvas.yview)
canvas.config(yscrollcommand=yscrollbar.set)
yscrollbar.grid(row=0, column=1, sticky="ns")
canvas.yview_moveto(0.5)
canvasFrame.bind("<Configure>", lambda event: canvas.configure(scrollregion=canvas.bbox("all")))
startingWin.mainloop()
Expected output: Scrollbar in the middle.
However, I get the Scrollbar always on the top, regardless of the value I give to yview_moveto() like the following:
How can I fix this?
You shouldn't call canvas.yview_moveto(0.5) until after the scrollregion has been defined.
I am currently programming something for my Computing coursework and I am trying to incorporate scroll bars into it, at the moment I cannot find any website which really explains why after moving the frame of the window, the scroll bar stops working (becomes grayed out) and after moving the canvas of the window, the canvas becomes really small (not the size I want it to be anyway). Here's some example code:
import Tkinter as tk
from Tkinter import *
master.geometry("800x600+300+150")
class Example(tk.Frame):
def main(self):
self.canvas = tk.Canvas(master, borderwidth=0, background="#ffffff")
self.frame = tk.Frame(self.canvas, background="#ffffff")
self.vsb = tk.Scrollbar(self.canvas, orient="vertical", command=self.canvas.yview)
self.hsb = tk.Scrollbar(self.canvas, orient="horizontal", command=self.canvas.xview)
self.canvas.configure(yscrollcommand=self.vsb.set)
self.canvas.configure(xscrollcommand=self.hsb.set)
self.vsb.pack(side="right", fill="y")
self.hsb.pack(side="bottom", fill="x")
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas.create_window((4,4), window=self.frame, anchor="nw",
tags="self.frame")
self.frame.bind("<Configure>", self.OnFrameConfigure)
self.populate()
def populate(self):
vars1 = StringVar()
vars1.set("junk")
for i in range(100):
tk.Entry(self.frame, text=vars1).grid(row=1*i, column=1)
def OnFrameConfigure(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
dave3 = Example()
dave3.main()
button = Button(master, text="Hi").place(x=0, y=0)
mainloop()
if I try to move the frame or canvas things happen that I don't want to, I just literally want the entire frame to move down so that the button does not overlap the canvas Entries and for the scroll bar to still work. If anyone can give a solution to this I would be extremely grateful, cheers.
P.s thanks to Bryan Oakley for getting me this far with his example code.
OK never mind I just figured it out, what I needed to do was create another frame and put the previous frame inside that one. After this I just configured that frame to the size I needed it to be. For any other newbies here's the code:
import Tkinter as tk
from Tkinter import *
master = Tk()
master.geometry("800x600+300+150")
class Example(tk.Frame):
def main(self):
self.framee = tk.Frame(master,background="red")
self.canvas = tk.Canvas(self.framee, borderwidth=0, background="#ffffff")
self.frame = tk.Frame(self.canvas, background="#ffffff")
self.vsb = tk.Scrollbar(self.canvas, orient="vertical", command=self.canvas.yview)
self.hsb = tk.Scrollbar(self.canvas, orient="horizontal", command=self.canvas.xview)
self.canvas.configure(yscrollcommand=self.vsb.set)
self.canvas.configure(xscrollcommand=self.hsb.set)
self.vsb.pack(side="right", fill="y")
self.hsb.pack(side="bottom", fill="x")
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas.create_window((4,4), window=self.frame, anchor="nw",
tags="self.frame")
self.frame.bind("<Configure>", self.OnFrameConfigure)
self.framee.place(x=0, y=50, width=500, height=500)
self.populate()
def populate(self):
vars1 = StringVar()
vars1.set("junk")
for i in range(100):
tk.Entry(self.frame, text=vars1).grid(row=1*i, column=1)
def OnFrameConfigure(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
dave3 = Example()
dave3.main()
button = Button(master, text="Hi").place(x=0, y=0)
mainloop()