views:

31

answers:

1

Any suggestions on how one might create event bindings that would allow a user to mouse drag a window without borders, eg. a window created with overridedirect(1)?

Use case: We would like to create a floating toolbar/palette window (without borders) that our users can drag around on their desktop.

Here's where I'm at in my thinking (pseudo code):

1. window.bind( '<Button-1>', onMouseDown ) to capture the initial position of the mouse.

2. window.bind( '<Motion-1>', onMouseMove ) to track position of mouse once it starts to move.

3. Calculate how much mouse has moved and calculate newX, newY positions.

4. Use window.geometry( '+%d+%d'% ( newX, newY ) ) to move window.

Does Tkinter expose enough functionality to allow me to implement the task at hand? Or are there easier/higher-level ways to achieve what I want to do?

+1  A: 

Yes, Tkinter exposes enough functionality to do this, and no, there are no easier/higher-level ways to achive what you want to do. You pretty much have the right idea.

here's an example:

import Tkinter as tk
import tkFileDialog 

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.floater = FloatingWindow(self)

class FloatingWindow(tk.Toplevel):
    def __init__(self, *args, **kwargs):
        tk.Toplevel.__init__(self, *args, **kwargs)
        self.overrideredirect(True)

        self.label = tk.Label(self, text="Click on the grip to move")
        self.grip = tk.Label(self, bitmap="gray25")
        self.grip.pack(side="left", fill="y")
        self.label.pack(side="right", fill="both", expand=True)

        self.grip.bind("<ButtonPress-1>", self.StartMove)
        self.grip.bind("<ButtonRelease-1>", self.StopMove)
        self.grip.bind("<B1-Motion>", self.OnMotion)

    def StartMove(self, event):
        self.x = event.x
        self.y = event.y

    def StopMove(self, event):
        self.x = None
        self.y = None

    def OnMotion(self, event):
        deltax = event.x - self.x
        deltay = event.y - self.y
        x = self.winfo_x() + deltax
        y = self.winfo_y() + deltay
        self.geometry("+%s+%s" % (x, y))



app=App()
app.mainloop()
Bryan Oakley
Bryan! Thank you very much for your help. What a cool feature - I'm going to have a lot of fun building tools that take advantage of this capability. I also enjoyed your technique for creating the grip - very clever. For readers following this thread, I added the line "self.attributes( '-topmost', 1 )" after the line "self.overrideredirect(True)" to make Bryan's floating window show on top of all windows. I think this shows off the potential for how one might use Bryan's solution to create a variety of desktop utilities.
Malcolm