Help with adding images to buttons, Pi filepaths?

Hi! Absolutely a noob to Python, this could be entirely wrong. The other portion of this project at large involved steppers and arduino, which was more my jam, I do not know the first thing about Pis and Python.
I had existing code with text buttons that worked just fine, but now I’m trying to get button graphics going. I have multiple buttons but they are all having the same issues at this point, so I’ll just give snippets of the stuff that I added/changed

Calling on the images:

 Homepng = PhotoImage(file = r"/home/pi/Desktop/Home.png")
        Homepngsz = Homepng.subsample(imgsz, imgsz) 

Creating the “Home” Button

       # Button for Homing (Single tap)
        self.button_homing = tk.Button(master, text= "Home Position", image=  Homepngsz, width=26, height=12, bg="red")
        self.button_homing.grid(row=1, column=2, padx=12, pady=10)
        self.button_tighten_upper.bind("<ButtonPress>", self.send_homing)

I’m currently tied up in getting errors that the directory/file does not exist, however I’m giving everything in case there is a glaring issue somewhere else that will come up once I fix the filepath.

TL;DR

I don’t know if I am calling out the filepath correctly to pull an image to make a graphic button; any imput would be great! :smile:

Hi,

it helps if you include the exact error message that you are observing from Python.

From your partial code, can you try the following since it appears that you are using classes for your script:

self.Homepng = PhotoImage(file = r"/home/pi/Desktop/Home.png")

Also try backward slashes vs. forward slashes.

and for now, comment out this line (if it is valid by the way, it would also require self prefix):

Homepngsz = Homepng.subsample(imgsz, imgsz) 
1 Like

Here’s the error that I got:

Traceback (most recent call last):
  File "/home/pi/Desktop/Chair Control With Graphics.py", line 110, in <module>
    app = MotorControlApp(root, serial_obj=ser)
  File "/home/pi/Desktop/Chair Control With Graphics.py", line 22, in __init__
    LoosenLumbarpng = PhotoImage(file = r"/home/pi/pictures/LoosenLumbar.png")
  File "/usr/lib/python3.7/tkinter/__init__.py", line 3545, in __init__
    Image.__init__(self, 'photo', name, cnf, master, **kw)
  File "/usr/lib/python3.7/tkinter/__init__.py", line 3501, in __init__
    self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't open "/home/pi/pictures/LoosenLumbar.png": no such file or directory

Different button was giving the error, but I think it just displays the first one it comes across.

As for the self prefix, where would that be applied?

Classes are generally a more advanced topic of Python (if you’re already familiar with other languages and OOP in general, then instances should be a familiar topic).

When working with classes, you create instances of those classes. In order for different parts of your class to have access to names (variables), you have to use the self prefix. Otherwise, you will get an error. Since, as you say, you are a total noob, I don’t want to go further on the topic as it might be a little confusing without persistent practice and theoretical background.

As per my previous post, can you try backward slashes for your file. As in:

self.Homepng = PhotoImage(file = r"\home\pi\Desktop\Home.png")
1 Like

Thanks for the refresher, last time I did anything truly OOP was with Java some 6 years ago in high school, been sticking to C arduino projects since then. I’ll fix my prefixes and check for other syntax stuff while I’m at it, and hopefully it will work!

Appears like you have a lot on your plate. First, you have to learn Python and then learn Tkinter.

In any case, here is a test script. Maybe you can learn from it and apply it to your application.
For this script, save it in the same folder as your .gif file.

import tkinter as tk

RELIEFS = [tk.SUNKEN, tk.RAISED, tk.GROOVE, tk.RIDGE, tk.FLAT]

class ButtonsApp(tk.Tk):

    def __init__(self):

        super().__init__()

        self.img = tk.PhotoImage(file = "python_test.gif")
        self.btn = tk.Button(self, text = "Button with image",
                             image = self.img, compound = tk.LEFT,
                             command = self.disable_btn)

        self.btns = [self.create_btn(r) for r in RELIEFS]
        self.btn.pack()

        for btn in self.btns:
            btn.pack(padx=10, pady=10, side=tk.LEFT)

    def create_btn(self, relief):
        return tk.Button(self, text=relief, relief=relief)

    def disable_btn(self):
        self.btn.config(state=tk.DISABLED)

if __name__ == "__main__":

    app = ButtonsApp()
    app.mainloop()
1 Like

Honestly, seeing a working piece of code is great to hold mine against. One question with the filepath,
upon seeing this:

self.img = tk.PhotoImage(file = "python_test.gif")

Would the program look only in the “space” that the .py is in to find the file?

Again, thanks for the help so far!

If the file .gif file is located in the same location as the script file, then you only need the filename in the path. However, if the .gif file is located in a different folder (i.e., directory), then you need to include the file path. Look at this example (I have only included the test script up to the point where the file is being set). Modify the code as shown here but make sure to include your specific path.

from pathlib import Path

# Create CONSTANT that represents where your file is stored on your computer
GIF_FILE = Path('/Users/my_comp/Desktop/test_folder/python_test.gif')

import tkinter as tk

RELIEFS = [tk.SUNKEN, tk.RAISED, tk.GROOVE, tk.RIDGE, tk.FLAT]

class ButtonsApp(tk.Tk):

    def __init__(self):

        super().__init__()

        self.img = tk.PhotoImage(file = GIF_FILE)

A little extra.

Since you are just learning Python and Tkinter, here are two recommended books:

  1. Learning Python, 5 Ed, Mark Lutz
  2. Tkinter GUI Application Development Cookbook
1 Like

Thanks for the reccomended reading, hopefully I can start my own Python project at my own pace and get a good feel for it, jumping blind into a half-finished code and adding capabilities is definitely not the best learning enviroment.

On the topic of Tkinter, if I wanted to change the button color to a hex value outside of their list of colors (i.e. “Red”), can I simply add the hex value as a string (i.e. “#A1224E”)?

To be honest, I don’t know. I would not be surprised if there is though. On one of my test scripts, I created a button and colored it as shown here.

self.btn_login = tk.Button(self, text = "Start Test", command = self.verifyUser, cursor = "hand2", bg = "light blue", activebackground = 'light green')

Here, the button has a general light blue appearance. When pressed (active), I have it changing to light green.

Here is another resource for Tkinter:

Tkinter 8.5 reference: a GUI for Python (anzeljg.github.io)

1 Like

In case you are curious, yes you can.

They worded it like hex values are actually the standard, and that the “named” colors is more of a convenience.

1 Like

Nice! Glad you figured it out. :wink:

If you are in need of a list:
python - Get Tk winfo_rgb() without having a window instantiated - Stack Overflow

1 Like

It looks in the current working directory in which you’re running
Python. Just like C’s fopen looks in the directory the C program it
running in if you give it a relative path.

There’s no direct association with where the Python .py script is,
any more than there is with the location of some compiled-from-C
executable which is opening a file.

1 Like

You need to understand how paths work (this is the common “language” of typical operating systems).

1 Like

Good reading, thank you, I think I was just mixed up with the syntax of the Pi (linux) directory, vs Windows which is all I have worked with before.