I tried to scroll a column of images in a canvas with code bellow, when I run the code, the scrollbar shows up but has nothing to scroll. and images are in the main directory.
CODE(python 3):
import tkinter as tk
root = tk.Tk()
root.configure(bg='#1d1d1d')
root.geometry('100x200')
f = tk.PhotoImage(file = 'folder.png')
d = tk.PhotoImage(file = 'database.png')
can = tk.Canvas(root , bg = 'red' )
scroll = tk.Scrollbar(root , command=can.yview)
for i in range(20):
tk.Label(can , image = f , anchor = 'w').pack( side = 'top')
for i in range(10):
tk.Label(can , image = d , anchor = 'w').pack( side = 'top')
can.pack( side = 'left')
scroll.pack(side = 'right' , fill = 'y')
can.config(yscrollcommand=scroll.set)
can.configure(scrollregion=can.bbox("all"))
root.mainloop()
Does anyone know where the problem is?
The canvas cannot scroll items added with pack, place, or grid. To add something to the canvas that can be scrolled you must use one of the create_* methods (create_window, create_image, etc).
Related
probalby those are two separate issues, but i can not find help for any of them
I am doing an basic interface with TKINTER that work both on PC and raspberry with LCD screen, plenty of lines to raise this. Interface is basic, just a image with some bottons on top, buttons are made with shapes (i.e. create rectangle)
issue come first that background image is only displayed briefly and the disapear, but not on debuggin mode (Visual Studio code and F5 step by step), and second, buttons do not capture click of mouse if I do not add button backgroud, if added border (as bellow example), only get hitted on the border.
codesnipet:
import tkinter as tk
...
self.canvas = tk.Canvas(self, bg=self.backgroundColor, bd=0, highlightthickness=0, relief='ridge')
self.canvas.config(cursor="circle")
self.canvas.pack(fill=tk.BOTH, expand=1)
self.canvas.bind("<Key>", event_keypress)
for i_v in range(2):
for i_h in range (5):
tagName = "pad_button_" + str(i_v * 5 + i_h)
self.canvas.tag_bind(tagName,"<Button-1>", lambda event, arg=tagName: event_callback(event, arg) )
self.canvas.create_image(10,10, image = myImg, anchor = "nw")
sleep(1)
keysize = 10
buttonsWidth = 2
colorOutline = 'red'
color = '' # <-
for i_v in range (0,2):
for i_h in range (0,5):
v_position = i_v * (keysize)
h_position = i_h * (keysize)
tagName = "pad_button_" + str(i_v * 5 + i_h)
self.canvas.create_rectangle( h_position
, v_position
, h_position + keysize
, v_position + keysize
, width=buttonsWidth
, fill=color
, outline=colorOutline
, tags=["pad_button",tagName] )
self.canvas.update()
I know I am not very good, I am learning, and I got stuck with that for several days, looking help haven't been able to come forward
I tested the "in_function_scope", does not seem to be the thing as it disvanice also in:
myImg = ...
img1=tk_canvas.create_image(4,4, image = myImg, anchor = "nw")
tk_canvas.pack()
tk_canvas.update()
time.sleep(0.3)
myImg = ...
img2=tk_canvas.create_image(40,40, image = myImg, anchor = "nw")
tk_canvas.pack()
tk_canvas.update()
(not sure what I am doing with the pack as it does not have any effect)
I am using Tk GUI and I want my window to be split into 2 frames, something like that:
import tkinter as tk
root = tk.Tk()
root.geometry('1000x800')
df_frame = tk.LabelFrame(root)
df_frame.place(relwidth = 1, height = 720)
open_file_frame = tk.LabelFrame(root)
open_file_frame.place(x = 0, y = 720, relwidth = 1, height = 80)
root.mainloop()
My problem is that I don't know how to make it adaptable to the size of the window. If the user enlarges the size of the window, I want the second frame to stay at the bottom, and the first frame to enlarge accordingly.
Thanks in advance for your help.
You can combine relheight and height options to control the height of the top frame.
And combine rely and y options to put the bottom frame at the bottom of the window:
import tkinter as tk
root = tk.Tk()
root.geometry('1000x800')
df_frame = tk.LabelFrame(root)
# frame_height = window_height - 80
df_frame.place(relwidth=1, relheight=1, height=-80)
open_file_frame = tk.LabelFrame(root)
# frame y position = 80 pixel from the bottom
open_file_frame.place(rely=1, y=-80, relwidth=1, height=80)
root.mainloop()
I have made most of this window already, and would prefer to not have to restart because of a hitch with a scrollbar not resizing properly. Problem being that the scrollbars appear way too small for the listboxes and I want them to span the whole height of each box respecitvely, but as of now they can only function if you spam the arrows as the actual scrolling bit can't move for lack of space. Any help would be appreciated, stuck on this for a while now. (Using python 3.8).
import tkinter as tk
from tkinter import *
setup = tk.Tk()
setup.title("Set Up Game")
setup.geometry("450x650")
setup.resizable(width=False, height=False)
select_Box = tk.Canvas(setup, width=450, height=496, bg="#cd3636")
select_Box.pack(padx=10)
listbox1 = Listbox(setup, width=33, height=30)
listbox1_win = select_Box.create_window(110,250, window=listbox1)
listbox2 = Listbox(setup, width=33, height=30)
listbox2_win = select_Box.create_window(320,250, window=listbox2)
scroll1 = Scrollbar(setup)
scroll1_win = select_Box.create_window(200,250, window=scroll1)
scroll2 = Scrollbar(setup)
scroll2_win = select_Box.create_window(410,250, window=scroll2)
listbox1.config(yscrollcommand = scroll1.set, selectmode=SINGLE)
scroll1.config(command = listbox1.yview)
listbox2.config(yscrollcommand = scroll2.set, selectmode=SINGLE)
scroll2.config(command = listbox2.yview)
nameArray = ["Bulbasaur", "Ivysaur", "Venasaur", "Charmander", "Charmelion", "Charazard", "Squirtle", "Wartortle", "Blastoise", "Lucario", "Garchomp", "Gengar", "Snorlax", "Reuniclus", "Joel","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder","placeholder"]
for item in nameArray:
listbox1.insert(END, item)
setup.mainloop()
If you want to use Canvas.create_window to place all of your widgets, all you have to do is define the height of your scrollbar (you may need to play around with the numbers a little to get it to the right size).
So the edited snippet from your code will be:
scroll1 = Scrollbar(setup)
scroll1_win = select_Box.create_window(200,
250,
height=480, # this is all you're missing!
window=scroll1)
I have a canvas named self.canvas_input_frame with a canvas within called self.canvas_input_image. self.canvas_input_image is where the image is actually displayed. I have attached a child element vertical and horizontal scrollbars to self.canvas_input_frame. My GUI looks like the image below:
The horizontal scrollbar does not extend from west to east completely. How to fix it? Below is my code:
def open_file_dialog(self):
self.filename = filedialog.askopenfilename(initialdir = "C:/Users/alyss/AppData/Local/Programs/Python/Python36/Damaged Text Document Virtual Restoration", title = "Select A File", filetype = (("png", "*.png"),("jpeg", "*.jpg"), ("pdf", "*.pdf"), ))
#Create Canvas Frame for Input Document
self.canvas_input_frame = tk.Canvas(self.main_canvas, bg = "blue")
self.canvas_input_frame.configure(width=456, height=470)
self.canvas_input_frame.pack(side="left", padx=10,pady = 10)
#Load Input Image
load = Image.open(self.filename)
render = ImageTk.PhotoImage(load)
self.width, self.height = load.size
self.canvas_input_image = tk.Canvas(self.canvas_input_frame,bg = "green") # how to render image in canvas
self.canvas_input_image.configure(width=390, height=470)
self.canvas_input_image.image = render
self.canvas_input_image.create_image(0,0,anchor="nw",image=self.canvas_input_image.image)
self.canvas_input_image.pack(side="left")
self.vsb_canvas_input_frame = tk.Scrollbar( self.canvas_input_frame, orient="vertical", command=self.canvas_input_image.yview)
self.hsb_canvas_input_frame = tk.Scrollbar( self.canvas_input_frame, orient="horizontal", command=self.canvas_input_image.xview)
self.canvas_input_image.config(yscrollcommand=self.vsb_canvas_input_frame.set,xscrollcommand=self.hsb_canvas_input_frame.set)
self.vsb_canvas_input_frame.pack(side = "right", fill = "y")
self.hsb_canvas_input_frame.pack(side = "bottom", fill = "x")
self.canvas_input_image.config(scrollregion = self.canvas_input_image.bbox("all"))
Here the issue is the order of packing widgets. If you change the order of packing the elements like below then it can get you expected view.
self.vsb_canvas_input_frame.pack(side = "right", fill = "y")
self.hsb_canvas_input_frame.pack(side = "bottom", fill = "x")
self.canvas_input_image.pack(side="left")
One way to understand pack method is that if you pack widget1 in 'left' then any other elements can only fit on its opposite side that is 'right'(not left, up or down). Similar logic applies for other sides as well..
I have created a scrollbar in Tkinter and it's working fine, but the size of the Scroll Button is not being scaled correctly (normally it's adjusted to the size of the scrollable area).
I'm placing all my widgets with a .pack(), therefore the .grid sticky configuration is something I would like to avoid.
My question is: Which part of the scrollbar configuration is responsible for scaling the height?
The code example:
master = Tk()
FrameBIG = Frame(master)
Main = Canvas(FrameBIG,height = 1200,width =1500,scrollregion=Main.bbox("all"))
scroll = Scrollbar(FrameBIG ,orient="vertical", command=Main.yview)
scroll.pack(side="right", fill="y")
Main.pack(side = BOTTOM, anchor = NW,fill="x")
FrameBIG.pack(anchor = W, fill = "x")
The code
Main = Canvas(FrameBIG,height=1200,width=1500,scrollregion=Main.bbox("all"))
is wrong because Main does not exists yet. It should be
Main = Canvas(FrameBIG,background="blue", height = 500,width =500)
Main.configure(scrollregion=Main.bbox("all"))
But it is meaningless because Main canvas was created right now and is empty (so the bbox method returns None)
When you created the scrollbar with
scroll = Scrollbar(FrameBIG ,orient="vertical", command=Main.yview)
you forgot to complete the two step contract between scroll and Main, so you have to add the line below (just after the creation of scroll)
Main.configure(yscrollcommand=scroll.set)
Now the code is like this
from tkinter import *
master = Tk()
FrameBIG = Frame(master)
Main = Canvas(FrameBIG,background="blue", height = 500,width =500)
Main.configure(scrollregion=Main.bbox("all"))
scroll = Scrollbar(FrameBIG ,orient="vertical", command=Main.yview)
Main.configure(yscrollcommand=scroll.set)
scroll.pack(side="right", fill="y")
Main.pack(side = BOTTOM, anchor = NW,fill="x")
FrameBIG.pack(anchor = W, fill = "x")
master.mainloop()
Now you can notice that the scroll bar does not have the button. Its because the Main canvas is empty. Let's add something to the Main canvas
FrameBIG.pack(anchor = W, fill = "x")
# creates a diagonal from coordinates (0,0) to (500,1000)
Main.create_line(0, 0, 500, 1000)
master.mainloop()
Now the line is there but the scroll button is not there yet, why?
Because you have to update the scrollregion of the Main canvas.
So let's do it with
FrameBIG.pack(anchor = W, fill = "x")
Main.create_line(0, 0, 500, 1000)
Main.configure(scrollregion=Main.bbox("all"))
master.mainloop()
Now it is working properly.
Here the complete code.
from tkinter import *
master = Tk()
FrameBIG = Frame(master)
Main = Canvas(FrameBIG,background="blue", height = 500,width =500)
Main.configure(scrollregion=Main.bbox("all"))
scroll = Scrollbar(FrameBIG ,orient="vertical", command=Main.yview)
Main.configure(yscrollcommand=scroll.set)
scroll.pack(side="right", fill="y")
Main.pack(side = BOTTOM, anchor = NW,fill="x")
FrameBIG.pack(anchor = W, fill = "x")
Main.create_line(0, 0, 500, 1000)
Main.configure(scrollregion=Main.bbox("all"))
master.mainloop()
In the next question, post a question with a complete working code that shows up you problem. You will get faster and better answers, ok?
Have a nice day.