How to make 2 event loops work together - Tkinter and PyPS4Controller

Viewed 110

I am currently on a project where I have to use Tkinter to make a game, and I would like to be able to move stuff on a canvas in Tkinter (like moving a circle with a ps4 controller's joystick for example). In this project, it is mandatory that I use tkinter to make the UI of the game, so I needed a python module to handle my PS4 controller. I chose to go for PyPS4Controller

But there are two event loops : tkinter.mainloop() from the Tkinter module and controller.listen() from the PyPS4Controller module.

I'm really lost. Your help is much appreciated. Thanks ! ;D

Edit:

Further down is the code I came up with to showcase my problem, along with the live result in the console. Even with the pyPS4Controller event loop inside a thread, my program is still stuck, waiting for an input

import tkinter as tk
from pyPS4Controller.controller import Controller
import threading

# The list the will contain all events related to the PS4 controller
eventQueue = []

# Function to launch a thread, for appending
# user inputs to the eventQueue
class getPS4Input(threading.Thread):
    def __init__(self, controller):
        threading.Thread.__init__(self)
        self.controller = controller

    def start(self):
        # No more visible loop, it is already in controller.listen
        self.controller.listen()

# All events that are related to the controller are handled by
# this class (a pyPS4Controller module specific class)
class MyController(Controller):

    def __init__(self, **kwargs):
        Controller.__init__(self, **kwargs)

    # On the X button is pressed
    def on_R3_right(self, value):
        # Append the new value for the xaxis along with a tag used to 
        # understand what the value is for
        eventQueue.append(('R3_xaxis', value))
      
    # Other events (none here for exemple purposes)

# The object that needs to be moved around
# Here its purpose is to have a way to know if the R3_xaxis value
# has been modified
class ball():
    def __init__(self):
        self.R3_xaxis = 0
    
    def show(self):
        print(self.R3_xaxis)

# The function to be called periodically by tkinter
# to update here just the R3_xaxis, example purposes
def checkEventQueue(ball):
    while (eventQueue != []):
         # Get new events until there is none left
        [eventTag, eventValue] = eventQueue.pop()
        # Update the R3_xaxis value for the object ball
        if (eventTag == 'R3_xaxis'):
            ball.R3_xaxis = eventValue
    # Repeat the check every 200 ms
    root.after(200, lambda:checkEventQueue(ball))

# The controller, view as an object by Python
controller = MyController(interface="/dev/input/js0", connecting_using_ds4drv=False) 

root = tk.Tk()

# A button, just to see if the tkinter loop is running correctly (not stopped)
tk.Button(root, text ="Hello", command=lambda:print("Bouton TK appuyé")).pack()

# Initialize the thread to get user inputs
t = getPS4Input(controller)
t.start()

# Check for user inputs entered in the last 200 ms
root.after(200, lambda:checkEventQueue(ball))

# The Tk event loop
tk.mainloop()

Here is the live program result, as you can see, it is waiting for an input (actually for a controller to be connected, but you see my point, I don't want to be stuck here, I want to get to the Tk mainloop)

Waiting for interface: /dev/input/js0 to become available . . .

Thanks for the help.

0 Answers
Related