1

Is it possible to scroll text box by just hovering on the window i.e. without having to click on the GUI? I'm using tkinter to develop the program.

last day
  • 13
  • 3
  • What have you tried so far? Also take a look at https://stackoverflow.com/questions/20399243/display-message-when-hovering-over-something-with-mouse-cursor-in-python and https://stackoverflow.com/questions/22751100/tkinter-main-window-focus – Nouman Apr 09 '21 at 05:05
  • The only solution I can really think of is, first of use the topmost attribute and second, track mouse position and if it enters the window set focus to it – Matiiss Apr 09 '21 at 07:22
  • About my answer: it works but it has to be adjusted because for example if there was a widget that widget is not root so if the focus is on the widget e.g. Entry and mouse moves away but still inside the window the focus will be lost from Entry widget – Matiiss Apr 09 '21 at 07:53
  • Another my suggestion is that in that function that tracks motion You place a while True loop in which You put the given loop and a loop that will work when there is focus that will check when there is no focus which will then break out and move to the first loo – Matiiss Apr 09 '21 at 08:01
  • Just in case You haven't noticed I edited my answer and code so that it solves some issues as mentioned before. – Matiiss Apr 09 '21 at 08:34

1 Answers1

0

So here is my solution:

from tkinter import Tk, Entry
import pyautogui
from _thread import start_new_thread


def track_motion(root):
    while True:
        while True:
            window_xtl = root.winfo_x()
            window_ytl = root.winfo_y()
            window_xbr = window_xtl + root.winfo_width()
            window_ybr = window_ytl + root.winfo_height()

            mouse_pos = pyautogui.position()
            mouse_x = mouse_pos[0]
            mouse_y = mouse_pos[1]

            if window_xtl < mouse_x < window_xbr and window_ytl < mouse_y < window_ybr:
                for _ in range(500):
                    root.focus_force()

                while True:
                    window_xtl = root.winfo_x()
                    window_ytl = root.winfo_y()
                    window_xbr = window_xtl + root.winfo_width()
                    window_ybr = window_ytl + root.winfo_height()

                    mouse_pos = pyautogui.position()
                    mouse_x = mouse_pos[0]
                    mouse_y = mouse_pos[1]

                    if window_xtl > mouse_x or mouse_x > window_xbr or window_ytl > mouse_y or mouse_y > window_ybr:
                        break


root = Tk()
root.geometry('300x300')
root.attributes('-topmost', True)

start_new_thread(track_motion, (root, ))

entry = Entry(root)
entry.pack()

entry2 = Entry(root)
entry2.pack()

root.mainloop()

For this You will have to install pyautogui using pip: pip install pyautogui. The way this works is that first of the window is always on top which is important because otherwise it would seem strange to have a window pop up out of nowhere.

What happens here is that first we run the function in a separated thread so that it doesn't interfere with tkinter's .mainloop(). In that loop we check the current windows position and current mouse position and then it checks whether the x and ycoordinates of the mice are inside the coordinates of the window, and if they are set focus to that window.

I made some changes to the code. I added another loop to switch off the focusing so that it is possible to use other widgets. Also noticed that pyautogui doesn't return the position of the tip of the pointer which means that it is possible to move the pointer slightly in before getting focus. Also there is that for loop because it is needed for some reason otherwise it doesn't get focus.

Matiiss
  • 5,970
  • 2
  • 12
  • 29