Reputation: 1
I was making a game with pyglet, and I decided to make window draggable on anywhere (In detail, you can drag window by clicking anywhere on the window, not only top bar of the window) However, the window flickered between two positions when I dragged it.
How can I solve it?
Here is the code:
import pyglet
class Window(pyglet.window.Window):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
winpos = self.get_location()
self.set_location(winpos[0] + dx, winpos[1] - dy)
if __name__ == "__main__":
win = Window(400, 300)
pyglet.app.run()
Upvotes: 0
Views: 209
Reputation: 11
I just encountered your problem last night. I think it's the movement of mouse w.r.t the movement of the window caused this issue, or so called relative movement, i.e. you are trying to move the window according to the movement of the mouse, but the position of the mouse is recorded with respect to the position of the window itself, which is also changing.
To solve this you can change from "relative position" to "absolute position", unfortunately, pyglet can only provide you the former one. I figured out a workaround using the package called pyautogui, which provides the absolute position of the mouse.
Below is my code, a bit too bloated, the main difference is: instead of getting relative x and y directly from pyglet's on_mouse_drag()
, use pyautogui.position()
and get the absolute x and y:
import pyglet
import pyautogui
import numpy as np
# create a pyglet window
win = pyglet.window.Window()
# a movement manager class, which records all mouse movement during a drag action, and turn it into movement of the window accordingly.
class windowMovementManager():
def __init__(self,wSX,wSY):
self.windowStartPositionVector=np.array([wSX,wSY])
self.mouseStartPositionVector=np.array([0,0])
self.windowDestinationVector=self.windowStartPositionVector
def mousePressed(self,mSX,mSY):
self.mouseStartPositionVector=np.array([mSX,mSY])
def move(self,mCX,mCY):
mouseCurrentPositionVector=np.array([mCX,-mCY])
movementVector=mouseCurrentPositionVector-self.mouseStartPositionVector
self.windowDestinationVector=self.windowStartPositionVector+movementVector
if self.windowDestinationVector[0]<0:
self.windowDestinationVector=0
if self.windowDestinationVector[1]<0:
self.windowDestinationVector[1]=0
win.set_location(windowMovementManagerObj.windowDestinationVector[0],windowMovementManagerObj.windowDestinationVector[1])
def mouseReleased(self):
self.windowStartPositionVector=self.windowDestinationVector
windowMovementManagerObj=windowMovementManager(win.get_location()[0],win.get_location()[1])
# below is how pyglet.window.Window object communicate with my movement manager object. All movement are recorded in the movement manager object because I want to keep track of
# mouse movements in between several mouse action sessions, into the movement object for later usage.
@win.event()
def on_mouse_press(x, y, button, modifiers):
global windowMovementManagerObj
mouseAbsX,mouseAbsY=pyautogui.position()
windowMovementManagerObj.mousePressed(mouseAbsX,mouseAbsY)
@win.event()
def on_mouse_drag(x, y, dx, dy, buttons, modifiers):
global windowMovementManagerObj
mouseAbsX, mouseAbsY = pyautogui.position()
windowMovementManagerObj.move(mouseAbsX,-mouseAbsY)
print(windowMovementManagerObj.windowDestinationVector)
@win.event()
def on_mouse_release(x, y, button, modifiers):
global windowMovementManagerObj
windowMovementManagerObj.mouseReleased()
# run our pyglet app, and show the window
pyglet.app.run()
Upvotes: 1