pythonpyqt5keyboard-input

How do I make this PyQt5 character move on arrow key input?


I'm making a simple PyQt5 application and am curious about how to make the circle move with the arrow keys. I want it to move 5 pixels on every press.

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(500, 500)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.coords = QtWidgets.QPushButton(self.centralwidget)
        self.coords.setGeometry(QtCore.QRect(0, 0, 75, 23))
        self.coords.setObjectName("coords")
        self.mover = QtWidgets.QLabel(self.centralwidget)
        self.mover.setGeometry(QtCore.QRect(200, 200, 50, 50))
        self.mover.setText("")
        self.mover.setPixmap(QtGui.QPixmap("mover.png"))
        self.mover.setObjectName("mover")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 500, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "DYM"))
        self.coords.setText(_translate("MainWindow", "Coords"))


if __name__ == "__main__":
     # Snip

Solution

  • You shouldn't edit nor use the code provided by pyuic from Designer files directly. Instead, you have to create your own code that uses that code as explained here.

    A very simple and limited implementation (which doesn't use Designer .ui files) looks like this:

    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class Mover(QtWidgets.QLabel):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setGeometry(0, 0, 500, 21)
            self.setPixmap(QtGui.QPixmap('mover.png'))
    
        def keyPressEvent(self, event):
            if event.key() == QtCore.Qt.Key_Up:
                self.move(self.x(), self.y() - 5)
            elif event.key() == QtCore.Qt.Key_Down:
                self.move(self.x(), self.y() + 5)
            elif event.key() == QtCore.Qt.Key_Left:
                self.move(self.x() - 5, self.y())
            elif event.key() == QtCore.Qt.Key_Right:
                self.move(self.x() + 5, self.y())
            else:
                QtWidgets.QLabel.keyPressEvent(self, event)
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self):
            QtWidgets.QMainWindow.__init__(self)
            centralWidget = QtWidgets.QWidget()
            self.setCentralWidget(centralWidget)
            self.mover = Mover(centralWidget)
            self.mover.setFocus()
    
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        window = MainWindow()
        window.show()
        sys.exit(app.exec_())
    

    There are some drawback about this, though: I had to setFocus to the widget in order to make it capture key press events, which means that if you have any other widget that interacts with key events (such as a QLineEdit) and it gets focus, your "mover" widget won't move anymore until it receives its focus back (which is usually achieved by means of a QWidget.setFocusPolicy()).