Search code examples
pythonpython-3.xpyqtpycharmpyqt4

How to create keyboard and mouse events with Pyqt widgets


I've just started doing Qt designing using python 3.x in Pycharms. I've watched a tuturial converting a .ui file to .py file. I'm good right now. I'm implementing a chat program.

Now, I want to type in TextEdit, linEdit but it dosen't wait for me type. I want to connect a keyboard or mouse event with them so when i click, it wait for me to type and when I hit Enter it stores the string.

The code between space and #here that's where I need help with. Basically I want to def methods for these events and calling them from them later.

My Ui_MainWindow class is as follows:

class Ui_MainWindow(QtGui.QMainWindow):

    def __init__(self):
        super(Ui_MainWindow,self).__init__()

        self.setObjectName(_fromUtf8("MainWindow"))
        self.resize(611, 487)
        self.setTabShape(QtGui.QTabWidget.Rounded)
        self.centralwidget = QtGui.QWidget(self)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.frame = QtGui.QFrame(self.centralwidget)
        self.frame.setGeometry(QtCore.QRect(10, 30, 591, 41))
        self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtGui.QFrame.Raised)
        self.frame.setObjectName(_fromUtf8("frame"))
        self.label = QtGui.QLabel(self.frame)
        self.label.setGeometry(QtCore.QRect(10, 10, 81, 17))
        self.label.setObjectName(_fromUtf8("label"))
        self.label_2 = QtGui.QLabel(self.frame)
        self.label_2.setGeometry(QtCore.QRect(320, 10, 66, 17))
        self.label_2.setObjectName(_fromUtf8("label_2"))
        #Here
        self.lineEdit = QtGui.QLineEdit(self.frame)
        self.lineEdit.setGeometry(QtCore.QRect(90, 10, 221, 21))
        self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
        #Here
        self.lineEdit_3 = QtGui.QLineEdit(self.frame)
        self.lineEdit_3.setGeometry(QtCore.QRect(360, 10, 221, 21))
        self.lineEdit_3.setObjectName(_fromUtf8("lineEdit_3"))

        self.frame_2 = QtGui.QFrame(self.centralwidget)
        self.frame_2.setGeometry(QtCore.QRect(10, 70, 291, 361))
        self.frame_2.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_2.setFrameShadow(QtGui.QFrame.Raised)
        self.frame_2.setObjectName(_fromUtf8("frame_2"))
        #Here
        self.textEdit = QtGui.QTextEdit(self.frame_2)
        self.textEdit.setGeometry(QtCore.QRect(10, 10, 271, 301))
        self.textEdit.setObjectName(_fromUtf8("textEdit"))

        self.pushButton_3 = QtGui.QPushButton(self.frame_2)
        self.pushButton_3.setGeometry(QtCore.QRect(10, 310, 161, 41))
        self.pushButton_3.setObjectName(_fromUtf8("pushButton_3"))
        self.pushButton_4 = QtGui.QPushButton(self.frame_2)
        self.pushButton_4.setGeometry(QtCore.QRect(180, 310, 98, 41))
        self.pushButton_4.setObjectName(_fromUtf8("pushButton_4"))
        self.pushButton_4.clicked.connect(self.clrLogs)         # Clear Logs from WidgetList by clicking
        self.verticalScrollBar = QtGui.QScrollBar(self.frame_2)
        self.verticalScrollBar.setGeometry(QtCore.QRect(260, 10, 20, 301))
        self.verticalScrollBar.setMinimumSize(QtCore.QSize(16, 301))
        self.verticalScrollBar.setCursor(QtGui.QCursor(QtCore.Qt.SizeVerCursor))
        self.verticalScrollBar.setAutoFillBackground(False)
        self.verticalScrollBar.setOrientation(QtCore.Qt.Vertical)
        self.verticalScrollBar.setInvertedAppearance(False)
        self.verticalScrollBar.setObjectName(_fromUtf8("verticalScrollBar"))

    ######################################################
        # Scroll to the bottom of chat windows
        # self.textEdit.verticalScrollBar().setValue(self.textEdit.verticalScrollBar().maximum)

        self.frame_3 = QtGui.QFrame(self.centralwidget)
        self.frame_3.setGeometry(QtCore.QRect(300, 70, 301, 361))
        self.frame_3.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_3.setFrameShadow(QtGui.QFrame.Raised)
        self.frame_3.setObjectName(_fromUtf8("frame_3"))
        self.listWidget = QtGui.QListWidget(self.frame_3)
        self.listWidget.setGeometry(QtCore.QRect(10, 10, 281, 341))
        self.listWidget.setObjectName(_fromUtf8("listWidget"))
        self.verticalScrollBar_2 = QtGui.QScrollBar(self.frame_3)
        self.verticalScrollBar_2.setGeometry(QtCore.QRect(270, 10, 21, 341))
        self.verticalScrollBar_2.setOrientation(QtCore.Qt.Vertical)
        self.verticalScrollBar_2.setObjectName(_fromUtf8("verticalScrollBar_2"))
        self.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(self)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 611, 25))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        self.menuMenu_Actions = QtGui.QMenu(self.menubar)
        self.menuMenu_Actions.setObjectName(_fromUtf8("menuMenu_Actions"))
        self.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(self)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        self.setStatusBar(self.statusbar)
        self.actionVersion = QtGui.QAction(self)
        self.actionVersion.setObjectName(_fromUtf8("actionVersion"))
        self.actionVersion.triggered.connect(Chat.app_ver)              # When submenu Action item Version is clicked
        self.actionExit = QtGui.QAction(self)
        self.actionExit.setObjectName(_fromUtf8("actionExit"))
        self.actionExit.triggered.connect(qApp.quit)                    #When submenu Action item Exit is clicked
        self.menuMenu_Actions.addAction(self.actionVersion)
        self.menuMenu_Actions.addAction(self.actionExit)
        self.menubar.addAction(self.menuMenu_Actions.menuAction())
        self.retranslateUi(self)
        QtCore.QMetaObject.connectSlotsByName(self)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", WindowTitle, None))
        self.setWindowIcon(QtGui.QIcon('chat_icon'))
        self.label.setText(_translate("MainWindow", "IP Address:", None))
        self.label_2.setText(_translate("MainWindow", "Nick:", None))
        self.pushButton_3.setText(_translate("MainWindow", "Send SMS", None))
        self.pushButton_4.setText(_translate("MainWindow", "Clear Logs", None))
        self.menuMenu_Actions.setTitle(_translate("MainWindow", "Menu Actions", None))
        self.actionVersion.setText(_translate("MainWindow", "Version", None))
        self.actionExit.setText(_translate("MainWindow", "Exit", None))

    def clrLogs(self):
        self.listWidget.clear()

enter image description here The big left is TextEdit and rightmost is listWidget. I want to type in TextEdit and stores it and and send this msg to Chatlog(ListWidget).


Solution

  • I would start saying that you have to care about the following things:

    1. Your keyboard UI, let's say a small prototype.
    2. Be aware of who is getting your keyboard focus.
    3. Take care of your filter to catch the events you need.
    4. Send the right response to the claimant object from your keyboard.

    I'd show your here some really nice example I've spent some considerable time to do and another one really simple and small. Since it's a quite amount of code I'd be leaving this small example and this more complex example from my github.

    You can clone or copy and paste the code, just be sure it comes with the right imports if you copy and paste.

    Edited[Added]

    Here is the small example catching the events from the receiver you pass, and posting the equivalent events:

    import sys
    
    from PyQt5.QtCore import QCoreApplication
    from PyQt5.QtCore import QEvent
    from PyQt5.QtCore import Qt
    from PyQt5.QtCore import pyqtSignal
    from PyQt5.QtGui import QKeyEvent
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtWidgets import QHBoxLayout
    from PyQt5.QtWidgets import QLineEdit
    from PyQt5.QtWidgets import QMainWindow
    from PyQt5.QtWidgets import QPushButton
    from PyQt5.QtWidgets import QWidget
    
    class MainWindow(QMainWindow):
    
        def __init__(self):
            super(MainWindow, self).__init__()
            self.central_widget = QWidget()
            self.cw_layout = QHBoxLayout()
            self.central_widget.setLayout(self.cw_layout)
            self.setCentralWidget(self.central_widget)
    
            self.line = LineEdit()
            self.kb = KeyBoard(self.line)
    
            self.cw_layout.addWidget(self.line)
    
            self.create_connections()
    
        def create_connections(self):
            self.line.signal_evoke_kb.connect(self.show_kb)
    
        def show_kb(self):
            if self.kb.isHidden():
                self.kb.show()
            else:
                self.kb.hide()
    
    
    class LineEdit(QLineEdit):
    
        signal_evoke_kb = pyqtSignal()
    
        def __init__(self):
            super(LineEdit, self).__init__()
    
        def mousePressEvent(self, QMouseEvent):
            super(LineEdit, self).mousePressEvent(QMouseEvent)
            self.signal_evoke_kb.emit()
    
    class Key(QPushButton):
    
        def __init__(self, name, event, receiver):
            super(Key, self).__init__()
            self.name = name
            self.event = event
            self.setText(name)
    
    
    class KeyBoard(QWidget):
    
        def __init__(self, receiver):
            super(KeyBoard, self).__init__()
            self.receiver = receiver
            self.layout = QHBoxLayout()
            self.keys = ['q','w','e','r','t','y']
            self.dict_keys ={'q':Qt.Key_Q,'w':Qt.Key_W,'e':Qt.Key_E,'r':Qt.Key_R,'t':Qt.Key_T,'y':Qt.Key_Y,}
            for key in self.keys:
                key_keyboard = Key(key,self.dict_keys[key],receiver)
                key_keyboard.clicked.connect(self.key_pressed)
                self.layout.addWidget(key_keyboard)
            self.setLayout(self.layout)
    
        def key_pressed(self):
            try:
                event = QKeyEvent(QEvent.KeyPress, self.sender().event, Qt.NoModifier,
                                  self.sender().name, False)
                QCoreApplication.postEvent(self.receiver, event)
            except Exception as e:
                print(e)
    
        def keyPressEvent(self, evt):
            event = QKeyEvent(QEvent.KeyPress, evt.key(), evt.modifiers(),
                              evt.text(), False)
            QCoreApplication.postEvent(self.receiver, event)
            evt.ignore()
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        mw = MainWindow()
        mw.show()
        sys.exit(app.exec_())
    

    In this way you can personalize your key since your have your own Key, and organize it better when you need upper case and all else. If you are willing to do that I'd strongly recommend looking at the more complete example I linked before.