0

There is this question to discover existing types:

However I've just developed tooltips (balloons) I've assigned to some buttons and would like to be able to recall all of them as a unique type. Also down the road I'd like to hand-craft canvas objects which will operate like pseudo buttons with <enter>, <leave>, <active>, <press> and <release> events. How might I declare a new object type for them?

WinEunuuchs2Unix
  • 1,801
  • 1
  • 17
  • 34

2 Answers2

1

Object Oriented Programming is probably the solution.

If I want to create a "new type" of tkinter button I can sub-class it.

class MySpecialButton(tkinter.Button):
    pass

This doesn't do anything special at the moment but will give it a unique type (If it have understood your interpretation correctly)

The following example from another one of my answers, creates a special button with custom behaviour for hovering over the button

class HoverButton(tk.Button):
    def __init__(self, master, **kw):
        tk.Button.__init__(self,master=master,**kw)
        self.defaultBackground = self["background"]
        self.bind("<Enter>", self.on_enter)
        self.bind("<Leave>", self.on_leave)

    def on_enter(self, e):
        self['background'] = self['activebackground']

    def on_leave(self, e):
        self['background'] = self.defaultBackground

With regard to canvas object, You can obviously create classes for these too which can contain methods for moving/resizing the object. As to how to create custom events for these, you can use tag_bind(item, event=None, callback=None, add=None) to bind a call back to a canvas object. A quick example below

import tkinter as tk

class CanvasShape:
    def __init__(self, canvas, callback = None):
        self.canvas = canvas
        self.id = canvas.create_oval(10,10,50,50,fill='blue')
        self.canvas.tag_bind(self.id,'<Button-1>',callback)

def clicked(e):
    print("You clicked on a shape")

root = tk.Tk()
c = tk.Canvas(root,width=200,height=200)
c.grid()
shape = CanvasShape(c,callback=clicked)

root.mainloop()

This will create a circle that when you click on it will fire an event that is received by the clicked function.

scotty3785
  • 6,763
  • 1
  • 25
  • 35
  • I don't think this answers the question – Delrius Euphoria Jun 04 '21 at 09:54
  • @CoolCloud Thanks for your feedback. Which aspects do you feel aren't answered? – scotty3785 Jun 04 '21 at 10:40
  • I'm already using your `HoverButton` class. The question is how do I find the 20 hover buttons and loop through them by searching on their object type? – WinEunuuchs2Unix Jun 04 '21 at 12:07
  • @WinEunuuchs2Unix Find the 20 hover buttons? This seems like an XY problem, why don't you make a new question explaining what you are actually trying to do and include some code for the custom class – Delrius Euphoria Jun 04 '21 at 14:01
  • @CoolCloud It could be an XY question I guess. I found a way simpler solution than parsing object types. I simply register objects as they are created to a list. Then to find all the objects of that type I simply loop through the list. Much simpler than using Tkinter calls to find all object types of a given type within parent `Tk.TopLevel` and all child `Tk.TopLevel` children including `Tk.Frame` with tooltips. Remind me in a few days and if another answer doesn't come up I'll accept one of them. Thanks. – WinEunuuchs2Unix Jun 05 '21 at 15:31
  • @scotty3785 It may interest you this project is to take balloons that work fine with `on_enter` and `on_leave` events (your function names not mine). Now I need a polling function to have tooltips (balloons) appear after 500 milliseconds (1/2 second) and fade after 5000 milliseconds (5 seconds). The current detailed design is drastically changed from the general design a couple days ago. Now my above question for discovering the python tkinter custom object type is a mute point. Your bonus canvas creation is very helpful though! Thanks. – WinEunuuchs2Unix Jun 05 '21 at 15:37
1

If I understand your question correctly you want to check if an instance created is a instance of the custom class, it can be directly done using isinstance:

class CustomTooltip():
    pass

cwidget = CustomTooltip()
btn     = tk.Button(root)

print(isinstance(cwidget, CustomTooltip)) # True
print(isinstance(b, CustomTooltip)) # False

print(type(cwidget) == CustomTooltip) # Not recommended

It is recommended to use isinstance rather than type, from the docs:

The isinstance() built-in function is recommended for testing the type of an object, because it takes subclasses into account.


I did not quite get your 2nd question, also it is better to keep a single question focused around one main question rather than asking more than one question.

Delrius Euphoria
  • 14,910
  • 3
  • 15
  • 46
  • Thank you for `isinstance()` documentation. I really wasn't asking a second question on how to convert rectangular buttons to rounded buttons of canvas type. I was just trying to give a brief project overview to explain why I needed to get python tkinter custom object types. In hind sight I should have instead said the purpose wast to track all balloon hovertips and fade them in after 1/2 second and fade them out after 5 seconds. – WinEunuuchs2Unix Jun 05 '21 at 15:54
  • @WinEunuuchs2Unix Cool, I have done the same thing in the past ~ like [this](https://github.com/nihaalnz/MPlayer/blob/c633936acce9228f717b98766b4853162d2beda7/widgets.py#L79). Now I have improved it alot by making it rounded and adding wait time and many more extra features. In a nutshell, I answered your question correctly, I assume? – Delrius Euphoria Jun 05 '21 at 15:56
  • 1
    I checked your link to `MPlayer` and my application is called `mserve` [Music Server](https://github.com/WinEunuuchs2Unix/mserve). No code yet but you can click on `Issues` to see sample screen. I think your answer is correct but would like to wait a couple of days to see what other answers lurk out on the web. – WinEunuuchs2Unix Jun 05 '21 at 16:14
  • @WinEunuuchs2Unix That was a coincidence, I meant for you to have some look at the tooltip, anyway great project :D Hoping to see the source code soon – Delrius Euphoria Jun 05 '21 at 20:43
  • 1
    "soon" is a relative term. I've been working on `mserve` for a year and I think soon it will be done in a year or two. As I learn new things like SQL I go back and rewrite functions that have pickles for Audio CD track listings from MusicBrainz for example. There are things like accessing file server's music through SSH or cell phones music over WiFi I already know need major rewrites ***sigh***. I did look at your code and I wish I saw it two days ago as I've just finished fading in tooltips after 500 ms delay and fading out after 5 seconds. Thanks for the few times you've already helped me! – WinEunuuchs2Unix Jun 05 '21 at 21:05
  • Also if you want to find yourself the modern type of tooltip that I was talking about, take a look [here](https://github.com/nihaalnz/mtk/blob/main/roundtools.py) – Delrius Euphoria Jun 10 '21 at 11:45
  • The modern type of tooltip will be helpful when I do version 2. I'd like to check out the window shadow. My version 1 is working perfectly including deactivating buttons that tkinter leaves activated because it fails to recognize the `` event can occur before `` event is finished generating tooltip window (read mouse moves EXTREMELY fast over button). I can't use the link as is because all my functions can't use more than a few milliseconds because of timeshare function that allows all animations to run at 30 fps so each function expects to be called every 33 ms. – WinEunuuchs2Unix Jun 10 '21 at 22:45
  • BTW your answer doesn't explain what a subclass is. That could be helpful for other OOPS neophytes like myself. – WinEunuuchs2Unix Jun 10 '21 at 22:48
  • @WinEunuuchs2Unix Great great. Well its just a google search away ~ https://www.geeksforgeeks.org/oop-in-python-set-3-inheritance-examples-of-object-issubclass-and-super/#:~:text=In%20inheritance%2C%20a%20class%20(usually,inheritance%20is%20implemented%20in%20Python.&text=%23%20Base%20or%20Super%20class. As an example, every tkinter widget is a subclass of the superclass `tk.Widget`. So if you want to check if something is a widget, feel free to `isinstance(tk.Button,tk.Widget)` because `isinstance` takes subclasses into consideration as well. – Delrius Euphoria Jun 11 '21 at 07:31