Issue
I'd like to be able to show Xbox controller events on a very simple GUI using PyQt5 which was created using the QT Designer. I'm using xbox360controller Python package to communicate the controller with my Python interface. The following example code works as it should, and instead of printing the values I'd like to set the text on the only label on the GUI:
import signal
from xbox360controller import Xbox360Controller
def on_button_pressed(button):
print('Button {0} was pressed'.format(button.name))
def on_button_released(button):
print('Button {0} was released'.format(button.name))
def on_axis_moved(axis):
print('Axis {0} moved to {1} {2}'.format(axis.name, axis.x, axis.y))
try:
with Xbox360Controller(0, axis_threshold=0.2) as controller:
# Button A events
controller.button_a.when_pressed = on_button_pressed
controller.button_a.when_released = on_button_released
# Left and right axis move event
controller.axis_l.when_moved = on_axis_moved
controller.axis_r.when_moved = on_axis_moved
signal.pause()
except KeyboardInterrupt:
pass
This is the simple GUI:
My idea was something like this, but I'm very lost:
class MainWindow(Ui_MainWindow, Ui_MainClass):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.controller = Xbox360Controller(0, axis_threshold=0.2)
self.controller.button_a.when_pressed = on_button_pressed()
self.controller.button_a.when_released = on_button_released()
# Left and right axis move event
self.controller.axis_l.when_moved = on_axis_moved
self.controller.axis_r.when_moved = on_axis_moved
def on_button_pressed(self, button):
print('Button {0} was pressed'.format(button.name))
self.label_joy.setText(f'Button {0} was pressed'.format(button.name))
def on_button_released(self, button):
print('Button {0} was released'.format(button.name))
self.label_joy.setText(f'Button {0} was released'.format(button.name))
def on_axis_moved(self, axis):
print('Axis {0} moved to {1} {2}'.format(axis.name, axis.x, axis.y))
self.label_joy.setText('Axis {0} moved to {1} {2}'.format(axis.name, axis.x, axis.y))
if __name__ == "__main__":
app = QApplication([])
form = MainWindow()
form.show()
sys.exit(app.exec_())
(I'm using Ubuntu 18.04)
Solution
You have 2 errors:
The first is that
self.controller.button_a.when_pressed = on_button_pressed()
is equivalent tovalue = on_button_pressed()
self.controller.button_a.when_pressed = value
, so you have not assigned the callback but you have assigned None since that is what the function returns.Even if you correct the above, there is also another error: callbacks are invoked in a secondary thread, so in conclusion you would be modifying the GUI from another thread, which Qt prohibits. In this case the solution is to use the Qt signals to transmit the information since they are thread-safe.
import sys
from functools import cached_property
from PyQt5 import QtCore, QtWidgets
from xbox360controller import Xbox360Controller
from xbox360controller.controller import Button, Axis, RawAxis
class Controller(QtCore.QObject):
button_pressed = QtCore.pyqtSignal(Button)
button_released = QtCore.pyqtSignal(Button)
axis_moved = QtCore.pyqtSignal(object)
def __init__(self, parent=None):
super().__init__(parent)
try:
self.Xbox360_controller
except Exception as e:
print(e)
sys.exit(-1)
for button in self.Xbox360_controller.buttons:
button.when_pressed = self._on_button_pressed
button.when_released = self._on_button_released
for axis in self.Xbox360_controller.axes:
axis.when_moved = self._on_axis_moved
@cached_property
def Xbox360_controller(self):
return Xbox360Controller(0, axis_threshold=0.2)
def _on_button_pressed(self, button):
self.button_pressed.emit(button)
def _on_button_released(self, button):
self.button_released.emit(button)
def _on_axis_moved(self, axis):
self.axis_moved.emit(axis)
def close(self):
self.Xbox360Controller.close()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.label = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
self.setCentralWidget(self.label)
def handle_button_pressed(self, button):
self.label.setText(f"Button {button.name} was pressed")
def handle_button_released(self, button):
self.label.setText(f"Button {button.name} was released")
def handle_axis_moved(self, axis):
if isinstance(axis, Axis):
self.label.setText(f"Axis {axis.name} moved to {axis.x} {axis.y}")
elif isinstance(axis, RawAxis):
self.label.setText(f"Axis {axis.name} moved to {axis.value}")
def main():
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
controller = Controller()
controller.button_pressed.connect(w.handle_button_pressed)
controller.button_released.connect(w.handle_button_released)
controller.axis_moved.connect(w.handle_axis_moved)
ret = app.exec_()
controller.close()
sys.exit(ret)
if __name__ == "__main__":
main()
Answered By - eyllanesc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.