i am trying to write code which take input from 4x4 keypad(Mechanical) using pad4pi module with pyqt5 based GUI application.
when i try to click button it work properly but when i try to genrate some event i get error message:
QObject::startTimer: Timers can only be used with threads started with QThread
class DigitalClock(QWidget,QThread):
def __init__(self):
super().__init__()
SetupKeyboard.keypad.registerKeyPressHandler(self.printKey)
self.setWindowTitle("OM SAI RAM")
self.showFullScreen()
#self.setCursor(Qt.BlankCursor)
button = QPushButton("Click", self)
button.clicked.connect(self.change)
button.move(10,10)
button.show()
def change(self):
self.newpage = Authentication_page()
self.close()
def printKey(self, key):
if key == 'A':
self.newpage = Authentication_page()
self.close()
class Authentication_page(QWidget):
"""
Class to validate authentication.
"""
def __init__(self):
super().__init__()
self.showFullScreen()
self.maindesign()
def maindesign(self):
"""Method to design main page"""
####Label###
self.admin_header = QLabel("Admin Panel", self)
self.admin_header.setStyleSheet("font-size:40px")
self.admin_header.move(130, 10)
self.admin_header.show()
when i click button code work fine but when i push mechanical button, code freeze with error message.
The handler assigned by registerKeyPressHandler is executed in the thread where the keys are monitored, in your case printKey is executed in a secondary thread where you try to create a widget but that is forbidden by Qt.
The solution is to create a QObject and emit a signal (since the signals are thread-safe) by sending the key pressed, then connect to a slot where you receive the information:
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject
from PyQt5.QtWidgets import QLabel, QPushButton, QWidget
from pad4pi import rpi_gpio
class KeypadManager(QObject):
keyPressed = pyqtSignal(object)
def __init__(self, parent=None):
super().__init__(parent)
factory = rpi_gpio.KeypadFactory()
self._keypad = factory.create_4_by_4_keypad()
self._keypad.registerKeyPressHandler(self._key_press_handler)
def _key_press_handler(self, key):
self.keyPressed.emit(key)
class DigitalClock(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("OM SAI RAM")
self._keypad_manager = KeypadManager()
self._keypad_manager.keyPressed.connect(self.printKey)
# self.setCursor(Qt.BlankCursor)
button = QPushButton("Click", self)
button.clicked.connect(self.show_authentication_page)
button.move(10, 10)
self.showFullScreen()
def show_authentication_page(self):
self.newpage = Authentication_page()
self.close()
@pyqtSlot(object)
def printKey(self, key):
if key == "A":
self.show_authentication_page()
class Authentication_page(QWidget):
# ...