Title: Make a moveable shaped analog clock in tkinter and Python
My post Make a shaped analog clock in tkinter and Python explains how to build a shaped analog clock. Unfortunately, because it has no title bar, there's no way for the user to move it. This post explains how you can let the user move a form that doesn't have a title bar. The trick is to catch mouse down and mouse move events.
The program uses the following code to install mouse down and mouse move event handlers.
self.window.bind("", self.mouse_down)
self.window.bind("", self.mouse_move)
When you press the left mouse button down over the window, the following mouse_down event handler springs into action.
def mouse_down(self, event):
'''Begin moving the window.'''
self.window.start_x = event.x
self.window.start_y = event.y
This code simply saves the mouse's current position in the class variables start_x and start_y.
If you move the mouse while the left mouse button is pressed, the following code executes.
def mouse_move(self, event):
'''Continue moving the window.'''
x = self.window.winfo_x() + event.x - self.window.start_x
y = self.window.winfo_y() + event.y - self.window.start_y
self.window.geometry(f"+{x}+{y}")
The way the values go into the new window position is a bit confusing. First, consider the program's goal. It moves the window so the point under the mouse doesn't change. For example, if you press the mouse down while it's over the middle of the clock and then move the mouse, the program moves the window so the center of the clock remains under the mouse.
The program saves the start_x value when you press the mouse down. Now suppose you move the mouse, say, 2 pixels to the right. Within the mouse_move event handler, event.x is measured with respect to the window's current origin so its value is 2 larger than start_x. (Because you just moved the mouse 2 pixels to the right, remember?)
To move the window to keep the mouse over the window's center, we need to add 2 to the window's current X position. We get that offset value from event.x - self.window.start_x and add it to the window's current X position self.window.winfo_x().
The program calculates the Y offset similarly and then calls self.window.geometry to update the window's position. As a result, the window moves the small distance between the mouse's star position and its current position.
Conclusion
Allowing the user to move a window that doesn't have a title bar is pretty easy. Just track mouse down and mouse move events to update the window's position. Using this technique and the one described in my post Make a shaped analog clock in tkinter and Python, you can make moveable shaped windows. That's handy for things like clocks, but you can use similar techniques to make unique and interesting splash screens or even application windows. (But I'm not sure if I'm going to do that.) (Who am I kidding? I'm definitely going to do that sooner or later!)
Download the example to experiment with it and to see additional details.
|