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!
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 am working on a tkinter project, where I set the background image (not a solid color). I was using .grid() for my widgets, but then I realized I need to display a widget at the very bottom of the tkinter window. To continue using grid for this, I separated my widgets into two frames; 1 frame that contained most of the widgets and one that just contained the widget I want to be displayed at the bottom. Then, I packed my frames, one on the top and the other at the bottom.
However, after I did this, my background image went on top of my existing widgets and blocked them out, so they can't be seen anymore. What can I do to fix this?
Here is the method I used to display the background photo:
from tkinter import *
filename = PhotoImage(file="image.png")
background_label = Label(root, image=filename) # root is the Tk() object
background_label.place(x=0, y=0, relwidth=1, relheight=1)
# Other code here
mainloop()
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.
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.
I have a piece of tkinter code running on python 3.4 that is a large frame placed in a canvas with a vertical scrollbar, however the scrollbar is grayed out and doesn't seem to be linked to the size of the frame. The code I'm using is essentially:
class EntryWindow:
def __init__(self, master):
self.master = master
self.master.minsize(750, 800)
self.master.maxsize(1000, 800)
self.canvas = tk.Canvas(self.master, borderwidth=0, bg='#ffffff')
self.vsb = tk.Scrollbar(self.master)
self.master_frame = tk.Frame(self.canvas)
self.vsb.pack(side="right", fill='y')
self.canvas.pack(side='left', fill='both', expand=True)
self.canvas.create_window((0,0), window=self.master_frame, anchor='nw', tags='self.master_frame')
self.canvas.config(yscrollcommand=self.vsb.set)
self.master_frame.grid()
###build widgets and place into master_frame
...
The master_frame is filled with about 36 widgets placed using the grid geometry manager and reaches a vertical height of about 2000 pixels, but the scrollbar doesn't work.
I saw a post about using ttk scrollbar, but when I imported that I couldn't get it to work. The input statement I used was:
import tkinter as tk
import tkinter.ttk as ttk
and then replaced the line self.vsb = tk.Scrollbar(self.master) with self.vsb = ttk.Scrollbar(self.master) but that didn't fix it either. I also tried removing the min/max sizing on master (those aren't the final values, I've been playing with it).
Is there something I'm doing wrong? I feel like it might be in the line where I set the canvas.config() but I read the documentation and it seems to be right. Tomorrow I plan on trying to load the frame into the canvas after I've built the frame.
But in the meantime, and in case that doesn't work, any help would be great! Thanks!
You must do three things when configuring a scrolling canvas:
have the canvas notify the scrollbar when it scrolls, by configuring the yscrollcommand attribute of the canvas to point to the scrollbar
have the scrollbar control the canvas when it is dragged, by configuring the command attribute of the scrollbar
tell the canvas what part of the virtual canvas should be scrollable by configuring the scrollregion attribute of the canvas
You are neglecting to do #3. After adding the widgets to master_frame you should do this:
self.canvas.configure(scrollregion=self.canvas.bbox("all")
The above will tell the canvas and scrollbar that the area of the canvas that is scrollable is the area that encompasses all of the objects on the canvas.
Finally, you need to remove the following line of code, because you are already adding the frame to the canvas with create_window. Frames added to a canvas with pack, place or grid won't scroll:
# remove this line
self.master_frame.grid()
For a working example of a scrollable frame, see Adding a scrollbar to a group of widgets in Tkinter