0

"I'm learning Tkinter from the "GUI Programming Cookbook". Using my MacBook Pro running Mojave, python3.8 and the Tkinter that came packaged. There is one method where a popup tool tip shows when the mouse is hovered over a widget. It works fine on Win 10 and linux, but the popup does not appear on my Mac. There are no errors.

I put in some debug print() statements and the mouse coordinates and movement are correct.

This works****. Window text hovers over widget

here is output from print(sys.version) on linux.

3.7.4 (default, Jul 9 2019, 16:48:28) [GCC 8.3.1 20190223 (Red Hat 8.3.1-2)]

This doe NOT work **** popup does not appear

output from print(sys.version) on Mac

3.8.0 (v3.8.0:fa919fdf25, Oct 14 2019, 10:23:27) [Clang 6.0 (clang-600.0.57)]

===================

'''
Created on May 3, 2019

@author: Burkhard A. Meier
'''
#======================
# imports
#======================
import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext
from tkinter import Menu
from tkinter import messagebox as msg
from tkinter import Spinbox


        #====================================================
class ToolTip(object):
    def __init__(self, widget, tip_text=None):
        self.widget = widget
        self.tip_text = tip_text
        widget.bind('<Enter>', self.mouse_enter) 
          # bind mouse events
        widget.bind('<Leave>', self.mouse_leave)

    def mouse_enter(self, _event):
        self.show_tooltip()
        print('entered the widget')

    def mouse_leave(self, _event):
        self.hide_tooltip()
        print('entered the widget')

    def show_tooltip(self):
        if self.tip_text:
            x_left = self.widget.winfo_rootx()
                # get widget top-left coordinates
            y_top = self.widget.winfo_rooty() - 18  
            
            #DEBUG
            print('self.widget, y_top, x_left')
            print(self.widget, y_top, x_left)
            
            # place tooltip above widget or it flickers

            self.tip_window = tk.Toplevel(self.widget)   
           # create Toplevel window; parent=widget
            self.tip_window.overrideredirect(True)     
            # remove surrounding toolbar window
            self.tip_window.geometry("+%d+%d" % (x_left, y_top)) 
            # position tooltip

            #print('\nTOOLTIP before author code line')
            #print(self.tip_text)
            #label = tk.Label(self.tip_window, text=self.tip_text,
             #justify=tk.LEFT, background="#ffffe0",
             # relief=tk.SOLID,
             #borderwidth=1, font=("tahoma", "8", "normal"))

            #below is my code cus the above line does 
            #not show up EKK 10/25/19

            label = tk.Label(self.tip_window, text=self.tip_text,
             justify=tk.LEFT)
            label.pack(fill="both")
            #label.pack(ipadx=1)

            print('TOOLTIP after author code line')
            print(self.tip_text)

    def hide_tooltip(self):
        if self.tip_window:
            self.tip_window.destroy()

#=====================================================
# just added all the code.
# the above class is called by the Spinbox and Scroll methods below.

          # Create instance
win = tk.Tk()   
    
# Add a title       
win.title("Python GUI")  
    
tabControl = ttk.Notebook(win)          # Create Tab Control
    
tab1 = ttk.Frame(tabControl)            # Create a tab 
tabControl.add(tab1, text='Tab 1')      # Add the tab
tab2 = ttk.Frame(tabControl)            # Add a second tab
tabControl.add(tab2, text='Tab 2')      # Make second tab visible
    
tabControl.pack(expand=1, fill="both")  # Pack to make visible
    
# LabelFrame using tab1 as the parent
mighty = ttk.LabelFrame(tab1, text=' Mighty Python ')
mighty.grid(column=0, row=0, padx=8, pady=4)
    
# Modify adding a Label using mighty as the parent instead of win
a_label = ttk.Label(mighty, text="Enter a name:")
a_label.grid(column=0, row=0, sticky='W')
    
# Modified Button Click Function
def click_me(): 
    action.configure(text='Hello ' + name.get() + ' ' + 
                     number_chosen.get())
    
# Adding a Textbox Entry widget
name = tk.StringVar()
name_entered = ttk.Entry(mighty, width=12, textvariable=name)
name_entered.grid(column=0, row=1, sticky='W')               
# align left/West
    
# Adding a Button
action = ttk.Button(mighty, text="Click Me!", command=click_me)   
action.grid(column=2, row=1)                                
    
ttk.Label(mighty, text="Choose a number:").grid(column=1, row=0)
number = tk.StringVar()
number_chosen = ttk.Combobox(mighty, width=12, textvariable=number, state='readonly')
number_chosen['values'] = (1, 2, 4, 42, 100)
number_chosen.grid(column=1, row=1)
number_chosen.current(0)
    
# Spinbox callback 
def _spin():
    value = spin.get()
    print(value)
    scrol.insert(tk.INSERT, value + '\n')
         
# Adding a Spinbox widget
spin = Spinbox(mighty, values=(1, 2, 4, 42, 100), width=5, bd=9, command=_spin) 
# using range
spin.grid(column=0, row=2)
   
    # Add a Tooltip to the Spinbox
ToolTip(spin, 'This is a Spin control')
     
# Using a scrolled Text control    
scrol_w  = 30
scrol_h  =  3
scrol = scrolledtext.ScrolledText(mighty, width=scrol_w, height=scrol_h, wrap=tk.WORD)
scrol.grid(column=0, row=3, sticky='WE', columnspan=3)                    
    
# Add a Tooltip to the ScrolledText widget 
ToolTip(scrol, 'This is a ScrolledText widget') 
   
# Bunch of code snipped here

name_entered.focus()      # Place cursor into name Entry
#======================
# Start GUI
#======================
win.mainloop()
    

the class is called from other code. the label on lines 42 and 46 will not show up on my MacBook but everything is fine on windows and Linux. There are no error messages. the window just never appears. anyone have suggestions?? I'm going nuts here! Thanks in advance.

Community
  • 1
  • 1
  • here is the output to the terminal window after adding print statement into the enter and leave functions in the code; TOOLTIP after author code line This is a ScrolledText widget entered the widget left the widget – user10865082 Oct 26 '19 at 15:51
  • I just found something from staging python.org. --- says to use Acive State. I'm researching now. – user10865082 Oct 26 '19 at 16:58
  • Next check: `print(self.widget, y_top, x_left)` **after** `if self.tip_text:`. Read [overrideredirect-prevents-certain-events-in-mac-and-linux](https://stackoverflow.com/questions/34582637/tkinters-overrideredirect-prevents-certain-events-in-mac-and-linux) – stovfl Oct 26 '19 at 20:03
  • output of print =====. self.widget, y_top, x_left .!notebook.!frame.!labelframe.!frame 263 163. If I move the window the coordinates follow – so it know the text was passed – user10865082 Oct 26 '19 at 22:24
  • I'm off, one last thought, put your `__main__`, starting at line `# Create instance` into a `if __name__ == "__main__" :` block. Read [executing-modules-as-scripts](https://docs.python.org/3/tutorial/modules.html#executing-modules-as-scripts) – stovfl Oct 27 '19 at 10:31
  • stovfl. --- The __main__ idea bombed also. Same results. This has to be a focus issue or something. Maybe its printing, but not in the right frame???? Who knows? Thanks for all your suggestions. I'm going to finish the book exercises on my linux box. I'll come back and tackle this later. It's really frustrating that the Mac is so good at some things and so terrible at others. I really appreciate all your suggestions. Learning to use C 30 years ago was a piece of cake compared to this! – user10865082 Oct 27 '19 at 22:10

1 Answers1

1

If you're still having this problem on Mac OSX, I found a reddit thread that pointed to:

https://github.com/python/cpython/blob/master/Lib/idlelib/tooltip.py

I added the following two lines to the end of my show_tooltip():

tw.update_idletasks()  # Needed on MacOS -- see #34275.
tw.lift()  # work around bug in Tk 8.5.18+ (issue #24570)

And the tooltips started showing up.

kamion
  • 461
  • 2
  • 9
  • Use `tw.update()` instead of `tw.update_idletasks()` and sometime just using `tw.lift()` just before the `mainloop()` works just fine as well. There are different ways to fix this issue see this [post](https://stackoverflow.com/a/55873471/10364425). – Saad May 29 '20 at 17:58
  • What does `tw` refer to? – The epic face 007 Nov 09 '21 at 01:39
  • @ViniDalvino `tw` is referring to: https://github.com/python/cpython/blob/cfc9154121e2d677b782cfadfc90b949b1259332/Lib/idlelib/tooltip.py#L30 – kamion Nov 09 '21 at 06:11