Python Forum

Full Version: Problems - buttons w icons not scrolling
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hi, can someone please help me. I am new to Python and I am having problems with scrollbars not scrolling my buttons in window1, only the background numbers-text is scrolling with scrollbars, which I dont need. How can I make my buttons with icons scroll up\down, and sideways with scrollbars in window1?
Regards
Kraco

My code is:

import tkinter as tk # for label frame named in this software tk
from tkinter import ttk # for Canvas scrollbar for buttons with images
from winsound import * # for sound
from tkinter import * # for photo images


# Sound Files
play1 = lambda: PlaySound('c:\images\siren.wav', SND_FILENAME)
play2 = lambda: PlaySound('c:\images\pling.wav', SND_FILENAME)

# Windows definitions
def new_window1(): # Window1 definitions
    # Image files to be uploaded in window1
    photo1 = PhotoImage(file="C:\images\plane.png")
    photo2 = PhotoImage(file="C:\images\car.png")
    photo3 = PhotoImage(file="c:\images\_apple.png")
    " new window"
    try:
        if win1.state() == "normal": win1.focus()
    except NameError as e:
        print(e)
        win1 = tk.Toplevel()
        win1.geometry("400x400+500+200")  # Window1 frame opening size
        win1["bg"] = "green"  # Window1 background colour

        # Canvas scrollbar for buttons with images
        c = Canvas(win1)
        hsb = Scrollbar(win1, orient="h", command=c.xview)
        vsb = Scrollbar(win1, orient="v", command=c.yview)
        c.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)

        c.grid(row=0, column=0, sticky="nsew")
        hsb.grid(row=1, column=0, stick="ew")
        vsb.grid(row=0, column=1, sticky="ns")

        win1.grid_rowconfigure(0, weight=1)
        win1.grid_columnconfigure(0, weight=1)

        c.configure(scrollregion=(0, 0, 5000, 5000))

        for x in range(100, 5000, 100):
            for y in range(100, 5000, 100):
                c.create_text((x, y), anchor=CENTER, text="%d,%d" % (x, y))


# Buttons
        lb = tk.Label(c, text="Window1")  # Create label-frame window1,position for text in label-frame window1
        lb.grid(row=0, column=2) # text location in window1 in framw window1
        Button1 = tk.Button(c, text="plane", command=play1, image=photo1)
        Button1.grid(row=1, column=1)
        Button2 = tk.Button(c, text="car", command=play2, image=photo2)
        Button2.grid(row=2, column=1)
        Button3 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button3.grid(row=3, column=2)
        Button4 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button4.grid(row=4, column=2)
        Button5 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button5.grid(row=5, column=2)
        Button6 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button6.grid(row=6, column=2)

        Button7 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button7.grid(row=7, column=2)
        Button8 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button8.grid(row=8, column=2)
        Button9 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button9.grid(row=9, column=2)
        Button10 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button10.grid(row=10, column=2)
        Button11 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button11.grid(row=11, column=2)
        Button12 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button12.grid(row=12, column=2)
        Button13 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button13.grid(row=13, column=2)
        Button14 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button14.grid(row=14, column=2)
        Button15 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button15.grid(row=15, column=2)
        Button16 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button16.grid(row=16, column=2)


        Button7 = tk.Button(c, text="apple", command=play2, image=photo3)
        Button7.grid(row=1, column=3)
        lb.pack()  # Close window1 frame with buttons

def new_window2():
    # Image files to be uploaded in window1
    photo1 = PhotoImage(file="C:\images\plane.png")
    photo2 = PhotoImage(file="C:\images\car.png")
    photo3 = PhotoImage(file="c:\images\_apple.png")
    " new window"
    try:
        if win2.state() == "normal": win2.focus()
    except NameError as e:
        print(e)
        win2 = tk.Toplevel()
        win2.geometry("300x300+500+200") # Window2 frame opening size
        win2["bg"] = "navy" # Window2 background colour
        lb2 = tk.Label(win2, text="Window2") # Create label-frame window2,position for text in label-frame window2
        lb2.grid(row=0, column=1)  # Position for text in label-frame window2
        Button1 = tk.Button(win2, text="plane", command=play1, image=photo1)
        Button1.grid(row=1, column=1)
        Button2 = tk.Button(win2, text="car", command=play2, image=photo2)
        Button2.grid(row=2, column=1)
        Button2 = tk.Button(win2, text="apple", command=play2, image=photo3)
        Button2.grid(row=1, column=2)
        lb2.pack()  # Close window2 frame with buttons

def new_window3():
    " new window"
    try:
        if win2.state() == "normal": win3.focus()
    except NameError as e:
        print(e)
        win1 = tk.Toplevel()
        win1.geometry("300x300+500+200")
        win1["bg"] = "yellow"
        lb = tk.Label(win1, text="Window3")
        lb.pack()

# Buttons on menu frame
win = tk.Tk()
win.geometry("200x200+200+100")
button = tk.Button(win, text="Open new Window1")
button['command'] = new_window1
button.pack()

button = tk.Button(win, text="Open new Window2")
button['command'] = new_window2
button.pack()

button = tk.Button(win, text="Open new Window3")
button['command'] = new_window3
button.pack()
win.mainloop()
can't run because of MS windows dependencies.
(Apr-27-2020, 04:06 PM)Larz60+ Wrote: [ -> ]can't run because of MS windows dependencies.

Hi, I can run the code fine on my windows 10, only problem is that scrollbars not working with buttons.
I think your problem is that you cannot put buttons on a canvas. You have to create windows on your canvas and put the button in the window. I found this:

https://stackoverflow.com/questions/4127...ter-canvas

Looking at it I see no reason why you couldn't create a window that fits all your buttons and scroll that. Using this method I think you would use labels instead of canvas.create_text
deanhystad,

You can place buttons on Canvas, why do you say it's not possible:
import tkinter as tk


root = tk.Tk()
canvas = tk.Canvas(root)
canvas.pack()
btn = tk.Button(canvas, text='Button')
btn.pack()
root.mainloop()
The question isn't if you can put a button on a canvas. That is obvious from the code posted in the question. The question is why don't any of the buttons scroll when you move the slider. I poked around a bit and each time I found something discussing doing this the solution involved creating windows in the canvas and putting the controls in those windows. The stackoverflow link I included was fairly short and concise.
First, THANK YOU everyone for the help, deanhyard I have tried this example https://stackoverflow.com/questions/4373...-with-grid, I get 2 another problems with this, 1. the images on buttons will not show and 2. I cant get the window in window functions to work. For example when I open new window 1 > window 1, cant get the code right. I REALLY APPRECIATE the help.
Tank You.

Regards
Kraco
Hi deanhystad
https://stackoverflow.com/questions/4373...-with-grid result, button images will not show:
import tkinter as tk
from winsound import * # for sound
from tkinter import * # for photo images
from PIL import ImageTk, Image
from tkinter.ttk import *


LABEL_BG = "#ccc"  # Light gray.
ROWS, COLS = 10, 6  # Size of grid.
ROWS_DISP = 10  # Number of rows to display.
COLS_DISP = 10  # Number of columns to display.

# Sound Files
play1 = lambda: PlaySound('c:\images\siren.wav', SND_FILENAME)
play2 = lambda: PlaySound('c:\images\pling.wav', SND_FILENAME)


class MyApp(tk.Tk):
    def __init__(self, title="Sample App", *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        self.title(title)
        self.configure(background="Gray")
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        master_frame = tk.Frame(self, bg="Light Blue", bd=3, relief=tk.RIDGE)
        master_frame.grid(sticky=tk.NSEW)
        master_frame.columnconfigure(0, weight=1)

        label1 = tk.Label(master_frame, text="Frame1 Contents", bg=LABEL_BG)
        label1.grid(row=0, column=0, pady=5, sticky=tk.NW)

        frame1 = tk.Frame(master_frame, bg="Green", bd=2, relief=tk.GROOVE)
        frame1.grid(row=1, column=0, sticky=tk.NW)

        cb_var1 = tk.IntVar()
        checkbutton1 = tk.Checkbutton(frame1, text="StartCheckBox", variable=cb_var1)
        checkbutton1.grid(row=0, column=0, padx=2)

        label2 = tk.Label(master_frame, text="Frame2 Contents", bg=LABEL_BG)
        label2.grid(row=2, column=0, pady=5, sticky=tk.NW)

        # Create a frame for the canvas and scrollbar(s).
        frame2 = tk.Frame(master_frame)
        frame2.grid(row=3, column=0, sticky=tk.NW)

        # Add a canvas in that frame.
        canvas = tk.Canvas(frame2, bg="PURPLE")
        canvas.grid(row=0, column=0)

        # Create a vertical scrollbar linked to the canvas.
        vsbar = tk.Scrollbar(frame2, orient=tk.VERTICAL, command=canvas.yview)
        vsbar.grid(row=0, column=1, sticky=tk.NS)
        canvas.configure(yscrollcommand=vsbar.set)

        # Create a horizontal scrollbar linked to the canvas.
        hsbar = tk.Scrollbar(frame2, orient=tk.HORIZONTAL, command=canvas.xview)
        hsbar.grid(row=1, column=0, sticky=tk.EW)
        canvas.configure(xscrollcommand=hsbar.set)

        # Create a frame on the canvas to contain the buttons.
        buttons_frame = tk.Frame(canvas, bg="Red", bd=2)

        # Image files to be uploaded in window1
        photo1 = PhotoImage(file="C:\images\plane.png")
        photo2 = PhotoImage(file="C:\images\car.png")
        photo3 = PhotoImage(file="c:\images\_apple.png")

        # Add the buttons to the frame.
        for i in range(1, ROWS+1):
            for j in range(1, COLS+1):
                button1 = tk.Button(buttons_frame, padx=1, pady=1, relief=tk.RIDGE, text="Plane", command=play1,
                                    image=photo1)
                button1.grid(row=1, column=1, sticky='news')
                button2 = tk.Button(buttons_frame, padx=2, pady=2, relief=tk.RIDGE, text="Car", command=play2,
                                    image=photo2)
                button2.grid(row=2, column=1, sticky='news')
                button3 = tk.Button(buttons_frame, padx=1, pady=1, relief=tk.RIDGE, text="Ball", command=play2,
                                    image=photo3)
                button3.grid(row=1, column=2, sticky='news')
                button4 = tk.Button(buttons_frame, padx=2, pady=2, relief=tk.RIDGE, text="Dog", command=play2)
                button4.grid(row=2, column=2, sticky='news')


        # Create canvas window to hold the buttons_frame.
        canvas.create_window((0,0), window=buttons_frame, anchor=tk.NW)

        buttons_frame.update_idletasks()  # Needed to make bbox info available.
        bbox = canvas.bbox(tk.ALL)  # Get bounding box of canvas with Buttons.
        #print('canvas.bbox(tk.ALL): {}'.format(bbox))

        # Define the scrollable region as entire canvas with only the desired
        # number of rows and columns displayed.
        w, h = bbox[2]-bbox[1], bbox[3]-bbox[1]
        dw, dh = int((w/COLS) * COLS_DISP), int((h/ROWS) * ROWS_DISP)
        canvas.configure(scrollregion=bbox, width=dw, height=dh)

        label3 = tk.Label(master_frame, text="Frame3 Contents", bg=LABEL_BG)
        label3.grid(row=4, column=0, pady=5, sticky=tk.NW)

        frame3 = tk.Frame(master_frame, bg="Blue", bd=2, relief=tk.GROOVE)
        frame3.grid(row=5, column=0, sticky=tk.NW)

        cb_var2 = tk.IntVar()
        checkbutton2 = tk.Checkbutton(frame3, text="EndCheckBox", variable=cb_var2)
        checkbutton2.grid(row=0, column=0, padx=2)


if __name__ == "__main__":
    app = MyApp("Scrollable Canvas")
    app.mainloop()
---------------------------------------------------
Tried the pack method, button images will not show:
import tkinter as tk
from winsound import * # for sound
from tkinter import * # for photo images
from PIL import ImageTk, Image
from tkinter.ttk import *


LABEL_BG = "#ccc"  # Light gray.
ROWS, COLS = 10, 6  # Size of grid.
ROWS_DISP = 10  # Number of rows to display.
COLS_DISP = 10  # Number of columns to display.

# Sound Files
play1 = lambda: PlaySound('c:\images\siren.wav', SND_FILENAME)
play2 = lambda: PlaySound('c:\images\pling.wav', SND_FILENAME)


class MyApp(tk.Tk):
    def __init__(self, title="Sample App", *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        self.title(title)
        self.configure(background="Gray")
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        master_frame = tk.Frame(self, bg="Light Blue", bd=3, relief=tk.RIDGE)
        master_frame.grid(sticky=tk.NSEW)
        master_frame.columnconfigure(0, weight=1)

        label1 = tk.Label(master_frame, text="Frame1 Contents", bg=LABEL_BG)
        label1.grid(row=0, column=0, pady=5, sticky=tk.NW)

        frame1 = tk.Frame(master_frame, bg="Green", bd=2, relief=tk.GROOVE)
        frame1.grid(row=1, column=0, sticky=tk.NW)

        cb_var1 = tk.IntVar()
        checkbutton1 = tk.Checkbutton(frame1, text="StartCheckBox", variable=cb_var1)
        checkbutton1.grid(row=0, column=0, padx=2)

        label2 = tk.Label(master_frame, text="Frame2 Contents", bg=LABEL_BG)
        label2.grid(row=2, column=0, pady=5, sticky=tk.NW)

        # Create a frame for the canvas and scrollbar(s).
        frame2 = tk.Frame(master_frame)
        frame2.grid(row=3, column=0, sticky=tk.NW)

        # Add a canvas in that frame.
        canvas = tk.Canvas(frame2, bg="PURPLE")
        canvas.grid(row=0, column=0)

        # Create a vertical scrollbar linked to the canvas.
        vsbar = tk.Scrollbar(frame2, orient=tk.VERTICAL, command=canvas.yview)
        vsbar.grid(row=0, column=1, sticky=tk.NS)
        canvas.configure(yscrollcommand=vsbar.set)

        # Create a horizontal scrollbar linked to the canvas.
        hsbar = tk.Scrollbar(frame2, orient=tk.HORIZONTAL, command=canvas.xview)
        hsbar.grid(row=1, column=0, sticky=tk.EW)
        canvas.configure(xscrollcommand=hsbar.set)

        # Create a frame on the canvas to contain the buttons.
        buttons_frame = tk.Frame(canvas, bg="Red", bd=2)

        # Image files to be uploaded in window1
        photo1 = PhotoImage(file="C:\images\plane.png")
        photo2 = PhotoImage(file="C:\images\car.png")
        photo3 = PhotoImage(file="c:\images\_apple.png")

        # Add the buttons to the frame.
        for i in range(1, ROWS+1):
            for j in range(1, COLS+1):
                button1 = tk.Button(buttons_frame, padx=1, pady=1, relief=tk.RIDGE, text="Plane", command=play1,
                                    image=photo1)
                button1.pack(side=LEFT)
                button2 = tk.Button(buttons_frame, padx=2, pady=2, relief=tk.RIDGE, text="Car", command=play2,
                                    image=photo2)
                button2.pack(side=LEFT)
                button3 = tk.Button(buttons_frame, padx=1, pady=1, relief=tk.RIDGE, text="Ball", command=play2,
                                    image=photo3)
                button3.pack(side=RIGHT)
                button4 = tk.Button(buttons_frame, padx=2, pady=2, relief=tk.RIDGE, text="Dog", command=play2)
                button4.pack(side=RIGHT)


        # Create canvas window to hold the buttons_frame.
        canvas.create_window((0,0), window=buttons_frame, anchor=tk.NW)

        buttons_frame.update_idletasks()  # Needed to make bbox info available.
        bbox = canvas.bbox(tk.ALL)  # Get bounding box of canvas with Buttons.
        #print('canvas.bbox(tk.ALL): {}'.format(bbox))

        # Define the scrollable region as entire canvas with only the desired
        # number of rows and columns displayed.
        w, h = bbox[2]-bbox[1], bbox[3]-bbox[1]
        dw, dh = int((w/COLS) * COLS_DISP), int((h/ROWS) * ROWS_DISP)
        canvas.configure(scrollregion=bbox, width=dw, height=dh)

        label3 = tk.Label(master_frame, text="Frame3 Contents", bg=LABEL_BG)
        label3.grid(row=4, column=0, pady=5, sticky=tk.NW)

        frame3 = tk.Frame(master_frame, bg="Blue", bd=2, relief=tk.GROOVE)
        frame3.grid(row=5, column=0, sticky=tk.NW)

        cb_var2 = tk.IntVar()
        checkbutton2 = tk.Checkbutton(frame3, text="EndCheckBox", variable=cb_var2)
        checkbutton2.grid(row=0, column=0, padx=2)


if __name__ == "__main__":
    app = MyApp("Scrollable Canvas")
    app.mainloop()
I think I know why the button images don't appear. Just yesterday someone was tryin to use image buttons. Their code worked until they created a class for their window. The class/no class code was identical except for one thing; Scope.

The problem was that the images used for the buttons were local variables inside the __init__ method. An image button must not have a reference to the image because as soon as the __init__ method exited and the local image variable went poof, so did the image. Changing the image variables from local to instance variables fixed the problem.

Please don't ask me why that happened because I haven't figured it all out for myself. Using that same logic your images should not have appeared in your earlier code (the one with image buttons that didn't scroll) since your image variables were local to your win1 function. Still a bit of a mystery

Try using self.photo1 instead of photo1 and see if that makes a difference. If so, that is another piece of the puzzle and it may be worth investigating what combinations of classes/functions/globals work with image buttons.
Pages: 1 2