Hi I can't seem to find the cause of a weird issue I am having in Tkinter\Python
When using the following code to create a scrolling window on a canvas
myFrame = Frame(ob)
ob.create_window((0, 0), window=myFrame, anchor='nw')
scroll = Scrollbar(sub, orient="vertical", command=ob.yview)
ob.configure(yscrollcommand=scroll.set)
scroll.grid(row=0, column=1, sticky=N+S)
# add check boxes for clients to buttons
for row in clients:
v = IntVar()
item = Checkbutton(myFrame, text=row[1], variable=v)
item.va = v
item.grid(sticky='w')
clientlist[str(row[0])] = v
ob.configure(scrollregion=ob.bbox('all'))
It creates the windows inside of the canvas and also creates the items inside of it. It even creates the scrollbar next to the canvas just fine.
The issue is that when I scroll down it allows me to scroll forever. It also scrolls upwards just past the top most item in the canvas window and then disables the scroll function.
Any insight on this as it seems I must not be setting the scroll region correctly is my guess but I am not sure what is wrong with it.
Related
I want to have a horizontal scrollbar for a canvas in tkinter. My canvas has both buttons and lines. When I use canvas inbuilt scrollbar it only scrolls the lines not the buttons. So for the buttons I tried using this function which shifts the position of buttons whenever the scrollbar is moved. But now the problem is that buttons and lines move with a different speed according to the width of the scrollbar. The scrollbar gives relative coordinates for its ends but I need absolute coordinates otherwise it disturbs the dragging feature of the buttons and lines. I have been stuck on this for a week now and can't figure out anything useful. Tried almost everything on stackoverflow.
Toplevel1.hbar = ttk.Scrollbar(panel_2, orient="horizontal")
self.SystemCanvas.configure(scrollregion = (0, 0, 1000, 1000),
xscrollcommand = Toplevel1.hbar.set)
Toplevel1.hbar['command'] = self.SystemCanvas.xview
Toplevel1.hbar.bind('<B1-Motion>', lambda e:hscrollBarMove(e,
Toplevel1.hbar, self.SystemCanvas))
Toplevel1.hbar.pack(side = "bottom", fill = "x")
def hscrollBarMove(event, hbar, systemcanvas):
for instance in systemcanvas.winfo_children():
if isinstance(instance, tk.Button) or isinstance(instance, tk.Menu):
try:
instance.place(relx = - hbar.get()[0])
except:
pass
Buttons and lines come dynamically.
Please someone help me :(
My canvas has both buttons and lines. When I use canvas inbuilt scrollbar it only scrolls the lines not the buttons.
Yes, that is correct. The canvas can only scroll canvas objects -- objects created with the various create_* methods (create_line, create_window, etc). It won't scroll items added to the canvas with place, pack, or grid.
If you want to put buttons on a canvas and have them be scrollable, use create_window to add them to the canvas.
I have a question regarding placed buttons on a frame!
I created a canvas and placed a frame inside this canvas! Inside the canvas I place rectangles and oder stuff, drawn by tkinters canvas.create_rectangle, whereas I place certain widgets like buttons inside the frame. (Result: There are togehter in one window)
window_canvas = Canvas(root, borderwidth=0, background="grey", width = window_canvas_size[0], height = window_canvas_size[1], highlightthickness=0)
window_frame = Frame(window_canvas, background='white', borderwidth=0, width = canvas_size[0], height = canvas_size[1])
Now I made the window_canvas scrollable via:
def OnMousewheelConfigureProcessCanvas(self, event):
window_canvas.yview_scroll(int(-1*(event.delta/120)), "units")
window_canvas.bind("<MouseWheel>", m.OnMousewheelConfigureProcessCanvas)
The buttons are scrollable with the window_canvas, when I place the cursor outside of them, no problem.
However, when I hover with my mouse cursor above a button, the "scrollability" just doesn't work anymore. The window_canvas doesn't react to the mouse wheel this time.
I dont want to create a new window (via canvas.create_window) for every button. I have quite a few of them on screen, so I tried to keep it simple by placing one frame for all inside a canvas!
Looking forward to your solutions!
Thanks!
Im coding my personal text editor. But i have a problem with the 2 widget text and the scrollbar (connect one scrollbar to two text).
What is my idea and logic (at the beginning)?
I want to display 2 text, one for writing text entered by user, and one to display the number of the line. I pack both of them, in the root. Then i create a scrollbar, that will scroll on Y axes the 2 text, so what i want to do (mainly) is to connect 2 widget (text) to one scrollbar.
But it didn't work.
This system absolutely doesn't work, are there any suggest or fix to fix this first idea?
Other ideas that i found.
After the first attempt, i thought that i can pack the 2 texts into 1 container. I tried to create a frame (packed into root) that contains the 2 texts, i did this because i have to connect the scrollbar only to the frame. But it didn't work, moreover it didnt allow me to write the following snippet: command=frame.yview in the scrollbar option, it seems that i cant connect frame to scrollbar.
So:
I will ask u if my reasoning are good, and how to solve. If not what can i do?
Similar question found on Google: (but that i dont undestand)
How to scroll two parallel text widgets with one scrollbar?
Tkinter adding line number to text widget
from tkinter import *
root = Tk()
root.geometry("480x540+100+100")
root.config(cursor='')
line = Text(root, bg="light grey", font="Roman 24", width=4)
line.pack(side=LEFT, fill=BOTH)
text = Text(root, bg="grey", font="Roman 24")
text.pack(side=LEFT, fill=BOTH, expand=True)
scrollbar = Scrollbar(text, orient=VERTICAL, command=(line.yview, text.yview))
text.configure(yscrollcommand=scrollbar.set)
line.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side=RIGHT, fill=Y)
for n in range(50):
line.insert("{}.0".format(n+1), "{}\n".format(n+1))
text.insert("{}.0".format(n+1), "Line no. {}\n".format(n+1))
if __name__ == '__main__':
root.mainloop()
There's nothing special about a scrollbar - it just calls a function when you move it. The API for this function is well defined. While it normally should call the yview (or xview) method of a scrollable window, there's no requirement that it must.
If you want to control two widgets with a single scrollbar, create a function for your scrollbar that scrolls both windows.
def multiple_yview(*args):
line.yview(*args)
text.yview(*args)
scrollbar = Scrollbar(text, orient=VERTICAL, command=multiple_yview)
You will have a similar problem when you scroll the text widget while entering new lines or moving around with cursor keys. You'll need to configure the yscrollcommand attribute of the text widget to call a function so that it both updates the scrollbar and also scrolls the other window (and maybe also add additional line numbers)
I know this isn't the first time a question like this is asked, but even after like 2 hours of browsing the Internet I can't get it to work:
So I'm trying to create a Tkinter-Frame, that contains several Buttons (As Example I took 30). But Because I don't have enough space in my program, I need to add an Scrollbar next to it, so that one can scroll through the Buttons.
The Problems I had where, that the inner "moving part" of the bar was as big as the whole scrollbar and couldn't be moved, which I kinda solved by using scollregion=(0,0,1000,1000), but even then the moving of the bar had no effect on the canvas whatsoever.
Here Is the corresponding code that I extracted out of my program:
import Tkinter as tk
root = tk.Tk()
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=50)
root.columnconfigure(1, weight=1)
root.minsize(300,400)
root.maxsize(300,400)
#Buttons
buttonFrame = tk.Canvas(root, bg='#bbb')
buttonFrame.grid(row=0, column=0, sticky=tk.N+tk.E+tk.S+tk.W)
buttonFrame.columnconfigure(0, weight=1)
scroll = tk.Scrollbar(root, command=buttonFrame.yview)
scroll.grid(row=0, column=1, sticky=tk.N+tk.E+tk.S+tk.W)
buttonFrame.configure(yscrollcommand=scroll.set)
for i in range(30):
tk.Button(buttonFrame, text=str(i+1)).grid(row=i, column=0, sticky=tk.N+tk.E+tk.S+tk.W)
root.mainloop()
As you (hopefully) see, the slider can't even be moved nor does it change anything on the canvas, even if I squeeze a scrollregion=(bla) somewhere in there.
2 Questions:
a.) What do I need to add (or remove), so that I can scroll through the list of Buttons
b.) Does the fix from a. still work when I make the Scrollbar a child of the buttonFrame instead of the root?
To add widgets to a Canvas you have to use the create_window method, not grid(). Then you have to update the canvas before setting the scrollregion.
for i in range(30):
btn = tk.Button(buttonFrame, text=str(i+1))
buttonFrame.create_window((100,i*50), window=btn)
root.update()
buttonFrame.config(scrollregion=buttonFrame.bbox("all"))
If you try that I suspect it's not what you were looking for, since the create_window method requires absolute positioning (you can't use grid or pack). That's why most people put a Frame in the Canvas, and add their widgets to that instead. Many people have abstracted this faux Frame that is actually a Frame in a Canvas in another Frame, including me.
Here is my Tkinter code. I intend to show the both horizontal and vertical scrollbar.
from Tkinter import *
root = Tk()
scrollbar = Scrollbar(root)
scrollbar.pack(side = RIGHT,fill = Y)
scrollbar_x = Scrollbar(root)
scrollbar_x.pack(side = BOTTOM,fill = X)
mylist = Listbox(root,xscrollcommand = scrollbar_x.set,yscrollcommand = scrollbar.set)
"""
To connect a scrollbar to another widget w, set w's xscrollcommand or yscrollcommand to the scrollbar's set() method. The arguments have the same meaning as the values returned by the get() method.
"""
for line in range(100):
mylist.insert(END,("this is line number"+str(line))*100)
mylist.pack(side = LEFT,fill=BOTH)
scrollbar.config(command = mylist.yview)
scrollbar_x.config(command = mylist.xview)
print root.pack_slaves()
mainloop()
And it doesn't match up to my expectation in my computer, which is Mac Sierra.
Furthermore, what's scrollbar.config(command = mylist.yview) means?
config()
More details about this function will be helpful~ thanks
Tkinter program: doesn't show me the bottom scrollbar
I can't duplicate that when I run your code. When I run your code I see a giant scrollbar at the bottom of the screen.
I presume you want the "x" scrollbar to be horizontal rather than vertical. If that is true, you must tell tkinter that by using the orient option:
scrollbar_x = Scrollbar(root, orient="horizontal")
Furthermore, what's scrollbar.config(command = mylist.yview) means?
Scrollbars require two-way communication. The listbox needs to be configured to know which scrollbar to update when it has been scrolled, and the scrollbar needs to be configured such that it knows which widget to modify when it is moved.
When you do scrollbar.config(command=mylist.yview) you are telling the scrollbar to call the function mylist.yview whenever the user tries to adjust the scrollbar. The .yview method is a documented method on the Listbox widget (as well as a few others). If you do not set the command attribute of a scrollbar, interacting with the scrollbar will have no effect.