a I had a similar problem. I am building an application where the GUI is compatible with both MacOS and Windows OS.
Problem: I want to create a button from an image. However, it must work in both MacOS and Windows (or at least find a solution for each respectively). Tkinter.Button wasn't working on MacOS, and Tkmacosx.Button had undesirable behaviors.
I will post some code, but the answer is very simple, ttk.Button()
works on both.
However, when using a ttk button, there is no movement animation when the button is clicked. When all borders are gone and all different background colors are set to the same color, the button doesn't move confirming to the user the button was clicked.
To fix this, we will bind the click and the click-release both to their own methods. Both methods just .place
the button, click +1 pixels to x and y, and unclick sends the button back to its starting location.
class Root(bootstrap.Window):
"""
Root UI comprised of import button and 'up-to-date' tracking system indicator
"""
def __init__(self):
super().__init__()
self.settings = UIOptions().settings
# Window Configuration
self.title("Automated Expenses Manager")
self.option_add("*tearOff", False)
self.geometry("1000x700")
self.resizable(False, False)
self.config(background='dark grey')
# Arrow Image Button
style = bootstrap.Style()
style.configure(style='Arrow.TButton', background='dark grey',
highlightcolor='dark grey', borderwidth=0,
focuscolor='dark grey')
style.map('Arrow.TButton',
background=[('active', 'dark grey')],)
arrow_image = ImageTk.PhotoImage(Image.open(ARROW_IMAGE).resize((235, 150), Image.Resampling.LANCZOS))
self.arrow = bootstrap.Button(self,
style='Arrow.TButton',
image=arrow_image)
self.arrow.bind("<Button-1>", self.click)
self.arrow.bind("<ButtonRelease-1>", self.unclick)
self.arrow.place(x=390, y=80, anchor='nw')
self.mainloop()
def click(self, event):
self.arrow.place(x=391, y=81, anchor='nw')
def unclick(self, event):
self.arrow.place(x=390, y=80, anchor='nw')
Inside this class, you will see I did a style map style.map()
. The first positional argument is the style name of which to modify, and in my code I name a property I want to modify and send it a list of tuples. Each tuple indicts a specific event and a value for the named property that will be set, when the event occurs.
I had a problem with hovering over the button. It would change the background color of the button. The solution is to map 'active' - when the mouse hovers the widget, to the same color as the root window background color ('active', 'dark grey')
. This stops the widget from changing colors when hovered, because it's just changing to the same color the background already was.
This code runs on both MacOS and Windows perfectly.
Hope it helps!
tkmacosx
. Easy to install via pip - requirements look pretty straight forward... as far as I can tell it's all pure python and available on pypi. Credit to Victor VosMottor for mentioning it: https://mcmap.net/q/334749/-how-to-change-the-foreground-or-background-colour-of-a-tkinter-button-on-mac-os-x – Chickasaw