与 Xbox 控制器的 GUI 交互
GUI Interaction with Xbox Controller
我希望能够使用使用 QT Designer 创建的 PyQt5 在非常简单的 GUI 上显示 Xbox 控制器事件。
我正在使用 xbox360controller Python 包将控制器与我的 Python 接口进行通信。以下示例代码可以正常工作,而不是打印值我想在 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
这是简单的 GUI:
我的想法是这样的,但是我很迷茫:
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_())
(我正在使用 Ubuntu 18.04)
您有 2 个错误:
首先是self.controller.button_a.when_pressed = on_button_pressed()
等同于value = on_button_pressed()
self.controller.button_a.when_pressed = value
,所以你没有赋值回调但是赋值了None因为这就是函数 returns.
即使您更正了上述内容,也会出现另一个错误:回调是在辅助线程中调用的,因此总而言之,您会从另一个线程修改 GUI,这是 Qt 禁止的。在这种情况下,解决方案是使用 Qt 信号来传输信息,因为它们是线程安全的。
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()
我希望能够使用使用 QT Designer 创建的 PyQt5 在非常简单的 GUI 上显示 Xbox 控制器事件。 我正在使用 xbox360controller Python 包将控制器与我的 Python 接口进行通信。以下示例代码可以正常工作,而不是打印值我想在 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
这是简单的 GUI:
我的想法是这样的,但是我很迷茫:
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_())
(我正在使用 Ubuntu 18.04)
您有 2 个错误:
首先是
self.controller.button_a.when_pressed = on_button_pressed()
等同于value = on_button_pressed()
self.controller.button_a.when_pressed = value
,所以你没有赋值回调但是赋值了None因为这就是函数 returns.即使您更正了上述内容,也会出现另一个错误:回调是在辅助线程中调用的,因此总而言之,您会从另一个线程修改 GUI,这是 Qt 禁止的。在这种情况下,解决方案是使用 Qt 信号来传输信息,因为它们是线程安全的。
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()