Cursor position stops working after cursor leaves window - python

I a pretty new to panda3d, and I came across a problem that I have no idea how to fix. I am trying to control the camera using the cursor's location, but every time it the cursor leaves the application window, and reenters it the program stops recording the cursor's position. Is this a task problem? I put the function's that receive the cursor position and control the camera into taskmgr. That section of my code is below.
taskMgr.add(self.get_mousepos, 'getmouse')
taskMgr.add(self.move_camera, 'movecam')
def get_mousepos(self,task):
if base.mouseWatcherNode.hasMouse():
self.camerax=base.mouseWatcherNode.getMouseX()
self.cameray=base.mouseWatcherNode.getMouseY()
return Task.cont
def move_camera(self,task):
if self.camerax>=.6:
self.camh-=.8
camera.setHpr(self.camh,self.camh1 ,0)
elif self.camerax<=-.6:
self.camh+=.8
camera.setHpr(self.camh,self.camh1 ,0)
elif self.cameray>=.6:
self.camh1+=.8
camera.setHpr(self.camh,self.camh1 ,0)
elif self.cameray<=-.6:
self.camh1-=.8
camera.setHpr(self.camh,self.camh1 ,0)
return Task.cont
Thanks in advance.

You should remove one indent in front of return Task.cont. Otherwise, the task will only continue as long as the mouse cursor is in the window; as soon as it leaves the window, hasMouse() will return False and the task will stop running.

Related

Mouse Listener on_move event

import pynput
import time
def poschange(x,y):
#print(f"{x},{y}")
print("poschange called")
pynput.mouse.Controller().position = (0,0)
def stop(key):
#print(key)
try:
if key.char == 'a':
print("stopped")
keyli.stop()
mouli.stop()
exit()
except:
pass
keyli = pynput.keyboard.Listener(on_press = stop)
keyli.start()
mouli = pynput.mouse.Listener(on_move = poschange)
mouli.start()
keyli.join()
mouli.join()
I just want to lock the mouse position when of the the mouse to (0,0) until I press the 'a' key on the keyboard and then the program terminates and i get control my mouse again.
To my knowledge in this code when ever i move the mouse the poschange() method is called and the mouse position must be set back to (0,0) and repeat again until the mouse listener thread is terminated, but it just works twice, the print statement in the poschange() function is printed twice in the console and then the mouse becomes sluggish and moves slowly, when I press 'a' the listeners must stop and program must terminate but it doesn't I have to manually do it and only the the mouse becomes fast and normal again. But when I remove the line pynput.mouse.Controller().position = (0,0) from the code the thing works as i intend, it prints the print statement "poschange called" every time I move the mouse and the program terminates as expected when I press the 'a' key.
can someone please tell me why and tell me whats wrong with this. Thanks in advance.
You've created a recursion with that call to .position as you move the cursor position in a callback triggered when a cursor changes its position.
I suppose you may get expected behavior by calling that
pynput.mouse.Controller().position = (0,0)
upon application start and by preventing the event propagation with:
mouli = pynput.mouse.Listener(on_move=poschange, suppress=True)

stop self.after when interrupt happens

I started coding snake in python 3. As GUI i use Tkinter.
I got a timer which waits for a second an then calls the method again. Well now my question is how to i stop the self.wait?
I know i could work around this pretty easily, but i had this problem already somewhere else, so it would be nice to know how i can stop this.
This is the method which moves the snake around. (Only the timer is critical). The timer is here so it moves every second.
def move_snake(self):
self.after(1000, self.move_snake)
# code goes on
Now if i change the direction (by pressing a button) i do following:
def change_direction(self, event):
self.pressed = event.keysym
self.move_snake()
If i do this this way the "old" timer still is active and therefore the method gets called multiple times (it adds an additional timer when you press an button).
It would be nice that just the latest timer is activated.
Do you need more information?
Assuming that move_snake uses self.pressed, you don't need to call move_snake inside of change_direction.
However, if you really want to stop the old loop and start a new loop, you can save the id that is returned from after and give that to after_cancel:
def move_snake(self):
self.after_id = self.after(1000, self.move_snake)
# code goes on
def change_direction(self, event):
self.pressed = event.keysym
# cancel the old loop
self.after_cancel(self.after_id)
# start a new loop
self.move_snake()

python curses while loop and timeout

I am having a hard time understanding the window.timeout() function. To be more specific, I am toying with a "snake" game in python:
s = curses.initscr()
curses.curs_set(0)
w = curses.newwin()
w.timeout(100)
while True:
move snake until it hits the wall
I understand that in this case, timeout(100) determines how fast the snake "moves", i.e. printing out new characters on the screen. However, I got stuck when I want to amend the code so that it waits until someone press "start". I wrote something like:
w.timeout(100)
while True:
if w.getch() is not start:
stay at the initial screen
else:
while True:
move the snake until it hits the wall
However, in this case, the timeout(100) seems to govern how long each time the program waits for w.getch(), not how long to wait between each time the snake moves. Also, I notice that in the first example, the timeout is declared at the top, outside the while loop. This looks weird to me because normally if I want to pause a while loop, I would put sleep() at the bottom inside the while loop.
If you want to pause between snake moves, you could use napms to wait a given number of milliseconds (and unlike sleep, does not interfere with screen updates). Setting w.timeout to 100 (milliseconds) is probably too long. If you're not concerned with reading function-keys, you could use nodelay to set the w.getch to non-blocking, relying on the napms to slow down the loop.
Regarding the followup comment: in ncurses, the wtimeout function sets a property of the window named _delay, which acts within the getch function, ultimately passed to a timed-wait function that would return early if there's data to be read.

Weird behavior - wxPython Events

I have this following piece of code. It is working sometimes, it is not the other time.
def OnReset(self, event):
self.reset_pump.Disable() # Disables the button so it is clicked
self.WriteToController([0x30],'GuiMsgIn') # Sends the reset command
self.flag_read.set()
self.tr.join()
time.sleep(2)
start = time.time()
self.offset_text_control.Clear()
print "Helloin reset"
self.gain_text_control.Clear()
self.firmware_version_text_control.Clear()
self.pump_rpm_text_control.Clear()
self.pressure_text_control.Clear()
self.last_error_text_control.Clear()
self.error_count_text_control.Clear()
self.pump_model_text_control.Clear()
self.pump_serial_number_text_control.Clear()
self.on_time_text_control.Clear()
self.job_on_time_text_control.Clear()
#self.MessageBox('Pump RESET going on Click OK \n')
# Having the above step is useful
print time.time() - start
#self.ser.close()
wx.CallLater(3000, self.CalledAfter, [event,])
def CalledAfter(self, event):
self.tr = threading.Thread(target=ReadData, name="ReadThread", args=(self.ser, self.flag_read))
self.tr.daemon = True
self.tr.start()
self.reset_pump.Enable()
What it does is When I click the Reset button on my GUI, it has to clear certain text fields on the GUI. It has to clear it, only after joining the self.tr thread.
Once it clears, it will execute the command wx.CallLater(3000, self.CalledAfter, [event,]). Which then starts a new thread again.
Apparently The .Clear() command is working very at a non consistent level, it is working some time, not working the other times, and working again.
Any idea why this might happen would be very helpful.
There seems to be a difference in the way SetValue and Clear update the windows. Calling SetValue("") seems to be a suitable workaround to this behavior.

Python thread executing function twice

Atm I'm working on a game using tkinter. I'm working on algorithm that moves enemies through the game map.
I will post only relevant lines, since the code is quiet hard-to-read.
I'm using class Timer imported from threading.
2 relevant functions are:
def add_enemies(self):
enemy = self.enemies.pop(0)
if enemy in '.':
Timer(1, self.add_enemies).start()
else:
self.move_enemy(enemy,set())
if not self.game_ended and self.enemies:
Timer(1, self.add_enemies).start()
def move_enemy(self, enemy, visited):
if type(enemy) == str:
if enemy in 'm':
enemy = Mongol(self.canvas, *self.start)
visited.add((enemy.x,enemy.y))
for move in (-1,0),(0,1),(1,0),(0,-1):
pos = (enemy.x + move[0], enemy.y+move[1])
if pos in self.way and pos not in visited:
print(pos)
enemy.move(*move)
enemy.take_shot(6)
visited.add(pos)
Timer(0.5, lambda: self.move_enemy(enemy, visited)).start()
This function should move the enemy, wait 0.5 second, then create a thread in which it recursively calls itself and moves the enemy again.
It might not be the best solution the create another thread inside the thread, but all other solutions made my GUI to freeze while executing the function.
Problem is, that Timer executes function move_enemy twice. Nothing else in the code can cause this problem.
Simple print test of enemy position shows this:
It simply moves the enemy twice, and increases its position twice as shown on the picture.
This is a wild guess, but substituting the enemy object with a new enemy object with a modified location in
Timer(0.5, lambda: self.move_enemy(enemy, visited)).start() might get the inbetween coordinates ((3,1),(5,1) and others). (If you do the same thing twice with the same input, you get two identical values.)
From the output I deduce: visited.add(pos) doesn't add positions to visited hence the if pos in self.way and pos not in visited: clause doesn't filter out already tested values (hence the (2,1)(2,1) printout). Try, if .append() works better.
I tried my best :D gl hf
Judging from the output, it looks like what's actually happening is that you were expecting things to execute in this order
print
move
print
move
print
move
print
move
....
but you failed to include enough synchronization and they are instead happening in this order:
print
print
move
move
print
print
move
move
....
It's not doing anything extra: it's just doing things not in the order you were hoping for.
Problem was, that tkinter is not thread safe hence it doesn't act deterministic.
I solved the problem by using Queue. My main thread, in which tkinter runs, periodically checks wheter or not it has something to draw.

Categories

Resources