Tkinter Scrollbar Does not work for objects inside canvas - python

I've made a canvas with two scrollbar and two buttons. But the scrollbar doesn't interact with the buttons inside the canvas.
What I want to make, is whenever I scrolls (for example, scroll down), all buttons in the canvas moves to the opposite direction (in this case, move up), but currently they won't move at all.
ws = Tk()
ws.title('PythonGuides')
frame = Frame(
ws,
width=500,
height=400
)
frame.pack(expand=True, fill=BOTH)
canvas = Canvas(
frame,
bg='#4A7A8C',
width=500,
height=400,
scrollregion=(0, 0, 700, 700)
)
vertibar = Scrollbar(
frame,
orient=VERTICAL
)
vertibar.pack(side=RIGHT, fill=Y)
vertibar.config(command=canvas.yview)
horibar = Scrollbar(
frame,
orient=HORIZONTAL
)
horibar.pack(side=BOTTOM, fill=X)
horibar.config(command=canvas.xview)
canvas.config(width=500, height=400)
canvas.config(
xscrollcommand=horibar.set,
yscrollcommand=vertibar.set
)
example=tkinter.Button(canvas, text="1")
example.grid(row=3, column=5)
example2 = tkinter.Button(canvas, text="2")
example2.grid(row=6, column=7)
canvas.pack(expand=True, side=LEFT, fill=BOTH)
ws.mainloop()

You cannot scroll items of canvas if they are put into the canvas using .grid()/.pack()/.place().
Use .create_window() instead:
...
example = tkinter.Button(canvas, text="1")
canvas.create_window(10, 10, window=example, anchor="nw")
example2 = tkinter.Button(canvas, text="2")
canvas.create_window(50, 50, window=example2, anchor="nw")
...

Related

Tkinter Scroll through a canvas of frames

I'm trying to add a scroll bar to a canvas filled with multiple MsgFrame classes. MsgFrame inherits from the tk.Frame class. I've tried multiple youtube videos and articles but none have worked.
root = tk.Tk()
root.geometry('500x500')
scrollBar= Scrollbar(root)
scrollBar.pack(side=RIGHT, fill='y')
canvas = Canvas(root, yscrollcommand=scrollBar.set)
frames = []
for row, msg in enumerate(MESSAGES):
frame = MsgFrame(msg, canvas, row*3+1)
frames.append(frame)
for frame in frames:
frame.pack(side=TOP, anchor=NW, padx=5, pady=5)
canvas.pack(side=LEFT, fill=BOTH)
scrollBar.config(command=canvas.yview)
root.mainloop()

Python tkinker resitze Canvas

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

scrollbar in Top level canvas

scrollbar in Top level window created for a canvas is not working and how do I get region of canvas. where canvas size varies with number of buttons in it
I have created frame in tk(root) and one widget in a frame creates Top level window , which has multiple Buttons in a Frame.Number of Button varies with list. That Frame(which has buttons in it) exists in a canvas. My problem is that after putting scroll widget canvas do not moves
from tkinter import *
root = Tk()
root.geometry("500x200")
my_app= Frame(root)
my_app.pack()
my_window = Toplevel(my_app, bg='brown')
my_window.geometry("500x200+300+500")
top_window = Frame(my_window, bd=2, relief=SUNKEN)
top_window.grid_columnconfigure(0, weight=1)
yscrollbar = Scrollbar(top_window)
yscrollbar.grid(row=0, column=1, sticky=N+S)
canvas = Canvas(top_window, bd=0, yscrollcommand=yscrollbar.set)
canvas.config(scrollregion=(0, 0, 500, 1000))
canvas.grid(row=0, column=0, sticky=N+S+E+W)
yscrollbar.config( command = canvas.yview)
top_window.pack()
my_f = Frame(canvas)
def ins_ind(m):
print(m)
results =
["one","two","three","four","five","six","seven","eight","nine","ten"]
ins_list=[]
for ind, result in enumerate(results):
ins=str(result)
ins_list.append(ind)
ins_list[ind] = Button(my_f, text = ins, font='Times 12 bold',
bg='sandy brown',anchor=E, fg="black", command = lambda m=ins:
ins_ind(m) )
ins_list[ind].pack()
my_f.pack()
root.mainloop()
Scroll bar do no moves
For the buttons to move when you scroll the canvas you must put the buttons on the canvas.
Your code puts the buttons on the frame my_f. To put the buttons on the canvas you should use: canvas.create_window(x, y, window=button).

How to add two widgets in a tk.Frame located inside a tk.Canvas?

I'm trying to do a scrollable application with two buttons. Pressing one of those buttons should be put a new button in the Frame, and scroll the widgets inside the frame.
My question is how to put the two buttons in the frame?
when I try to put in the same Frame only I can see one button and only a small part of the other.
How to solve this?
from tkinter import * # from x import * is bad practice
global y
y=0
def _configure_interior(event):
print("hola")
size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
canvas.config(scrollregion="0 0 %s %s" % size)
def newbutton():
buttons=Button(interior, text="Button ")
buttons.pack()
#b2.place(y=50)
root =Tk()
#configuring the Scrollbars
vscrollbar = Scrollbar(root, orient=VERTICAL)
vscrollbar.pack(fill=Y, side=RIGHT)
hscrollbar = Scrollbar(root, orient=HORIZONTAL)
hscrollbar.pack(fill=X, side=BOTTOM)
#setting canvas with scrollbar
canvas = Canvas(root,height=500, width=500, bg="blue",
yscrollcommand=vscrollbar.set,xscrollcommand=hscrollbar.set)
canvas.propagate(0)
vscrollbar.config(command=canvas.yview)
hscrollbar.config(command=canvas.xview)
canvas.pack()
#making a interior scrolleable frame
interior = Frame(canvas,bg='black',height=600,width=600)
interior.pack(side="top", fill="both", expand=True)
#adding some widgets to the Frame
b=Button(interior, text="Button 2",command=newbutton)
b.pack()
b2=Button(interior, text="Button 2",command=newbutton)
b2.pack()
b2.place(x=50,y=50)
interior_id = canvas.create_window(30,30, window=interior,
anchor=NW)
interior.bind('<Configure>', _configure_interior)
root.mainloop()
You have also used pack() to place the interior frame on the canvas, which does not work. I've commentet that line out in the code below. Also I've commented out the b2.place() as you should not use more tham one geometry manager in a frame.
#making a interior scrolleable frame
interior = Frame(canvas,bg='black',height=600,width=600)
#interior.pack(side="top", fill="both", expand=True)
interior_id = canvas.create_window(30,30, window=interior,
anchor=NW)
#adding some widgets to the Frame
b=Button(interior, text="Button 2",command=newbutton)
b.pack()
b2=Button(interior, text="Button 2",command=newbutton)
b2.pack()
#b2.place(x=50,y=50)
The new buttons are now packed into interior.

Tkinter: Placing the Labels one after another in Canvas relatively.

I would like to arrange the Labels in the canvas one after another. But placement is not coming out as desired.
Below is the function that inserts the labels in the canvas. But the ones in the for loop overlaps. Reason - some labels are larger in size than the other. Hence, I assume that largest size be 80 and do the placements respectively. I would like to change this type of approach. Rather I want the labels to be placed relatively one after the other.
def calculate(*args):
try:
ttk.Label(canvas, text="Result:").place(x=20, y=20)
ttk.Label(canvas, text="Topic:").place(x=20, y=80)
ttk.Label(canvas, textvariable=topic).place(x=200, y=80)
ttk.Label(canvas, text="Environment:").place(x=20, y=120)
ttk.Label(canvas, textvariable=environment).place(x=200, y=120)
ttk.Label(canvas, text="Event Results:").place(x=20, y=160)
inputValue=TextArea.get("1.0","end-1c")
len_max=0
result={}
for s in inputValue.splitlines():
data = MainInstance.searchWithPayload(s)
result[s]=data
if len(s+data) > len_max:
len_max = len(s+data)
i = 190
for key in result.keys():
print(key)
print(result[key])
ttk.Label(canvas, text=key+"\n\n"+result[key], wraplength=800).place(x=20,y = i)
i = i + 80
except ValueError:
pass
Below is the code that integrates the canvas widget. And the calculate button calls the calculate function.
ttk.Button(page2, text="Exit",command=page1.quit).grid(column=2, row=8)
ttk.Button(page2, text="Calculate", command=calculate).grid(column=3, row=8)
canvas = Canvas(root, width=900, height=universal_height)
canvas.grid(column=1, row=0)
root.mainloop()
Actually, there are two parts of the question:
How can I relatively place the label to stop the overlapping?
I tried adding the scroll to the canvas. But the application does not respond and does not pop up.
Code for adding the scrollbar:
canvas=Canvas(root,bg='#FFFFFF',width=300,height=300,scrollregion=
(0,0,500,500))
hbar=Scrollbar(root,orient=HORIZONTAL)
hbar.pack(side=BOTTOM,fill=X)
hbar.config(command=canvas.xview)
vbar=Scrollbar(root,orient=VERTICAL)
vbar.pack(side=RIGHT,fill=Y)
vbar.config(command=canvas.yview)
canvas.config(width=300,height=300)
canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
canvas.pack(side=LEFT,expand=True,fill=BOTH)
This is the output that I am getting, wherein the first two labels are getting overlapped.
If you want to scroll the widgets that you put inside the canvas, you need to use canvas.create_window(x, y, window=label) instead of label.place(...).
I suggest you to create a frame, grid all you labels inside it so that you won't have overlapping issues and put the frame inside the canvas using create_window to be able to scroll it:
import tkinter as tk
from tkinter import ttk
def on_resize(event):
"""Resize canvas scrollregion when the canvas is resized."""
canvas.configure(scrollregion=canvas.bbox('all'))
root = tk.Tk()
root.geometry('100x100')
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
canvas = tk.Canvas(root)
frame = ttk.Frame(canvas)
# create and grid the labels
for i in range(3):
for j in range(3):
ttk.Label(frame, text="Label %i-%i" % (i, j)).grid(row=i, column=j, padx=10, pady=10)
# put the frame in the canvas
canvas.create_window(0, 0, anchor='nw', window=frame)
# add the scrollbars
vbar = ttk.Scrollbar(root, orient='vertical', command=canvas.yview)
hbar = ttk.Scrollbar(root, orient='horizontal', command=canvas.xview)
canvas.configure(xscrollcommand=hbar.set,
yscrollcommand=vbar.set,
scrollregion=canvas.bbox('all'))
canvas.grid(row=0, column=0, sticky='eswn')
vbar.grid(row=0, column=1, sticky='ns')
hbar.grid(row=1, column=0, sticky='ew')
canvas.bind('<Configure>', on_resize)
root.mainloop()

Categories