OK, I have a theory about what the issue is and a horrible kludge solution that works, barely.
There is a pyglet joystick.py demo available in the bitbucket repository, code copied at the bottom of this post. You can run this from the psychopy python install and it works just fine, so we know pyglet can talk to a joystick in principle.
However, the way this demo seems to work is that it’s not worrying about event dispatchers at all, it’s just checking the joystick’s status every time the window’s on_draw event occurs. That doesn’t work when going through a psychopy window object. I tried making a win.winHandle.event on_draw handler and it never trips, even when win.flip() is called. If there’s another way to establish a handler for that it might work, but I have no idea.
I can find no working example of anyone using the joystick events anywhere on the internet. So, it is possible that the joystick events don’t work, in which case our only real problem is that something about the way the pyglet window is implemented means that it’s not able to properly update and check the current state of the joystick. That requires a much deeper understanding of psychopy’s window class than I have, I fear.
On the other hand, I can create an awful kluge solution that at least gets the psychopy joystick demo to work, albiet without using the psychopy joystick class. Basically, you just do joystick.close and joystick.open on every screen refresh (just in your main presentation loop before win.flip), and get the values of each of the axes/buttons directly from the pyglet object that way. It’s ugly and probably horribly inefficient in some way (though I haven’t seen any obvious signs of memory or processor load), but it does work.
#!/usr/bin/env python
'''
'''
__docformat__ = 'restructuredtext'
__version__ = '$Id: $'
import pyglet
from pyglet.gl import *
joysticks = pyglet.input.get_joysticks()
assert joysticks, 'No joystick device is connected'
joystick = joysticks[0]
joystick.open()
window = pyglet.window.Window()
@window.event
def on_draw():
x = (0.8*joystick.x + 1) * window.width / 2
y = (-0.8*joystick.y + 1) * window.height / 2
z = joystick.z
angle = joystick.rz * 180
# Axes
glClear(GL_COLOR_BUFFER_BIT)
glColor3f(1, 0, 0)
glLoadIdentity()
glTranslatef(x, y, 0)
glScalef(1 + z, 1 + z, 1 + z)
glRotatef(-angle, 0, 0, 1)
glBegin(GL_TRIANGLES)
glVertex2f(-10, 0)
glVertex2f(0, 13)
glVertex2f(10, 0)
glEnd()
# Buttons
glLoadIdentity()
x = 10
y = 10
glPointSize(5)
glBegin(GL_POINTS)
for button in joystick.buttons:
if button:
glVertex2f(x, y)
x += 20
glEnd()
# Hat
glColor3f(0, 0, 1)
x = window.width / 2
y = window.height / 2
glBegin(GL_POINTS)
glVertex2f(x + joystick.hat_x * 50, y + joystick.hat_y * 50)
glEnd()
pyglet.clock.schedule(lambda dt: None)
pyglet.app.run()